/* =========================================================================
   Design-Fundament 2026-07-29 — Owner-Referenzen vom 28.07. («exakt
   nachbauen», docs/design/ZIELBILD-2026-07-28.md). EINE Erscheinung für
   alle 53 Bildschirme: sehr dunkler, leicht blaugrüner Grund · Karten eine
   Stufe heller MIT feiner Hairline · viel Luft · Radius 14 · EIN Akzent
   Türkis für Aktion, aktiven Zustand, Balken und Positivwerte · Bernstein
   für Warnung, Rot sparsam für Fehler.

   Warum als Token-Schicht und nicht Bildschirm für Bildschirm: die
   Klassenverträge (.panel, .panel-row*, .stat*, .field, .primary-btn,
   .badge, .sl-badge*, .kp-*, .vt-*, .jetzt-*, .lx-*) stehen seit 27
   Iterationen. Wer die Tokens und die Kernbausteine umkleidet, kippt die
   ganze App in einem Zug — ohne 53 Einzelkorrekturen und ohne einen
   einzigen Quelltest zu brechen.

   Gebaut auf «Precision Ink» (DESIGN.md): Struktur, Dichte, Motion und
   Touch-Regeln bleiben. Ersetzt sind Farbe, Form und die Tiefen-Idee —
   statt Innen-Glanz + Ambient-Schatten trägt jetzt die Hairline die Kante.
   Skip-Zone: nur der Token-Block trägt Roh-Hexes.
   ========================================================================= */
:root {
  color-scheme: dark;
  /* Ink-Leiter (Flächen, von tief nach erhaben).
     1:1-HUELLE (Owner-Regel 02.08., Memory referenz-ist-massstab-nicht-soll):
     alle Werte hier sind aus dem Referenzbild 13_25_27 GEMESSEN
     (scripts/_referenz_farben_messen.mjs, 3×3-Mittel) — das Fundament ist
     BLAU-schwarz (Blauanteil ueber Gruen), nicht tuerkis-neutral. Wer hier
     aendert, misst zuerst. */
  /* DIE FARBWELT DER REFERENZ (Owner 03.09.: «das UI, die Farbe … falsch
     verstanden»). Gemessen an docs/design/referenzen/konfigurator-greenfield-
     2026-08-10 (2800 px, Bild 02/09/12/14): Grund #070a0e · Panel #080b0f ·
     Karte #0e141a · erhaben #12191f · Feld #080d12 · Haarlinie #2c323c auf
     #080b0f · Text #f0f6fc/#91a3b5/#8795a3 · gewählter Rand #9ccfff ·
     Tönung #162b3f · Hauptknopf #dcecff · Startklar #a4d7c5 · fehlt #d8ba83.
     Blauschwarz und Eisblau statt Petrol und Türkis; Ecken ~2 px statt
     Pillen. Türkis #13c5c0 war der Akzent bis v393 — Referenz (10.08.) und
     Owner-Wort (02./03.09.) sind neuer als DESIGN.md/EINHEIT §1.3. */
  --canvas-background: radial-gradient(120% 90% at 55% 42%, #0b131c 0%, #04111a 48%, #020a11 80%, #01070c 100%);
  --work-heading-background: linear-gradient(180deg, #0c1420, #0a1016);
  --bg: #070a0e;
  --surface: #0e141a;        /* Karten/Panels — gemessen Wahlkarte Bild 02 */
  --surface-1: #080b0f;      /* eingelassen — gemessen Panel/Band Bild 02/09 */
  --surface-inset: #080d12;  /* Formularfelder — gemessen Eingabefeld Bild 02 */
  --surface-2: #12191f;      /* erhaben — gemessen «Zurück»-Knopf Bild 09 */
  --surface-3: #182027;      /* Hover-/Aktiv-Fläche */
  --surface-hover: #101820;
  /* Hairlines: die Kante der Karte UND der Trenner in Listen — kuehl-blau */
  --border: rgba(140, 168, 196, .19);      /* #2c323c auf #080b0f, Bild 09 */
  --line-strong: rgba(140, 168, 196, .36);
  /* DESIGN.md nennt die Tokens --hairline/--hairline-strong; die Implementierung
     taufte sie --border/--line-strong. ~26 Verwendungen lasen die DESIGN.md-Namen
     ins Leere (var() undefiniert ⇒ Deklaration invalid ⇒ Linie fehlte komplett,
     auch die Organigramm-Äste). Alias statt Umbenennung: löst am Element auf. */
  --hairline: var(--border);
  --hairline-strong: var(--line-strong);
  /* Alias-Kanal für die G-01-/E-0x-Blöcke (Benachrichtigungen, Freigaben,
     Regeln, Schulden, Belege). Sie lasen --panel/--line/--muted/--hover/
     --danger/--panel-2, die es NIE gab: jede dieser 40 Deklarationen fiel
     auf ihren eingebauten Roh-Hex zurück und stand damit ausserhalb jeder
     Farbwahrheit. Hier definiert = sie erben ab sofort mit. */
  --panel: var(--surface);
  --panel-2: var(--surface-inset);
  --line: var(--border);
  --muted: var(--text-secondary);
  --hover: var(--surface-hover);
  --danger: var(--bad);
  --danger-rgb: var(--bad-rgb);
  /* Text — kuehl-weiss statt gruenstichig, folgt der blauen 1:1-Huelle */
  --text: #d8e2ec;           /* gemessen Kartentitel Bild 02 */
  --text-primary: #f0f6fc;   /* gemessen Frage-Titel Bild 02 */
  --text-secondary: #91a3b5; /* gemessen Sektions-Etikett Bild 02 */
  --text-tertiary: #8795a3;  /* gemessen Helfersatz Bild 02; >=4.5:1 auf --surface */
  /* Marken-Türkis (NUR Interaktion + Positivwerte: Aktion, Selektion, Fokus,
     aktiver Zustand, Fortschritt) — gemessen am Referenz-Fortschrittsbalken */
  --accent-rgb: 156, 207, 255;
  --accent: #9ccfff;         /* gewählter Rand / aktives Wort — gemessen Bild 02 */
  --accent-deep: #6fa8dc;
  --accent-hover: #b7dcff;   /* Schieber-Knopf Bild 09 */
  --accent-strong: #cbe8ff;  /* heller Akzent-Text auf Soft-Flächen — Häkchen-Kreis Bild 02 */
  --accent-bright: #e7f3ff;  /* gewähltes Segment TAGE, Bild 09 */
  --accent-fill: #dcecff;    /* die gefüllte Hauptaktion — gemessen Bild 14 */
  --on-accent: #0c161e;      /* Wort AUF der eishellen Fläche — gemessen Bild 02 */
  /* Fläche und Kante des Akzents kommen AUS dem Akzent. Bis 03.08. trugen
     beide noch das Türkis von vor dem Hüllen-Pass (45, 212, 191) — zwei
     Türkis-Wahrheiten in einer Datei, verteilt über 80 Regeln. Wer den
     Akzent misst und nachführt, hätte 80 Flächen unbemerkt zurückgelassen. */
  /* «gewählt/hier» ist eine BLAUE Tönung, kein aufgehellter Akzent:
     gemessen #162b3f auf #0e141a (Bild 02) = rgba(60,140,230,.2). */
  --accent-tint-rgb: 60, 140, 230;
  --accent-soft: rgba(var(--accent-tint-rgb), .20);
  --accent-line: rgba(var(--accent-rgb), .55);
  /* Magenta — nur Marken-Highlight, nie Funktionsfarbe */
  --magenta: #ef5aa4;
  --magenta-rgb: 239, 90, 164;
  /* Status-Semantik. Positiv teilt sich den Akzent (ZIELBILD: EIN Akzent),
     Warnung ist Bernstein, Fehler bleibt Rot und bleibt selten.
     Die *-rgb-Kanäle tragen die Soft-Flächen: vorher standen dieselben
     Farben als ~45 rohe rgba()-Tripel im ganzen Blatt. */
  /* Stand-Farben gemessen: «Startklar» #a4d7c5/Rand #283f3d (Bild 02), «Auswahl
     fehlt» #d8ba83/Rand #4c402b (Bild 12). Grün ist Mint, nicht Türkis. */
  --good: #6fcfae;  --good-strong: #a4d7c5;  --good-deep: #3f9d80;  --good-rgb: 111, 207, 174;
  --warn: #d8ba83;  --warn-strong: #e9d2a6;  --warn-deep: #a88a55;  --warn-rgb: 216, 186, 131;
  --bad: #f2686f;   --bad-strong: #ff9ea3;   --bad-deep: #b8344f;   --bad-rgb: 242, 104, 111;
  --bad-soft: rgba(242, 104, 111, .14);   /* Fläche, nicht Text (app-lock) */
  --info-strong: #93c5fd;  --info-muted: #6989c9;  --info-rgb: 96, 165, 250;
  /* Prioritäten (Leads) — dieselbe Semantik, nicht eine zweite Palette */
  --high: var(--good);
  --medium: var(--warn);
  --low: var(--bad);
  /* Regionen (Datenfarben — unangetastet) */
  --zuerich: #3b82f6;  --zuerich-text: #93c5fd;
  --aarau: #8b5cf6;    --aarau-text: #c4b5fd;
  --bern: #06b6d4;
  --solothurn: #f97316;
  --luzern: #ec4899;   --luzern-text: #f9a8d4;
  --neutral-badge: #1d2b33;
  /* DIE BEREICHSFARBEN — hierher gezogen am 25.08.2026, aus zwei Flaechen
     befreit. Sie waren entschieden und wirkten trotzdem fast nirgends:
     die sieben Sach-Toene standen in `.gz` (docs/design/patch-zentrale.css),
     die acht Bereichs-Toene in `.bs` (docs/design/patch-ortsschild.css) —
     also nur INNERHALB der Zentrale und INNERHALB des Bereichs-Starts.
     GEMESSEN ueber 29 gebaute Flaechen bei 1400px: auf 21 von ihnen loeste
     `--gz-feld` auf gar nichts auf, obwohl 36 Flaechen-Dateien `gz-ic`- oder
     `data-bereich`-Traeger ausgeben. `--gz-buchhaltung` heisst «Gold — Geld,
     Rechnung, Schuld» und erschien auf keiner einzigen Geld-Flaeche.
     Ein Token, das an seiner Flaeche angebunden ist, ist kein Farbcode,
     sondern eine Dekoration dieser einen Flaeche.

     WERTE UNVERAENDERT uebernommen, keine neue Farbe erfunden. Die beiden
     Tabellen bleiben getrennt, weil sie zwei verschiedene Fragen beantworten:
     `--gz-*` faerbt die SACHE (eine Offerte, eine Rechnung, ein Lead),
     `--bs-*` faerbt den BEREICH (wo bin ich). Wo beide dasselbe meinen,
     tragen sie denselben Wert — nachgerechnet: verkauf/partner/finanzen.
     EINHEIT §1.3 bleibt die Grenze: NUR Soft-Feld hinter Symbol und Kurve,
     nie Flaeche, nie Text, nie Knopf. Tuerkis bleibt der EINE Akzent. */
  --gz-verkauf:     122, 178, 255;   /* Blau      — Angebot, Offerte, Abschluss */
  --gz-leads:       176, 142, 255;   /* Violett   — Pool, Anrufe, Team-Tag      */
  --gz-buchhaltung: 236, 190, 112;   /* Gold      — Geld, Rechnung, Schuld      */
  --gz-partner:     112, 208, 154;   /* Grün      — Standorte und ihre Screens  */
  --gz-screens:     240, 138, 186;   /* Rosa      — Screens, Standorte, Material */
  --gz-kunden:      246, 155, 118;   /* Koralle   — Kundinnen und Kunden        */
  --gz-missionen:   168, 190, 205;   /* Stahl     — der Betrieb selbst          */
  --bs-zentrale:          168, 190, 205;   /* Stahl    — der Betrieb selbst   */
  --bs-akquise:           176, 142, 255;   /* Violett  — Pool, Anrufe         */
  --bs-verkauf:           122, 178, 255;   /* Blau     — Offerte, Abschluss   */
  --bs-betrieb:           240, 138, 186;   /* Rosa     — Screens, Standorte   */
  --bs-standortbetreiber: 112, 208, 154;   /* Grün     — Betreiber            */
  --bs-vertriebspartner:  246, 155, 118;   /* Koralle  — der externe Kanal    */
  --bs-team:              145, 205, 224;   /* Eisblau  — die eigenen Leute    */
  --bs-finanzen:          236, 190, 112;   /* Gold     — Geld                 */
  /* Tint-Kanal: Overlay-Affordanzen als rgba(var(--tint-rgb), α) —
     dunkel weiss, hell dunkles Ink. EIN Kanal, gleiche Alphas. */
  --tint-rgb: 190, 225, 225;
  --topbar-bg: rgba(7, 12, 14, .88);
  /* Form & Tiefe: die Hairline trägt die Kante, der Schatten hebt nur, was
     wirklich schwebt (Popover, Modal, Toast). Radius 14 wie in der Referenz. */
  /* Ecken fast eckig (Referenz: ~2 px) — keine Pillen, keine 14-px-Kacheln. */
  --radius-card: 12px;
  --radius-button: 8px;
  --radius-badge: 4px;
  --shadow-sm: 0 1px 2px rgba(2, 8, 9, .30);
  --shadow-md: 0 6px 18px rgba(2, 8, 9, .40), 0 1px 2px rgba(2, 8, 9, .30);
  --shadow-lg: 0 18px 48px rgba(2, 8, 9, .55), 0 2px 6px rgba(2, 8, 9, .35);
  /* Typo: Inter (self-hosted/DSG); Mono NUR für echte Datenwerte */
  --font-mono: ui-monospace, 'SF Mono', SFMono-Regular, Menlo, Consolas, 'Liberation Mono', monospace;
  /* Motion: Zustand, nie Deko — out-quint, kurz */
  --ease: cubic-bezier(.22, 1, .36, 1);
  --dur-fast: 120ms;
  --dur: 180ms;
  --dur-slow: 240ms;
  --transition: var(--dur-fast) var(--ease);
  --header-height: 84px;
  /* PWA Safe-Area (Notch/Home-Indicator im Standalone) */
  --sat: env(safe-area-inset-top, 0px);
  --sab: env(safe-area-inset-bottom, 0px);
}

/* =========================================================================
   BODEN- UND KOPF-GEOMETRIE — EIN Höhensystem statt geratener Zahlen
   (Owner-Video-Audit 09.08., Klasse 6 · Paket P1)

   Am Handy liegen bis zu drei Dinge fix über dem Seitenende: die Leiste am
   Daumen, eine flächeneigene Fixleiste (Offerten-Total) und der schwebende
   «+»-Knopf. Bis 09.08. RIET jede Fläche ihren Bodenabstand selbst — acht
   Stellen mit acht verschiedenen Zahlen (70 · 80 · 84 · 112 · 140 px), und am
   Handy gewann in der Kaskade ausgerechnet die kleinste. Ergebnis im Video:
   der Plus-Knopf lag auf «Alle →», auf «Erledigt», auf Formularfeldern; unter
   den Fixleisten verschwand die letzte Zeile jeder Liste (c1 B4/B10/B13,
   c2 B5, c5 B2/B18, c6 B2/B16/B17/B30).

   DIE REGEL AB HIER: Eine Leiste SETZT ihre Höhe, eine Fläche LIEST sie.
   Wer eine neue Fixleiste baut, setzt --leiste-h und ist fertig.

     --nav-h     Leiste am Daumen (nur Handy, nur wenn sie wirklich da ist)
     --leiste-h  flächeneigene Fixleiste ÜBER der Daumenleiste
     --fab-h     Platz, den der schwebende «+» über dem Boden braucht
     --kopf-h    Höhe der klebenden Kopfzeile (die Reiterzeile liest sie)
     --fuss-h    Fuss einer Fläche, die selbst schon bis zum Bildschirmende
                 reicht (Cockpit): er verdrängt Meldungen, aber KEINEN
                 Seiteninhalt — darum steht er nicht in `--boden-abstand`
     --boden-h        was unten wirklich fest belegt ist (Leiste + sichere Zone)
     --boden-abstand  was ein Scroll-Container darunter freihalten MUSS

   Die Zusammenrechnung steht auf `body` und NICHT auf `:root`, weil jeder
   Zustand (has-quick-create, lx-pool, lx-werkflaeche, so-editor-open) an der
   Körper-Klasse hängt: nur wenn Teil und Summe auf demselben Element stehen,
   rechnet der Browser die Summe mit dem überschriebenen Teil neu.

   --vv-* schreibt der Beobachter des sichtbaren Fensters
   (public/src/utils/viewport.js). Ohne ihn bleiben sie 0 — dann verhält sich
   alles exakt wie vorher.
   ========================================================================= */
body {
  --nav-h: 0px;
  --leiste-h: 0px;
  --fab-h: 0px;
  --kopf-h: 0px;
  --fuss-h: 0px;
  --boden-h: calc(var(--nav-h) + var(--sab));
  --boden-abstand: calc(var(--boden-h) + var(--leiste-h) + var(--fab-h));
}
/* Owner14.09.: warm sand is an additional app appearance. Semantic roles,
   spacing, permissions and document paper remain shared with the dark mode. */
:root[data-theme="light"] {
  color-scheme: light;
  --bg: #f1ede5;
  --surface: #faf7f0;
  --surface-1: #f5f0e7;
  --surface-inset: #fdfaf4;
  --surface-2: #e9e2d6;
  --surface-3: #dfd5c5;
  --surface-hover: #ede7db;
  --border: rgba(78, 66, 47, .16);
  --line-strong: rgba(78, 66, 47, .37);
  --control-border: #877f71;
  --text: #38372f;
  --text-primary: #292d29;
  --text-secondary: #635d51;
  --text-tertiary: #6b6255;
  --accent-rgb: 26, 105, 87;
  --accent: #1a6957;
  --accent-deep: #195647;
  --accent-hover: #175544;
  --accent-strong: #195647;
  --accent-bright: #154b40;
  --accent-fill: #1a6957;
  --on-accent: #fcf8ef;
  --accent-tint-rgb: 26, 105, 87;
  --accent-soft: rgba(var(--accent-tint-rgb), .09);
  --accent-line: rgba(var(--accent-rgb), .58);
  --magenta: #973460; --magenta-rgb: 151, 52, 96;
  --good: #25674f; --good-strong: #205b47; --good-deep: #184d3b; --good-rgb: 37, 103, 79;
  --warn: #80550c; --warn-strong: #714600; --warn-deep: #674002; --warn-rgb: 128, 85, 12;
  --bad: #ac3239; --bad-strong: #982c34; --bad-deep: #87262d; --bad-rgb: 172, 50, 57;
  --bad-soft: rgba(var(--bad-rgb), .08);
  --info-strong: #315b91; --info-muted: #3c5c84; --info-rgb: 49, 91, 145;
  --zuerich: #315b91; --zuerich-text: #315b91;
  --aarau: #735298; --aarau-text: #735298;
  --bern: #166877;
  --solothurn: #8d491f;
  --luzern: #984b70; --luzern-text: #984b70;
  --neutral-badge: #e5dccd;
  --gz-verkauf: 49, 91, 145;
  --gz-leads: 115, 82, 152;
  --gz-buchhaltung: 128, 85, 12;
  --gz-partner: 37, 103, 79;
  --gz-screens: 152, 75, 112;
  --gz-kunden: 141, 73, 31;
  --gz-missionen: 71, 92, 103;
  --bs-zentrale: 71, 92, 103;
  --bs-akquise: 115, 82, 152;
  --bs-verkauf: 49, 91, 145;
  --bs-betrieb: 152, 75, 112;
  --bs-standortbetreiber: 37, 103, 79;
  --bs-vertriebspartner: 141, 73, 31;
  --bs-team: 22, 104, 119;
  --bs-finanzen: 128, 85, 12;
  --tint-rgb: 66, 56, 43;
  --topbar-bg: rgba(241, 237, 229, .96);
  --shadow-sm: 0 1px 2px rgba(0, 0, 0, .09);
  --shadow-md: 0 6px 18px rgba(0, 0, 0, .12), 0 1px 2px rgba(0, 0, 0, .09);
  --shadow-lg: 0 18px 48px rgba(0, 0, 0, .18), 0 2px 6px rgba(0, 0, 0, .10);
  --canvas-background: var(--bg);
  --work-heading-background: var(--surface-1);
}
/* =========================================================================
   Breakpoint-System (Referenz — kein Build-Step, @media = rohe px):
     •  520px  phone-xs      sehr schmal: KPI-Grids einspaltig
     •  640px  phone-sm      schmal: 4-/3-spaltige Panel-Grids → 2-spaltig
     •  720px  mobile    ◀   HAUPT-Umbruch: Stack-Layout, Karten full-width
     •  900px  tablet        Sidebar wird Off-Canvas (901px = Desktop-Twin)
     •  980/1100/1200        Manager-Mehrspalten-Grids stufig
   Touch-Floor (≥44px) via (max-width:1024px),(pointer:coarse) — Memory
   project_tablet_touch_breakpoint. Mobile-@media stets NACH der Basis —
   Memory project_css_cascade_mobile.
   ========================================================================= */

/* ---------- Reset & Base ---------- */
* { box-sizing: border-box; }
/* DER SEITLICHE RIEGEL (Owner-Video-Audit 09.08., c2 B12 / c6 B29 · Paket P2).
   Es gab keinen: ein einziges Element mit fester Mindestbreite (`.team-table`
   640px, `.cal-week-cols` 720px, ein rohes `100vw`) schob die GANZE Seite
   seitwärts. Sichtbar wurde das als schwarzer Streifen links — der
   Verlaufs-Grund (`body::before`) liegt `fixed` und bleibt stehen, während der
   Inhalt wandert; rechts war der Avatar angeschnitten, die Navigation endete
   mit «Meh».
   `clip` statt `hidden`: `hidden` macht aus html/body einen Scroll-Behälter und
   nimmt jedem `position: sticky` darin seinen Anker (Kopfzeile, Reiterzeile,
   Filterleisten). `clip` klemmt nur — es scrollt nichts und hängt nichts ab. */
html, body { overflow-x: clip; }
html { scroll-behavior: smooth; }
[hidden] { display: none !important; }
/* Schrift-Floor für <small> (DESIGN.md §2: nichts rendert unter 11px).
   Der Browser-Default für <small> ist `smaller` = 0.8333× der Elterngrösse.
   In Datenzeilen (13px) sind das 10.83px — belegt vom Breiten-Wächter auf
   #/v/offer/new (b<small<div.so2-pos__price@10.8333px). Im Markup stehen
   27 blanke <small> ohne jede Regel; jedes einzelne davon unterschreitet den
   Floor, sobald sein Elternteil <= 13px ist.
   `max()` statt fixer 11px, damit das relative Verhalten unter grossen
   Überschriften erhalten bleibt — nur der Boden wird eingezogen. Jede
   klassen-qualifizierte Regel (z.B. `.so-hint`, `.so-stat small`) sticht
   diese hier ohnehin. EINE Zeile statt 27 Fundstellen. */
small { font-size: max(11px, 0.8333em); }
body {
  margin: 0;
  min-height: 100vh;
  min-height: 100dvh;
  font-family: 'Inter', system-ui, sans-serif;
  font-size: 14px;
  /* 1:1-Huelle (Owner-Regel 02.08., loest den flachen Grund vom 28.07. ab):
     das Referenzbild traegt einen GEMESSENEN Verlauf — Mitte #0b131c,
     Raender bis #01070c (13_25_27, Messpunkte Seite-*/App-Grund-*). Der
     Verlauf liegt als eigene feste Ebene (body::before) hinter allem:
     background-attachment:fixed ist auf iOS unzuverlaessig, eine
     position:fixed-Ebene nicht. var(--bg) bleibt der Fallback-Grund. */
  background: var(--bg);
  color: var(--text);
  line-height: 1.5;
  text-rendering: optimizeLegibility;
  overscroll-behavior-y: none;
  -webkit-tap-highlight-color: transparent;
}
/* Die gemessene Verlaufs-Ebene der 1:1-Huelle (siehe body-Kommentar). */
body::before {
  content: '';
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background: var(--canvas-background);
}
a { color: inherit; text-decoration: none; }
button, input, select, textarea { font: inherit; color: inherit; }
button { cursor: pointer; }
input, select, textarea, button {
  transition: border-color var(--transition), background var(--transition),
              color var(--transition), box-shadow var(--transition),
              transform var(--transition), opacity var(--transition);
}
::placeholder { color: var(--text-secondary); opacity: 1; }
::selection { background: rgba(var(--accent-rgb), .28); }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 2px; }
/* Scrollbars: schmal, ruhig, themetreu */
* { scrollbar-width: thin; scrollbar-color: rgba(var(--tint-rgb), .16) transparent; }
*::-webkit-scrollbar { width: 8px; height: 8px; }
*::-webkit-scrollbar-track { background: transparent; }
*::-webkit-scrollbar-thumb { background: rgba(var(--tint-rgb), .14); border-radius: var(--radius-card); }
*::-webkit-scrollbar-thumb:hover { background: rgba(var(--tint-rgb), .24); }
.skip-link {
  position: absolute; left: 16px; top: -48px; background: var(--accent); color: var(--on-accent);
  padding: 10px 14px; border-radius: var(--radius-button); z-index: 50; font-weight: 600;
}
.skip-link:focus { top: 12px; }
/* `left: 0` ist keine Kosmetik, sondern die Reparatur eines QUERLAUFS
   (gemessen 19.08.2026 im echten Browser auf 1400 px).
   `position: absolute` OHNE Kante behaelt die statische Stelle. Steht die
   Vorleser-Zeile in der letzten Spalte einer breiten Tabelle
   (`<th class="pl-menu-cell"><span class="sr-only">Aktionen</span></th>`), ist
   das ein Punkt WEIT rechts — und `.table-wrap { overflow-x: auto }` klemmt ihn
   NICHT ab, weil der Wirt selbst nicht positioniert ist und darum nicht sein
   Bezug ist. Ergebnis: die ganze Seite bekam einen waagrechten Rollbalken —
   «Standortbetreiber» 22 px, «Vertriebe» 194 px (Hausregel 9: kein Querlauf).
   Mit `left: 0` sitzt die Zeile an der linken Kante ihres Bezugs, bleibt
   1×1 px, bleibt geklemmt und bleibt fuer Vorleseprogramme genau dort, wo sie
   im Baum steht — die Lesereihenfolge ist der Baum, nicht die Lage.
   Gegenprobe am selben Lauf: dieselbe Messung auf «Personen», «Was ich
   schulde» und «Offerten» bleibt 0 px, vorher wie nachher. */
.sr-only { position: absolute; left: 0; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0,0,0,0); border: 0; }

/* ---------- App-Shell ---------- */
.app-shell { min-height: 100vh; min-height: 100dvh; display: grid; grid-template-columns: var(--sidebar-w, 236px) 1fr; }
body.no-topbar .app-shell { grid-template-columns: 1fr; }
body.sidebar-collapsed .app-shell { --sidebar-w: 68px; }
.main-shell {
  /* Owner-Entscheid 2026-07-05 (Monday-Referenz): Arbeitsflächen nutzen die
     VOLLE Breite — kein Content-Cap; der Seitenrand wächst sanft mit.
     Dokument-Views (Offer-Editor) deckeln sich SELBST (.so-editor).
     ⚠️ Lehre v73-Regression: margin-inline:auto + max-width auf einem
     GRID-ITEM shrinkt auf fit-content (Login/Tabellen kollabierten schmal) —
     Grid-Items brauchen width:100%, nie auto-Margins für Zentrierung. */
  width: 100%;
  /* Der Bodenabstand kommt aus EINER Rechnung (Block «Boden-Geometrie» oben) —
     er kennt Daumenleiste, Fixleiste, Plus-Knopf und sichere Zone. Am Rechner
     ist er `var(--sab)`, also exakt der bisherige Wert. */
  padding: 20px clamp(28px, 2.5vw, 56px) calc(32px + var(--boden-abstand));
  min-width: 0;                       /* Grid-Item muss schrumpfen können (Kanban) */
}
.view { display: none; }
.view.active { display: block; }

/* Topbar (Legacy-Chrome einzelner Views/Doc-Routen) */
.topbar {
  position: sticky; top: 0; z-index: 30; display: grid; grid-template-columns: auto 1fr auto; gap: 18px;
  align-items: center; min-height: var(--header-height); padding: max(14px, var(--sat)) 24px 14px;
  backdrop-filter: blur(18px); background: var(--topbar-bg); border-bottom: 1px solid var(--border);
}
.logo { width: 170px; color: var(--accent); }
.footer { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 12px; padding: 18px 24px 26px; color: var(--text-secondary); font-size: 13px; }

/* Micro-Label (Ex-Eyebrow). Der Mono-Kicker-Scaffold ist abgeschafft; die
   View-Wellen haben ihn abgebaut, wo er reine Deko war. Die Mitnahme
   `.panel__eyebrow` ist damit erledigt — kein Markup traegt sie mehr. */
.eyebrow {
  margin: 0 0 2px; color: var(--text-tertiary);
  text-transform: uppercase; letter-spacing: .07em;
  font-size: 11px; font-weight: 600; font-family: inherit;
}

/* ---------- Sidebar ---------- */
.sidebar {
  position: sticky; top: 0; align-self: start; height: 100vh; height: 100dvh; overflow-y: auto;
  display: flex; flex-direction: column; gap: 6px;
  background: var(--surface-1);
  border-right: 1px solid var(--border);
  padding: 16px 12px;
}
.sidebar__top { display: flex; align-items: center; min-height: 44px; padding: 4px 8px 14px; }
.sidebar .logo { width: 124px; transition: width var(--dur) var(--ease); }
.sidebar__nav { display: flex; flex-direction: column; gap: 2px; flex: 1; }
.sidebar .nav-tab {
  display: flex; align-items: center; gap: 11px; width: 100%;
  padding: 9px 11px; border-radius: var(--radius-button); min-height: 38px;
  border: 0; background: transparent; color: var(--text-secondary);
  font: 500 13.5px/1 inherit; text-decoration: none; white-space: nowrap; overflow: hidden;
  transition: background var(--transition), color var(--transition);
}
.sidebar .nav-tab:hover { background: rgba(var(--tint-rgb), .05); color: var(--text-primary); }
/* Aktiv = gefüllte Türkis-Pille mit dunkler Schrift (Referenz 13_25_27:
   «Cockpit»). Die Soft-Fassung davor war im Nebeneinander kaum vom
   Ruhezustand zu unterscheiden — der Owner fand den Ort nicht wieder.
   OHNE Hof (03.08.): senkrechter Schnitt durch 13_25_27.png bei x=520 —
   Pille 7,41,48 · eine Zeile unter ihrer Kante 2,12,18 · Grund 3,12,18.
   Ein 16px-Leuchtradius hätte dort angehoben. Die Pille trägt ihre
   Auffälligkeit durch die Füllung, nie durch Schein. */
.sidebar .nav-tab.active { background: var(--accent); color: var(--on-accent); }
.sidebar .nav-tab.active .nav-tab__icon { color: var(--on-accent); }
.nav-tab__icon { display: inline-flex; flex: none; width: 19px; height: 19px; }
.nav-tab__icon svg { width: 19px; height: 19px; }
.nav-tab__label { overflow: hidden; text-overflow: ellipsis; }
.sidebar__footer { margin-top: auto; padding-top: 10px; border-top: 1px solid var(--border); display: flex; flex-direction: column; gap: 2px; }
/* Fusszeile der Seitenleiste: Name führt, Rolle steht klein darunter. Nebeneinander
   brach «Standortbetreiber · Sazan Deskaj» im 236px-Well auf zwei Zeilen um. */
.sidebar__footer .user-pill { width: 100%; justify-content: flex-start; flex-direction: column; align-items: flex-start; gap: 1px; }
.sidebar__footer .user-pill__role { order: 2; }

/* Inline-Icon (folgt Schriftgrösse, sitzt auf der Textlinie) */
.eico { display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto; line-height: 0; vertical-align: -0.14em; }
.eico svg { width: 1.05em; height: 1.05em; }

/* Die Grundgroesse jedes Zeichens aus utils/icons.js (20.08.2026).
   Vorher trug ein Icon nur seinen viewBox — die Groesse musste JEDER Kasten
   selbst per `.foo svg { width: … }` setzen. Wo diese Regel fehlte, wurde aus
   einem 12-px-Zeichen ein Klotz in Kastenbreite: so hat die Uhr an
   `.kanban-card__cb` das Rechnungs-Kanban auf ~500 px je Karte gesprengt
   (gemessen: Uhr 283 px, Karte 384 px — scripts/_zeichen_geometrie_test.mjs).
   `.ico` hat Spezifitaet 0,1,0 und verliert damit gegen JEDE bestehende Regel
   der Form `.foo svg` (0,1,1) — kein gesizter Slot aendert sich, nur die
   vergessenen bekommen einen Boden statt eines Kraters. */
.ico { width: 1em; height: 1em; flex: 0 0 auto; vertical-align: -0.14em; }

/* Hamburger + Overlay (nur Mobile) */
.sidebar-toggle {
  position: fixed; top: calc(12px + var(--sat)); left: 12px; z-index: 55; width: 44px; height: 44px;
  border-radius: var(--radius-card); background: var(--surface-2); border: 1px solid var(--border);
  color: var(--text); align-items: center; justify-content: center; cursor: pointer; display: none;
  box-shadow: var(--shadow-sm);
}
.sidebar-overlay { position: fixed; inset: 0; background: rgba(4, 8, 10, .55); backdrop-filter: blur(2px); z-index: 55; }

/* Eingeklappt (Desktop): nur Icons */
@media (min-width: 901px) {
  body.sidebar-collapsed .nav-tab__label,
  body.sidebar-collapsed .sidebar .user-pill__role,
  body.sidebar-collapsed .sidebar .user-pill strong { display: none; }
  body.sidebar-collapsed .sidebar { padding: 16px 8px; }
  body.sidebar-collapsed .sidebar .nav-tab,
  body.sidebar-collapsed .sidebar__footer .user-pill { justify-content: center; padding: 9px; }
  body.sidebar-collapsed .sidebar__top { justify-content: center; }
  body.sidebar-collapsed .sidebar .logo { width: 30px; }
}
/* Mobile: Sidebar als Off-Canvas */
@media (max-width: 900px) {
  .app-shell { grid-template-columns: 1fr !important; }
  .sidebar {
    position: fixed; top: 0; left: 0; width: 268px; z-index: 60;
    height: 100vh; height: 100dvh; overflow-y: auto;
    padding-top: var(--sat); padding-bottom: var(--sab);
    transform: translateX(-100%); transition: transform var(--dur-slow) var(--ease);
    border-right: 1px solid var(--border);
  }
  body.sidebar-open .sidebar { transform: translateX(0); box-shadow: var(--shadow-lg); }
  .sidebar-toggle { display: flex; }
  .main-shell { padding-top: calc(64px + var(--sat)); }
  .main-shell:has(.doc-sheet) { padding-top: calc(22px + var(--sat)); }
}

/* ---------- Subnav: Underline-Tabs (Seiten-Ebene) ---------- */
.subnav {
  display: flex; gap: 2px; align-items: center; width: fit-content; max-width: 100%;
  margin: 0 0 18px; padding: 0 0 0;
  background: transparent; border: 0; border-bottom: 1px solid var(--border); border-radius: 0;
  overflow-x: auto; -webkit-overflow-scrolling: touch; scrollbar-width: none;
}
.subnav::-webkit-scrollbar { display: none; }
/* Die Fahne der Subnav: sie scrollt waagrecht, also muss sie es auch sagen
   (DESIGN §7). Ohne sie stand der letzte Reiter auf 390 px hart an der Kante
   abgeschnitten und sah kaputt aus statt scrollbar. Klassen: main.js
   `subnavFahne()`. Gleiche Mechanik wie `.cp__zonenwahl`. */
.subnav.is-mehr-rechts {
  -webkit-mask-image: linear-gradient(90deg, #000 calc(100% - 28px), transparent);
  mask-image: linear-gradient(90deg, #000 calc(100% - 28px), transparent);
}
.subnav.is-mehr-links {
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 28px);
  mask-image: linear-gradient(90deg, transparent, #000 28px);
}
.subnav.is-mehr-links.is-mehr-rechts {
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 28px, #000 calc(100% - 28px), transparent);
  mask-image: linear-gradient(90deg, transparent, #000 28px, #000 calc(100% - 28px), transparent);
}
.subnav__tab {
  position: relative; flex: none; display: inline-flex; align-items: center; min-height: 40px;
  padding: 0 13px; border-radius: var(--radius-card) var(--radius-card) 0 0; color: var(--text-secondary);
  font-weight: 500; font-size: 13.5px; white-space: nowrap;
  transition: background var(--transition), color var(--transition);
}
.subnav__tab::after {
  content: ""; position: absolute; left: 10px; right: 10px; bottom: -1px; height: 2px;
  border-radius: 2px 2px 0 0; background: transparent; transition: background var(--transition);
}
.subnav__tab:hover { color: var(--text-primary); background: rgba(var(--tint-rgb), .04); }
.subnav__tab.active { color: var(--text-primary); }
.subnav__tab.active::after { background: var(--accent); }

/* Legacy .view-switch/.nav-tab (Doc-/Login-Chrome): Segmented-Optik */
.view-switch { display: inline-flex; gap: 2px; background: var(--surface-inset); border: 1px solid var(--border); border-radius: var(--radius-card); padding: 3px; }
.view-switch .nav-tab {
  border: 0; background: transparent; color: var(--text-secondary); border-radius: var(--radius-button);
  padding: 8px 14px; font-weight: 650; font-size: 12px; letter-spacing: 0; text-transform: none; min-height: 36px;
}
.view-switch .nav-tab:hover { color: var(--text-primary); }
.view-switch .nav-tab.active { background: var(--accent-soft); color: var(--text-primary); box-shadow: inset 0 0 0 1px var(--accent-line); }

/* ---------- Segmented Control (view-toggle / section-nav — EIN Stil) ---------- */
.view-toggle, .section-nav {
  display: inline-flex; gap: 2px;
  background: var(--surface-inset); border: 1px solid var(--border);
  border-radius: var(--radius-card); padding: 3px; margin-bottom: 12px;
}
.section-nav { margin-top: 6px; margin-bottom: 0; flex-wrap: wrap; }
/* Karte 01.08., Position 6: zwei eingeklappte Tueren wurden zu Umschaltern in
   derselben Bauart wie der Blatt-Wechsel — «Ich | Team» auf «Heute» und
   «Aktivität | Änderungen» im «Verlauf». Sie brauchen keine eigene Erscheinung,
   nur ihren Platz: der Umfangs-Schalter steht in der Werkzeugleiste (kein
   doppelter Abstand), die Reiterleiste steht ueber der Flaeche. */
.filters-toolbar .view-toggle--scope { margin-bottom: 0; }
.vl-reiter { margin-bottom: 14px; }
/* «Am haeufigsten korrigiert …» im Kopf des Reiters «Aenderungen»
   (field_edit_heatmap). Eine leise Zeile rechts im Panelkopf — sie beantwortet
   die Frage der Liste darunter, ohne einen zweiten Bildschirm zu oeffnen. */
.vl-haeufig { margin-left: auto; font-size: 12px; text-align: right; }
@media (max-width: 720px) { .vl-haeufig { margin-left: 0; text-align: left; width: 100%; } }
.view-toggle__btn, .section-nav__btn {
  display: inline-flex; align-items: center; gap: 8px;
  border: 0; background: transparent; color: var(--text-secondary);
  padding: 7px 14px; border-radius: var(--radius-button); font-weight: 650; font-size: 12px;
  letter-spacing: 0; text-transform: none;
  cursor: pointer; min-height: 34px; white-space: nowrap;
  transition: background var(--transition), color var(--transition);
}
.view-toggle__btn .vt-ico { display: inline-flex; }
.view-toggle__btn .vt-ico svg { width: 16px; height: 16px; }
/* GEWAEHLT IST BLAU (Owner 03.09.2026, «man spuert: das ist gewaehlt»): dieselbe
   Toenung und Haarlinie wie .kf-segment — ein Aktiv-Stil im ganzen Haus. */
.view-toggle__btn.is-active, .section-nav__btn.is-active {
  background: var(--accent-soft); color: var(--text-primary);
  box-shadow: inset 0 0 0 1px var(--accent-line);
}
.view-toggle__btn:hover:not(.is-active), .section-nav__btn:hover:not(.is-active) { color: var(--text-primary); }

/* ---------- Panels & Karten: Fläche + Hairline (Referenz 28.07.) ----------
   Die Karte ist eine Stufe heller als der Grund und trägt eine feine
   Hairline als Kante — kein Innen-Glanz, kein Ambient-Schatten. Radius 14.
   Der Border-Hook bleibt an derselben Stelle: Regeln, die border-color
   setzen (Selektion, Warnzustände), wirken unverändert. */
/* DIE BLOCKGRENZE — DIE KARTE KOMMT ZURUECK (Owner-Urteil 2026-08-25).
   Owner-Wortlaut: «Dort im Desktop meine ich das gesamte UI/UX. Man hat keinen
   Unterschied: Alles ist einfach auf dunkle Flaeche geschrieben, kein Leben,
   keine Ahnung, was.»

   WAS HIER VORHER STAND — und warum es faellt. Am 13.08. wurde `.panel` FLACH
   gemacht («Wizard oder Widget»): `background: transparent`, kein Rahmen, kein
   Radius, `padding: 21px 0`, und statt einer Fuge eine GETEILTE Haarlinie zum
   Nachbarn. Der Befund von heute ist die gemessene Folge davon:

     · `.panel` ist mit 1'183 Fundstellen in 109 Dateien der meistbenutzte
       Baustein des Hauses und war der einzige, der KEINE Kante hatte.
     · Gemessen ueber 29 gebaute Flaechen bei 1400px: `.panel` stellt mit 51
       breiten Bloecken die groesste Gruppe ueberhaupt (vor `div` 46,
       `panel-row` 44) — und keiner davon war als Block erkennbar.
     · Von 249 senkrechten Abstaenden lagen 213 bei 20px oder darunter: ein
       neuer ABSCHNITT stand so eng wie zwei Zeilen INNERHALB einer Liste.

   DER WIDERSPRUCH IST KEINER. Der Owner sagte am 13.08. NICHT «keine Karten»,
   sondern: nichts soll wie ein aufgesetztes Widget ueber der Flaeche schweben.
   Das Schweben ist der Schatten und die abhebende Erhoehung — beides bleibt
   weg (`box-shadow: none`, `--surface` ist EINE Stufe, nicht drei). Was
   zurueckkommt, ist die Kante, die das Fundament dieser Datei von Anfang an
   vorschreibt: «Karten eine Stufe heller MIT feiner Hairline · Radius 14»
   (Kopf dieser Datei, Owner-Referenzen 28.07.). `--surface` traegt den
   Kommentar «Karten/Panels», `--radius-card: 14px` heisst «Radius 14 wie in
   der Referenz». Beide waren entschieden und wurden von `.panel` nicht
   benutzt.

   DIE REFERENZ ZEIGT ES OHNE AUSLEGUNG:
   docs/design/referenzen/Kundenansichtenportal/«… 13_21_30 (12).png» (jedes
   Panel eine Karte mit eigener Flaeche, Haarlinie, Radius und echter Fuge —
   Aktive Kampagnen, Schnellaktionen, Wieder buchen, Entwuerfe, Benoetigte
   Inhalte, Letzte Reports, Letzte Rechnungen) und «… 13_21_27 (10).png»
   (Buchungszusammenfassung, Preisuebersicht, Zahlungsart als drei Karten).

   WAS BLEIBT: `.modal`. Ein Dialog DARF schweben (EINHEIT §3.9).
   `.firm-card` bleibt flach: die Lead-ZEILE ist ein Listeneintrag, kein
   Abschnitt — sie steht INNERHALB eines Blocks und wuerde als eigene Karte
   die Karte in der Karte erzeugen, die unten ausdruecklich verhindert wird.

   DIE FUGE STATT DER GETEILTEN LINIE: mit eigener Kante je Karte waere die
   `border-top` des Nachbarn eine doppelte Linie. Sie faellt, der Abstand
   kommt zurueck (16px). Gemessen an 29 Flaechen in beiden Massen: von 104
   `.panel` liegen 102 in einem `display:block`-Eltern, die beiden anderen
   sind das EINZIGE Kind ihres Rasters (`.login-card`) — `+` trifft dort
   nie. Der Befund vom 13.08. (9 Routen) haelt also auch ueber 29.

   WAAGERECHTES PADDING: 20px. Der Inhalt ruecken damit um die Kartenkante
   ein — genau wie in der Referenz. Senkrecht 18px + 1px Rahmen = die alte
   Hoehe von 21px minus zwei Pixel, die die Fuge zurueckgibt. */
.modal {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  box-shadow: none;
}
.panel, .firm-card {
  box-shadow: none;
}
.firm-card {
  background: transparent;
  border: 0;
  border-radius: 0;
}
.panel {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  padding: 18px 20px;
  /* DIE FUGE HAENGT AN DER KARTE, NICHT AM NACHBARN (nachgemessen 25.08.).
     Erster Versuch war `.panel + .panel { margin-top: 16px }`. Am Bild
     gemessen half das fast nirgends: die Flaechen legen ihre Abschnitte in
     Halter (`<div data-slot="liquiditaet">`), also sind zwei Karten nur
     selten GESCHWISTER — von 126 Karten ueber 29 Flaechen standen genau
     neun in einer messbaren Geschwister-Fuge, Median 10px. Eine Karte, die
     ihren eigenen Abstand nach unten mitbringt, trifft jeden Fall: den
     Geschwister-Fall, den Halter-Fall und den kuenftigen. */
  margin-bottom: 16px;
}
.panel + .panel { border-top: 0; }
/* Ein Panel IM Panel waere eine Karte in der Karte. Es bleibt ein Abschnitt
   mit Haarlinie — die Gliederung ohne den zweiten Kasten, und ohne die Fuge:
   innerhalb einer Karte trennt die Linie. */
.panel .panel { background: none; border: 0; border-radius: 0; padding: 16px 0; margin-bottom: 0; }
.panel .panel + .panel { border-top: 1px solid var(--border); }
.panel__header { display: flex; justify-content: space-between; gap: 16px; align-items: flex-start; margin-bottom: 14px; }
/* EINHEIT 1.5: Panel-Titel 13px, fest — innen wie aussen (Integrator W-B).
   RANGFOLGE 25.08.: die Ueberschrift war KLEINER als die Zeile, die sie
   ueberschreibt — `.panel h3` 13px/600/weiss gegen `.panel-row__main > b`
   14px/600/weiss (gemessen im Browser, nicht geschaetzt). Zwei Dinge in
   derselben Farbe und demselben Gewicht, und das untergeordnete groesser.
   Geheilt wird es OHNE fuenften Schriftgrad (EINHEIT §1.5 legt vier fest):
   die Zeile faellt auf den Grad «Kachel-Label» (12.5px, weiter unten), und
   die Ueberschrift bekommt Laufweite statt Enge — `-.01em` war negativ und
   zog sie optisch noch kleiner. Hell bleibt sie: die Referenz
   («… 13_21_30 (12).png», «Aktive Kampagnen») zeigt den Panel-Titel weiss,
   und eine graue Ueberschrift waere genau die zweite graue Zeile, die der
   Owner heute beklagt. */
.panel h3, .panel h2 { margin: 0; font-size: 13px; font-weight: 600; letter-spacing: .02em; color: var(--text-primary); }
/* Sektions-Titel gesperrt (Referenz: «PRIMÄRES KAMPAGNENZIEL», «SCREENUMFANG»). */
.panel__title { margin: 0 0 6px; font-size: 15px; font-weight: 650; letter-spacing: -.015em; text-transform: none; color: var(--text-secondary); }
/* 03.09.2026 (W4 «der Bereich, wo gerechnet wird»): der Kopf eines Kastens ist ein
   ETIKETT wie in der Referenz (Bild 14: «IHR MEDIAPLAN AUF EINEN BLICK», «IHRE
   PREISSCHÄTZUNG») — gesperrte Versalien, gedämpft; das Grosse sind die Zahlen
   darunter. Der Zusatz im Kopf (`.panel__hint`) bleibt gemischt geschrieben: er ist
   Beschriftung, kein zweites Etikett. Gilt im ganzen Haus, nicht je Fläche. */
.panel__header h3, .panel__header h2 {
  font-size: 12px; font-weight: 650; letter-spacing: .12em; text-transform: uppercase;
  color: var(--text-secondary);
}
.panel__header h3 .panel__hint, .panel__header h2 .panel__hint { text-transform: none; letter-spacing: 0; }

/* ---------- Kennzahl-Kachel (Referenz: grosse Zahl, kleines Label) ---------- */
/* KPI-Strip (Berater/Besucher): EIN Panel, Hairline-getrennte Stats */
.kpi-strip { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 0; padding: 6px 0; }
.kpi-pill { display: flex; flex-direction: column; gap: 3px; padding: 10px 18px; background: transparent; border: 0; border-left: 1px solid var(--border); border-radius: 0; }
.kpi-pill:first-child { border-left: 0; }
.kpi-pill span { color: var(--text-secondary); font-size: 12.5px; font-weight: 500; letter-spacing: 0; }
.kpi-pill strong { font-size: 24px; font-weight: 650; letter-spacing: -.4px; font-variant-numeric: tabular-nums; color: var(--text-primary); }
.kpi-pill--rate strong { color: var(--text-primary); }

/* ---------- Filter & Formulare ---------- */
.sticky-filters { position: sticky; top: calc(var(--sat) + 10px); z-index: 20; margin-bottom: 16px; }
.filters-panel { padding: 12px 14px; }
.filters-toolbar { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 12px; }
.filters-group, .filters-actions { display: flex; flex-wrap: wrap; gap: 10px; align-items: end; }
.field { display: flex; flex-direction: column; gap: 6px; min-width: 150px; }
.field--wide { min-width: min(420px, 100%); flex: 1 1 320px; }
.field--narrow { max-width: 120px; min-width: 0; }
/* ZWEI KURZE FELDER TEILEN SICH EINE ZEILE (25.08.2026).
   Anlass: der Anlege-Dialog des Offerten-Rechners fragt Firmenname, Strasse,
   PLZ und Ort. Auf 390×620 standen die vier untereinander — PLZ, Ort UND beide
   Knöpfe lagen unter der Zone, die eine offene iOS-Tastatur bedeckt (gemessen
   25.08.: Felder bei y=394 und y=478, Knöpfe bei y=537 auf 620 px Schirm; der
   Dialog selbst rollt nicht, weil sein Inhalt ohne Tastatur genau passt). PLZ
   ist vier Zeichen — sie neben den Ort zu stellen spart eine ganze Zeile.
   Die Regel greift NUR in einem Kasten, der ein solches Feld wirklich enthält
   (`:has`) — jeder andere Dialog des Hauses behält seine einspaltige Form,
   Pixel für Pixel. `.modal__body` ist ein Grid (eine Spalte); mit zwei Spalten
   müssen alle übrigen Kinder ausdrücklich über beide gehen. */
.modal__body:has(> .field--eng) { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.modal__body:has(> .field--eng) > * { grid-column: 1 / -1; }
.modal__body:has(> .field--eng) > .field--eng { grid-column: span 1; min-width: 0; }
/* EINHEIT 1.5 (Schlichtung 10.08., Prüfblick W9 Q1): Versalien tragen genau
   eine Aufgabe — den Tabellenkopf. Feldnamen sind keine Spaltenköpfe; die
   gemischte Form kommt aus patch-firma.css, wo sie zuerst hergeleitet wurde,
   und gilt ab hier hausweit statt je Fläche einzeln. */
.field span { color: var(--text-secondary); font-size: 12px; font-weight: 600; }
select, .search-input, textarea {
  width: 100%; min-height: 40px;
  background: var(--surface-inset); border: 1px solid var(--border);
  border-radius: var(--radius-button); padding: 0 12px; color: var(--text);
}
/* Jedes Textfeld, auch ohne label.field und ohne .search-input. Vorher trug
   ein blankes <input> die Voreinstellung des Browsers — im Kundenportal stand
   die Standortsuche als grauer Systemkasten mitten in der dunklen Fläche.
   `:where()` macht die Regel spezifitätslos: sie ist ein BODEN, den jede
   Komponentenregel überschreibt. Ohne das Auszeichnen gewinnt
   `input[type=number]` (0,1,1) gegen `.lx-policy__num` (0,1,0) und hätte
   dessen 44px-Tapfläche auf 40px gedrückt — im Regel-Test gemessen. */
:where(input[type=text], input[type=search], input[type=email], input[type=tel],
input[type=number], input[type=password], input[type=url], input[type=date],
input[type=time], input[type=datetime-local], input[type=month], input:not([type])) {
  min-height: 40px; padding: 9px 12px; color: var(--text);
  /* 1:1-Huelle: Eingabefelder tragen in der Referenz einen DEUTLICHEN Rand
     (Suchfeld-Rand gemessen #383d45) — die feine Karten-Hairline war hier zu
     leise, Felder verschwammen mit dem Grund. */
  background: var(--surface-inset); border: 1px solid var(--line-strong);
  border-radius: var(--radius-button);
}
:where(input[type=text], input[type=search], input[type=email], input[type=tel],
input[type=number], input[type=password], input[type=url], input[type=date],
input[type=time], input[type=datetime-local], input[type=month], input:not([type])):focus {
  outline: none; border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(var(--accent-rgb), .18);
}
select {
  appearance: none; -webkit-appearance: none;
  padding-right: 32px;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%238a9ba3' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='m6 9 6 6 6-6'/></svg>");
  background-repeat: no-repeat;
  background-position: right 10px center;
}
select:hover, .search-input:hover, textarea:hover { background-color: var(--surface-hover); border-color: var(--line-strong); }
select:focus, .search-input:focus-within, textarea:focus {
  outline: none; border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(var(--accent-rgb), .18);
}
.search-input { display: flex; align-items: center; gap: 10px; padding-right: 12px; }
.search-input svg { width: 17px; height: 17px; color: var(--text-secondary); flex: 0 0 auto; }
.search-input input { border: 0; outline: none; background: transparent; width: 100%; min-width: 0; min-height: 36px; }
.field input[type=date], .field input[type=time], .field input[type=tel], .field input[type=email],
.field input[type=text], .field input[type=search], .field input[type=number], .field input[type=password],
.field select, .field textarea {
  background: var(--surface-inset); border: 1px solid var(--border); border-radius: var(--radius-button);
  padding: 9px 12px; color: var(--text); min-height: 38px;
}
.field input:focus, .field select:focus, .field textarea:focus {
  border-color: var(--accent); outline: none;
  box-shadow: 0 0 0 3px rgba(var(--accent-rgb), .18);
}
.field textarea, textarea { padding-top: 9px; padding-bottom: 9px; }
.notes-area { width: 100%; min-height: 96px; background: var(--surface-inset); border: 1px solid var(--border); border-radius: var(--radius-button); padding: 10px 12px; color: var(--text); resize: vertical; font: inherit; }
.check-row { display: flex; gap: 14px; flex-wrap: wrap; }
.check-row label { display: flex; gap: 8px; align-items: center; }
.field--check { flex-direction: row; align-items: center; gap: 10px; min-height: 38px; }

/* Custom Checkbox (app-weit, ohne Markup-Änderung) */
input[type="checkbox"] {
  appearance: none; -webkit-appearance: none;
  width: 18px; height: 18px; flex: none; margin: 0;
  border: 1.5px solid var(--line-strong); border-radius: var(--radius-card);
  background: var(--surface-inset); cursor: pointer; display: inline-grid; place-items: center;
  transition: background var(--transition), border-color var(--transition), box-shadow var(--transition);
}
input[type="checkbox"]::after {
  content: ""; width: 100%; height: 100%;
  background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='3.4' stroke-linecap='round' stroke-linejoin='round'><path d='m5.5 12.5 4 4 9-9'/></svg>") center / 70% no-repeat;
  transform: scale(0); transition: transform var(--dur-fast) var(--ease);
}
input[type="checkbox"]:hover { border-color: var(--accent); }
input[type="checkbox"]:checked { background: var(--accent); border-color: var(--accent); }
input[type="checkbox"]:checked::after { transform: scale(1); }
input[type="checkbox"]:indeterminate { background: var(--accent); border-color: var(--accent); }
input[type="checkbox"]:indeterminate::after {
  background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='3.4' stroke-linecap='round'><path d='M6 12h12'/></svg>") center / 70% no-repeat;
  transform: scale(1);
}

/* ---------- Buttons: EIN Vokabular ---------- */
/* Es sind noch zwei: .primary-btn und .ghost-btn. .secondary-btn, .toggle-btn
   und .sort-btn hatten in public/src keinen Traeger mehr — sie sind mit dem
   Redundanz-Pass gefallen, nicht ersetzt worden. */
/* Knöpfe tragen ihr Wort gesperrt in Versalien (Referenz: SPEICHERN, ZURÜCK,
   GEBIET PLANEN →); die Hauptaktion ist eine eishelle Fläche mit dunklem
   Wort, die zweite ein dunkles Feld mit Haarlinie. */
.primary-btn, .ghost-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  min-height: 38px; padding: 0 16px;
  border-radius: var(--radius-button); font-weight: 650; font-size: 12px;
  letter-spacing: .1em; text-transform: uppercase;
  border: 1px solid transparent; cursor: pointer; white-space: nowrap;
  max-width: 100%;
}
/* Ein Knopf, dessen Wort laenger ist als das Handy breit («Abschluss (Bilanz,
   Erfolgsrechnung, MWST)» in Versalien), ragte 13,5 px aus dem Bild — nichts
   konnte dorthin rollen (Breitenprobe 03.09., buchhaltung@390). Am Handy
   bricht das Wort im Knopf um; der Boden von 44 px bleibt, die Hoehe waechst. */
@media (max-width: 720px) {
  .primary-btn, .ghost-btn { white-space: normal; text-align: center; line-height: 1.25; }
}
.primary-btn { background: var(--accent-fill); color: var(--on-accent); box-shadow: none; }
.primary-btn:hover:not(:disabled) { background: var(--accent-bright); }
.primary-btn:active:not(:disabled) { transform: scale(.985); }
.primary-btn:disabled { opacity: .55; cursor: not-allowed; }
.primary-btn--call { background: var(--accent-fill); color: var(--on-accent); }
.primary-btn--call:hover { background: var(--accent-bright); color: var(--on-accent); }
.ghost-btn { background: var(--surface-2); color: var(--text); border-color: var(--border); }
.ghost-btn:hover { background: rgba(var(--tint-rgb), .05); border-color: var(--line-strong); }
.ghost-btn:active { transform: scale(.985); }
.ghost-btn--danger { color: var(--bad-strong); border-color: rgba(var(--bad-rgb), .3); }
.ghost-btn--danger:hover { background: rgba(var(--bad-rgb), .10); border-color: var(--bad-strong); }
.ghost-btn--block { width: 100%; justify-content: flex-start; flex-direction: column; align-items: flex-start; padding: 12px 14px; gap: 4px; text-align: left; min-height: 0; }
.ghost-btn--block strong { color: var(--text-primary); }
.ghost-btn--block span { color: var(--text-secondary); font-size: 12.5px; font-weight: 400; white-space: normal; }
.ghost-btn--xs { padding: 4px 10px; min-height: 28px; font-size: 12.5px; }
.icon-btn {
  width: 36px; height: 36px; min-height: 0; flex-shrink: 0; padding: 0;
  display: grid; place-items: center; cursor: pointer;
  background: transparent; border: 1px solid var(--border); border-radius: var(--radius-button); color: var(--text);
}
.icon-btn svg { width: 17px; height: 17px; }
.icon-btn:hover { background: rgba(var(--tint-rgb), .06); border-color: var(--line-strong); }
.icon-btn:active { transform: scale(.94); }
.icon-btn--sm { width: 30px; height: 30px; }
.icon-btn--sm svg { width: 14px; height: 14px; }

/* Touch-Floor: auf Touch-Geräten bleibt ALLES ≥44px (Tablet-Bruchzone inkl.) */
@media (max-width: 1024px), (pointer: coarse) {
  .primary-btn, .ghost-btn { min-height: 44px; }
  .icon-btn { width: 44px; height: 44px; }
  .icon-btn--sm { width: 38px; height: 38px; }
  select, .search-input, textarea { min-height: 44px; }
  .field input[type=date], .field input[type=time], .field input[type=tel], .field input[type=email],
  .field input[type=text], .field input[type=search], .field input[type=number], .field input[type=password],
  .field select, .field textarea { min-height: 44px; }
  /* Auch die Felder ohne label.field halten die Tapfläche (Boden von Z. 429). */
  input[type=text], input[type=search], input[type=email], input[type=tel],
  input[type=number], input[type=password], input[type=url], input[type=date],
  input[type=time], input[type=datetime-local], input[type=month],
  input:not([type]) { min-height: 44px; }
  .search-input input { min-height: 42px; }
  input[type="checkbox"] { width: 22px; height: 22px; }
  /* Iter 26, verschärft 08.08. (MASTERPLAN E2): iOS zoomt die GANZE App,
     sobald ein Feld mit Schrift <16px den Fokus bekommt — und bleibt
     gezoomt hängen (un-nativ). Der Floor stand hier seit Iter 26 als
     Element-Selektor und verlor damit gegen JEDE spätere Klassen-Regel —
     am 08.08. lagen alle Konfigurator-Felder auf 12–13px (.kf-feld input,
     .calc-felder, .kf-leiste__gruppe select …): das Gesetz galt, nur
     nirgends. Deshalb !important — ein OS-Verhaltens-Floor wie [hidden]
     und reduced-motion, keine Gestaltung. Er trifft nur Feld-INHALTE
     (input/select/textarea); Labels, Hinweise und Buttons bleiben.
     Wächter: _konfigurator_ui_test.mjs («Kein fokussierbares Eingabefeld
     unter 16px»). Wer ein Feld am Touch anders will, ändert es HIER. */
  input, select, textarea { font-size: 16px !important; }
  .view-toggle__btn, .section-nav__btn { min-height: 44px; }
  .firm-link { min-height: 44px; display: inline-flex; align-items: center; }
  .cal-toggle { min-height: 44px; }
  .subnav__tab { min-height: 44px; }
  .ghost-btn--xs { min-height: 38px; }
}

/* ---------- Status-Chips: Wort in Pillenform (Referenz 28.07.) ----------
   Alpha-Fläche + Strong-Text, keine Border, Radius 999 — ein Zustand ist ein
   Wort, kein Kasten. --radius-badge trägt die Pillenform app-weit. */
/* Stand-Chip: gerahmt, Versalien gesperrt, kaum Fläche (Referenz Bild 02
   «STARTKLAR» grün, Bild 12 «AUSWAHL FEHLT» bernstein). */
.badge {
  display: inline-flex; align-items: center; gap: 6px;
  border-radius: var(--radius-badge); padding: 4px 10px;
  font-size: 11px; font-weight: 650; letter-spacing: .12em; text-transform: uppercase; line-height: 1.3;
  border: 1px solid rgba(var(--tint-rgb), .18); white-space: nowrap;
}
.badge--version { background: var(--accent-soft); color: var(--accent-strong); }
.badge--industry { background: rgba(var(--tint-rgb), .06); color: var(--text-secondary); }
.badge--high   { background: rgba(var(--good-rgb),.06); color: var(--good-strong); border-color: rgba(var(--good-rgb),.35); }
.badge--medium { background: rgba(var(--warn-rgb),.06); color: var(--warn-strong); border-color: rgba(var(--warn-rgb),.35); }
.badge--low    { background: rgba(var(--bad-rgb),.06);  color: var(--bad-strong);  border-color: rgba(var(--bad-rgb),.35); }
.badge--region-zuerich   { background: rgba(59,130,246,.14); color: var(--zuerich-text); }
.badge--region-aarau     { background: rgba(139,92,246,.14); color: var(--aarau-text); }
.badge--region-bern      { background: rgba(var(--accent-rgb),.14); color: var(--accent-strong); }
.badge--region-solothurn { background: rgba(249,115,22,.14); color: var(--warn-strong); }
.badge--region-luzern    { background: rgba(236,72,153,.14); color: var(--luzern-text); }
.badge--open        { background: rgba(var(--tint-rgb), .08); color: var(--text); }
.badge--inprogress  { background: rgba(59,130,246,.15); color: var(--info-strong); }
.badge--contacted   { background: rgba(var(--accent-rgb),.15); color: var(--accent-strong); }
.badge--appointment { background: rgba(var(--good-rgb),.15); color: var(--good-strong); }
.badge--won         { background: rgba(var(--good-rgb),.22); color: var(--good-strong); }
.badge--lost        { background: rgba(var(--bad-rgb),.16); color: var(--bad-strong); }
.badge--later       { background: rgba(var(--warn-rgb),.16); color: var(--warn-strong); }
.badge--pool        { background: rgba(var(--tint-rgb), .06); color: var(--text-secondary); }
.badge--round       { background: var(--accent-soft); color: var(--accent-strong); font-variant-numeric: tabular-nums; }
.badge--role-admin   { background: rgba(var(--bad-rgb),.15); color: var(--bad-strong); }
.badge--role-manager { background: rgba(var(--warn-rgb),.15); color: var(--warn-strong); }
.badge--role-caller  { background: rgba(59,130,246,.15); color: var(--info-strong); }
/* 03.08.: Seit die externen Vertriebe in der Verteil-Auswahl stehen, brauchen
   sie eine eigene Farbe. Sie sind KEINE eigenen Leute — wer ihnen einen Lead
   gibt, gibt ihn aus dem Haus, und das muss man in der Liste sehen, ohne die
   Rollen-Bezeichnung zu lesen. Türkis wie die Marke: extern, aber zugehörig. */
.badge--role-vertrieb_admin,
.badge--role-vertrieb_user { background: rgba(var(--accent-rgb),.14); color: var(--accent-strong); }
.badge--lg { padding: 6px 14px; font-size: 13px; }
.ads-badge {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 68px; min-height: 24px; padding: 0 11px; border-radius: var(--radius-badge);
  border: 0; font-size: 11.5px; font-weight: 700; letter-spacing: .03em; text-transform: uppercase;
}
.results-pill {
  display: inline-flex; align-items: center; justify-self: start; width: max-content; max-width: 100%;
  min-height: 30px; padding: 0 12px; border-radius: var(--radius-badge);
  background: rgba(var(--tint-rgb), .05); border: 0;
  color: var(--text-secondary); font-size: 12.5px; font-variant-numeric: tabular-nums lining-nums;
}

/* ---------- Firm-Card (Lead-Karte) ---------- */
/* FLACH STATT KASTEN (Owner «Widget», 2026-08-13): die Lead-Liste war ein
   Stapel schwebender Karten mit 10px Luft dazwischen. Jetzt eine durchgehende
   Flaeche aus Zeilen, getrennt durch eine Haarlinie — dasselbe Idiom wie die
   Standortliste des Konfigurators (`.kf-loc`) und der Korb (`.kf-stueck`).
   Die 1px des alten Rahmens wandern ins senkrechte Padding (14 → 15), die
   waagerechten 16px fallen weg: die Zeile beginnt an derselben Kante wie
   Seitentitel und Filterleiste. */
.firms-list { display: grid; gap: 0; }
.firm-card { padding: 15px 0; display: grid; gap: 10px; cursor: pointer; border-bottom: 1px solid var(--border); transition: background var(--transition); }
.firm-card:last-child { border-bottom: 0; }
.firm-card:hover { background: rgba(var(--tint-rgb), .045); }
.firm-card__bottom { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 12px; align-items: center; margin-top: 6px; }
.firm-card__meta { display: flex; flex-wrap: wrap; justify-content: flex-start; gap: 4px 6px; align-items: center; color: var(--text-secondary); font-size: 13px; margin: 2px 0; }
.firm-card__contact { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; justify-content: flex-end; }
.firm-link { color: var(--accent-strong); text-decoration: none; font-size: 12.5px; font-weight: 500; padding: 5px 10px; border: 1px solid var(--border); border-radius: var(--radius-badge); display: inline-flex; align-items: center; gap: 6px; }
.firm-link:hover { background: rgba(var(--tint-rgb), .06); border-color: var(--line-strong); color: var(--accent-bright); }
/* FLACH STATT KASTEN (Owner «Widget», 2026-08-13): zwei getoente Kaestchen IN
   der Zeile. Sie tragen jetzt dasselbe Zeichen wie die Warnung des
   Konfigurators (`.kf-warn`, docs/design/patch-konfigurator.css): eine Akzentkante links statt
   einer Flaeche. Die Warnstufe bleibt ueber die Textfarbe voll erkennbar. */
.firm-card__notes { background: transparent; border: 0; border-radius: 0; box-shadow: inset 3px 0 0 var(--warn); padding: 8px 10px; font-size: 13px; color: var(--warn-strong); margin: 4px 0 0; }
.firm-card__schmerz {
  font-size: 12.5px; color: var(--text-secondary);
  background: transparent; border: 0; border-left: 0;
  box-shadow: inset 3px 0 0 rgba(var(--tint-rgb), .22);
  padding: 7px 10px; border-radius: 0; margin-top: 4px;
}
/* Toggle-Affordanz: kurzer Text + SVG-Chevron (currentColor via Mask) — kein Unicode-«▼» */
.card-toggle { display: inline-flex; align-items: center; gap: 4px; color: var(--text-secondary); font-weight: 500; font-size: 12.5px; }
.card-toggle::after {
  content: ""; width: 13px; height: 13px; flex: none; background: currentColor;
  -webkit-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'><path d='m6 9 6 6 6-6'/></svg>") center / contain no-repeat;
  mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'><path d='m6 9 6 6 6-6'/></svg>") center / contain no-repeat;
}
.firm-card:hover .card-toggle { color: var(--text-primary); }
/* Selektion: Accent-Inset links + Tint (keine Vollborder) */
.firm-card.firm-card--selectable { padding-left: 48px; position: relative; }
.firm-card__check { position: absolute; left: 0; top: 4px; width: 44px; height: 44px; display: grid; place-items: center; cursor: pointer; }
.firm-card__checkbox { cursor: pointer; }
/* Der gewaehlte Zustand bleibt vollstaendig sichtbar — er lebte nie vom
   Rahmen, sondern von der Akzentkante links und dem Tuerkis-Hauch (EINHEIT
   §4.4). Nur der abhebende `var(--surface)`-Grund und der Schlagschatten
   fallen weg: eine gewaehlte Zeile ist keine schwebende Karte. */
.firm-card.is-selected {
  background: linear-gradient(180deg, rgba(var(--accent-rgb),.07), rgba(var(--accent-rgb),.04));
  box-shadow: inset 2.5px 0 0 var(--accent);
}
@media (max-width: 720px) {
  .firm-card { padding: 14px 0; }
  .firm-card__contact { justify-content: flex-start; }
}

/* ---------- Listen-Zeilen (User-Modal u.a.) ---------- */
.user-leads-list, .user-appts-list { display: flex; flex-direction: column; gap: 6px; }
.lead-row, .appt-row {
  display: flex; gap: 12px; background: var(--surface-2); border: 1px solid transparent;
  border-radius: var(--radius-card); padding: 11px 13px; cursor: pointer;
  transition: background var(--transition), border-color var(--transition);
}
.lead-row:hover, .appt-row:hover { background: var(--surface-3); }
.lead-row__main { flex: 1; min-width: 0; }
.lead-row__heading, .appt-row__heading { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.lead-row__meta, .appt-row__meta { color: var(--text-secondary); font-size: 12.5px; margin-top: 3px; }
.lead-row__notes, .appt-row__note { font-size: 13px; margin: 6px 0 0; color: var(--text); padding: 6px 8px; background: rgba(var(--tint-rgb), .04); border-radius: var(--radius-card); }
.appt-row__note--feedback { background: rgba(var(--good-rgb),.09); }
.appt-row__time { display: flex; flex-direction: column; min-width: 76px; }
.appt-row__time strong { font-size: 14px; font-variant-numeric: tabular-nums; }
.appt-row__time span { font-size: 12px; color: var(--text-secondary); }

/* ---------- Pagination ---------- */
.pagination { display: flex; gap: 4px; justify-content: center; margin-top: 18px; flex-wrap: wrap; }
.page-btn {
  min-width: 36px; min-height: 36px; padding: 6px 10px;
  border-radius: var(--radius-button); border: 1px solid transparent;
  background: transparent; color: var(--text-secondary); font-weight: 600; cursor: pointer;
  font-variant-numeric: tabular-nums;
}
.page-btn:hover:not(:disabled) { background: rgba(var(--tint-rgb), .06); color: var(--text-primary); }
.page-btn.active { background: var(--accent-soft); color: var(--accent-strong); }
.page-btn:disabled { opacity: .4; cursor: not-allowed; }
@media (max-width: 1024px), (pointer: coarse) { .page-btn { min-width: 44px; min-height: 44px; } }

/* ---------- Tabellen ---------- */
.table-wrap {
  overflow-x: auto; border-radius: var(--radius-card);
  background:
    linear-gradient(to right,  var(--surface), rgba(20,20,20,0)) left  center / 24px 100% no-repeat local,
    linear-gradient(to left,   var(--surface), rgba(20,20,20,0)) right center / 24px 100% no-repeat local,
    radial-gradient(farthest-side at 0% 50%, rgba(var(--tint-rgb), .16), rgba(var(--tint-rgb), 0)) left  center / 14px 100% no-repeat scroll,
    radial-gradient(farthest-side at 100% 50%, rgba(var(--tint-rgb), .16), rgba(var(--tint-rgb), 0)) right center / 14px 100% no-repeat scroll;
}
.team-table { width: 100%; border-collapse: collapse; min-width: 640px; }
/* Die 640px sind das Haus-Muster — sie ergeben nur IM Scroll-Wirt einen Sinn.
   Steht die Tabelle ohne ihn (zehn Ansichten bauen sie so), schob ihre
   Mindestbreite bis 09.08. die ganze Seite seitwärts; mit dem Riegel oben
   (`overflow-x: clip`) wäre sie stattdessen rechts abgeschnitten und der Rest
   unerreichbar. Ohne Wirt bricht sie darum um, statt auszubrechen — der Inhalt
   bleibt vollständig lesbar. Wo ein `.table-wrap` steht, ändert sich nichts. */
:not(.table-wrap) > .team-table { min-width: 0; }
.team-table th, .team-table td { padding: 11px 12px; border-bottom: 1px solid var(--border); text-align: left; vertical-align: middle; }
/* W6.1 Dossier-Tuerschild: Knopf haelt die 44px-Tapflaeche (Gate 1n2). */
.team-table .ghost-btn { min-height: 44px; }
.team-table th {
  background: transparent; color: var(--text-tertiary);
  font-weight: 600; font-size: 11px; text-transform: uppercase; letter-spacing: .05em;
  border-bottom: 1px solid var(--line-strong);
}
.team-table tr:hover td { background: rgba(var(--tint-rgb), .025); }
.team-table tr:last-child td { border-bottom: 0; }
.team-table .team-role { background: var(--surface-inset); border: 1px solid var(--border); color: var(--text); padding: 6px 8px; border-radius: var(--radius-card); }
.team-table tr.is-inactive td { opacity: .55; }
.team-table tr.is-inactive strong { color: var(--text-secondary); font-weight: 600; }

/* ---------- Modals ---------- */
.modal-backdrop {
  position: fixed; inset: 0; background: rgba(4, 8, 12, .62); backdrop-filter: blur(10px);
  z-index: 100; display: grid; place-items: start center; padding: 24px; overflow-y: auto;
  animation: backdrop-in var(--dur) var(--ease);
}
@keyframes backdrop-in { from { opacity: 0; } to { opacity: 1; } }
/* Der kleine Bestätigungs-Dialog (components/app-dialog.js) hatte bis 09.08.
   KEINE eigene Regel und erbte darum die Geometrie der grossen, scrollenden
   Modale: `place-items: start center` — gebaut für ein Blatt, das den halben
   Bildschirm füllt. Eine Frage von drei Zeilen klebte damit oben am Rand, zwei
   Drittel darunter blieben leere Abdunklung (c3 B15, c5 B13). Sie gehört in
   die Mitte; am Handy an den Daumen, wo die Antwortknöpfe erreichbar sind.
   `--vv-unten` hält sie über einer offenen Tastatur (fragen()/formular()
   tragen Eingabefelder). */
.app-dialog { place-items: center; }
@media (max-width: 720px) {
  .app-dialog { place-items: end center; padding-bottom: calc(24px + var(--vv-unten, 0px)); }
}
.modal {
  width: 100%; max-width: 900px; background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-card); box-shadow: var(--shadow-lg); display: flex; flex-direction: column;
  max-height: calc(100vh - 48px); max-height: calc(100dvh - 48px);
  animation: modal-in var(--dur-slow) var(--ease);
}
@keyframes modal-in { from { opacity: 0; transform: scale(.975) translateY(6px); } to { opacity: 1; transform: none; } }
.modal--small { max-width: 560px; }
.modal__header { display: flex; justify-content: space-between; align-items: center; padding: 16px 20px; border-bottom: 1px solid var(--border); }
.modal__header h2 { margin: 0; font-size: 17px; font-weight: 600; letter-spacing: -.01em; }
.modal__body { overflow-y: auto; padding: 20px; display: grid; gap: 16px; }
.modal-section { background: rgba(var(--tint-rgb), .025); border: 0; border-radius: var(--radius-card); padding: 14px 16px; display: grid; gap: 10px; }
.modal-section h3 { margin: 0; font-size: 13px; font-weight: 600; color: var(--text-primary); letter-spacing: 0; text-transform: none; }
.modal-grid { display: grid; gap: 10px; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); }
.modal-actions { display: flex; gap: 10px; justify-content: flex-end; margin-top: 8px; flex-wrap: wrap; }
.info-card { background: var(--surface-2); border: 0; border-radius: var(--radius-card); padding: 10px 12px; }
.info-card strong { display: block; font-size: 11px; text-transform: uppercase; letter-spacing: .06em; color: var(--text-tertiary); margin-bottom: 3px; font-weight: 600; }
.info-card p { margin: 0; color: var(--text); font-size: 13.5px; }
.review-negative { background: rgba(var(--bad-rgb),.07); }
.review-negative strong, .review-negative p { color: var(--bad-strong); }
/* Iter 27 Welle F: Cyan-Verlauf → neutrale erhabene Fläche + Cyan-Hairline oben
   (DESIGN.md §3); Kontakt-Zeile im text-link-Ton statt Deko-Grün. */
.contact-hero {
  background: var(--surface-2); border: 0; border-radius: var(--radius-card);
  padding: 14px 16px; margin-bottom: 12px;
  
}
.contact-hero__name { font-size: 16px; font-weight: 600; color: var(--text-primary); margin-bottom: 2px; }
.contact-hero__role { color: var(--text-secondary); font-size: 12.5px; margin-bottom: 8px; }
.contact-hero__why { font-size: 13.5px; color: var(--text); line-height: 1.5; margin: 6px 0; padding: 9px 12px; background: rgba(var(--tint-rgb), .05); border-radius: var(--radius-card); }
.contact-hero__method { font-size: 13px; color: var(--accent-strong); font-weight: 500; margin-bottom: 4px; }
.contact-hero__strategy { font-size: 13px; color: var(--text-secondary); line-height: 1.5; border-top: 1px solid var(--border); padding-top: 8px; margin-top: 8px; }
.contact-hero__strategy strong { color: var(--text-primary); }
.pain-list { display: grid; gap: 8px; }
.pain-item { display: flex; gap: 10px; align-items: flex-start; background: rgba(var(--bad-rgb),.05); border: 0; border-radius: var(--radius-card); padding: 9px 12px; }
.pain-item p { margin: 0; font-size: 13.5px; }
.pain-item__dot { color: var(--low); font-weight: 800; }
.pitch-box { background: var(--surface-2); border: 0; border-radius: var(--radius-card); padding: 13px 14px; box-shadow: inset 2.5px 0 0 var(--accent); }
.pitch-box p { margin: 0; }
/* Zurückgehaltene Zusagen. Dieselbe Machart wie .firm-card__notes — Balken in
   Warnfarbe, kein Kasten —, damit der Befund als Randnotiz zum Einstieg
   liest und nicht als zweites Panel. */
/* Herkunft des Gespraechseinstiegs — keine Erklaerflaeche, sondern die Grenze,
   die der Berater im Gespraech einhalten muss. Leise gesetzt: er soll sie
   einmal lesen und dann wissen, nicht bei jedem Blick lesen muessen. */
.pitch-herkunft { margin: 7px 0 0; font-size: 12px; line-height: 1.45; color: var(--text-3); }
.pitch-befund { margin: 8px 0 0; padding: 9px 12px; background: rgba(var(--warn-rgb),.07); border-radius: var(--radius-card); box-shadow: inset 2.5px 0 0 var(--warn); }
.pitch-befund__kopf { margin: 0 0 6px; font-size: 12.5px; color: var(--warn-strong); }
.pitch-befund__liste { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }
.pitch-befund__liste li { font-size: 12.5px; line-height: 1.45; }
.pitch-befund__liste b { display: block; color: var(--warn-strong); font-weight: 600; }
.pitch-befund__liste span { color: var(--text-2); }
.competitors-list { display: grid; gap: 8px; }
.competitor-card { background: var(--surface-2); border: 0; border-radius: var(--radius-card); padding: 11px 13px; }
.competitor-card__header { display: flex; gap: 10px; align-items: center; margin-bottom: 6px; }
.competitor-card__number {
  display: inline-flex; align-items: center; justify-content: center; width: 22px; height: 22px;
  border-radius: var(--radius-card); background: rgba(var(--tint-rgb), .07); color: var(--text-secondary);
  font-size: 11.5px; font-weight: 700; flex-shrink: 0; font-variant-numeric: tabular-nums;
}
.competitor-card strong { color: var(--text-primary); }
.competitor-card p { margin: 0; color: var(--text-secondary); line-height: 1.5; font-size: 13px; }
.text-link { color: var(--accent-strong); }
.text-link:hover { color: var(--accent-bright); text-decoration: underline; }
.audit-score { margin: 0; font-size: 26px; line-height: 1; font-weight: 600; letter-spacing: -.02em; font-variant-numeric: tabular-nums; }
.hr-section { padding: 14px; border: 0; border-radius: var(--radius-card); background: rgba(var(--tint-rgb), .03); }

/* ---------- Toast (Iter 27 Welle F: Stack ≤3 + Icon nach Typ — toast.js) ---------- */
/* Ueber einer Cockpit-Flaeche sitzt unten der Fuss mit dem Total. Ein Toast
   auf 20px landete darin und wurde halb verdeckt — gesehen am 06.08. im Bild:
   «Rueckgaengig mit dem Knopf im Korb» ragte zur Haelfte hinter dem Fussband
   heraus. Eine Meldung, die man nicht lesen kann, ist keine Meldung.
   Der Fuss ist eine Fixleiste wie jede andere — er meldet seine Höhe an das
   Boden-System, statt dass fünf Regeln sie einzeln raten (09.08., c3 B16).
   `[data-cockpit]` trennt die Cockpit-Schale von der gleichnamigen
   Befehls-Palette (die Kollision steht bei style.css `.cp[data-cockpit]`). */
body:has(.cp[data-cockpit]) { --fuss-h: 64px; }
/* EINE Bodenrechnung statt fünf sich überbietender `bottom`-Regeln (:801,
   :1118, :3584, :12992, :12993 vor dem Umbau). Am Rechner ergibt sie
   `20px + var(--sab)` — exakt der bisherige Grundwert. */
.toast-stack {
  position: fixed; right: 20px; z-index: 200;
  bottom: calc(20px + var(--boden-abstand) + var(--fuss-h) + var(--vv-unten, 0px));
  display: flex; flex-direction: column; align-items: flex-end; gap: 8px;
  max-width: min(420px, calc(100vw - 32px)); pointer-events: none;
}
.toast {
  display: flex; align-items: flex-start; gap: 10px;
  background: var(--surface-2); border: 1px solid var(--border); color: var(--text);
  padding: 11px 14px; border-radius: var(--radius-card); box-shadow: var(--shadow-md); font-size: 13.5px;
  pointer-events: auto;
  transition: opacity var(--dur-slow) var(--ease), transform var(--dur-slow) var(--ease);
  animation: toast-in var(--dur-slow) var(--ease);
}
@keyframes toast-in { from { opacity: 0; transform: translateY(10px) scale(.98); } to { opacity: 1; transform: none; } }
.toast__ico { display: inline-flex; flex: none; margin-top: 2px; line-height: 0; }
.toast__ico svg { width: 15px; height: 15px; }
/* «Mein Vergleich» im Partner-Portal (04.08., Anschluss partner_benchmark). */
.pp-vergleich { margin: 0; padding: 12px 16px; font-size: 14px; color: var(--text-primary); }
.pp-vergleich__meta { display: block; margin-top: 4px; font-size: 12px; color: var(--text-tertiary); }

/* Der Aktions-Knopf im Toast (04.08.): «Rückgängig» statt Rückfrage. */
.toast__aktion {
  flex: none; margin-left: 10px; padding: 4px 10px; min-height: 28px;
  border: 1px solid var(--border); border-radius: var(--radius-card); background: none;
  color: var(--accent); font: inherit; font-size: 12.5px; font-weight: 600;
  cursor: pointer;
}
.toast__aktion:hover { background: var(--surface-hover); }
/* Der Schliess-Griff (Prüfblick W10 B-3): eine Meldung, die Bedienung
   verdecken kann, muss sich wegnehmen lassen — nicht nur ablaufen. */
.toast__zu {
  flex: none; display: grid; place-items: center; margin-left: 6px;
  width: 28px; height: 28px; border: 0; border-radius: var(--radius-card);
  background: none; color: var(--text-tertiary); cursor: pointer;
}
.toast__zu:hover { background: var(--surface-hover); color: var(--text-secondary); }
.toast__zu svg { width: 14px; height: 14px; }
@media (max-width: 1024px), (pointer: coarse) {
  .toast__aktion { min-height: 44px; padding: 8px 14px; }
  .toast__zu { width: 44px; height: 44px; }
}
.toast--error   { box-shadow: inset 2.5px 0 0 var(--bad), var(--shadow-md); }
.toast--error .toast__ico   { color: var(--bad-strong); }
.toast--info    { box-shadow: inset 2.5px 0 0 var(--accent), var(--shadow-md); }
.toast--info .toast__ico    { color: var(--accent-strong); }
.toast--success { box-shadow: inset 2.5px 0 0 var(--good), var(--shadow-md); }
.toast--success .toast__ico { color: var(--good-strong); }

/* ---------- Empty-State (Icon im Soft-Ring + Titel + Aktion) ---------- */
/* FLACH STATT KASTEN (Owner «Widget», 2026-08-13): der Leerzustand war ein
   gerundeter, eingelassener Kasten. Ein Satz, der sagt «hier ist nichts»,
   braucht keine Flaeche unter sich — er steht jetzt auf dem Grund, wie im
   Konfigurator (`.kf-leer`). Waagerechtes Padding faellt weg (Ausrichtung an
   der Spaltenkante), senkrecht bleibt es. */
.empty-state { padding: 34px 0; text-align: center; color: var(--text-secondary); border: 0; border-radius: 0; background: transparent; }
.empty-state__icon {
  display: grid; place-items: center; width: 42px; height: 42px; margin: 0 auto 12px;
  border-radius: 50%; background: var(--accent-soft); color: var(--accent-strong);
  box-shadow: 0 0 0 7px rgba(var(--accent-rgb), .05);
}
.empty-state__icon svg { width: 19px; height: 19px; }
.empty-state h3 { margin: 0 0 6px; color: var(--text-primary); font-size: 15px; font-weight: 600; }
.empty-state p { margin: 0; color: var(--text-secondary); font-size: 13.5px; line-height: 1.5; }
.empty-state p + p { margin-top: 10px; }
/* Die Wege unter dem Satz (03.09.2026, Owner-Farbwelt): zwei Knoepfe standen
   ohne Abstand aufeinander (Korb «Noch kein Gebiet», 1440 px). Eine Reihe mit
   Luft, die umbricht, wenn die Spalte schmal ist. */
.empty-state__tun { display: flex; flex-wrap: wrap; justify-content: center; gap: 8px; margin-top: 14px; }
.empty-state--inset { margin: 16px; }
.empty-state--compact { padding: 16px; }
.empty-state--compact .empty-state__icon { width: 36px; height: 36px; margin-bottom: 8px; }
/* ---------- Die SPALTEN-Fassung: am Rechner der Satz, am Handy der Block ---
   Sie stand bis zum 22.08.2026 als `.kf-leer` in patch-konfigurator.css und
   war die einzige der vierzehn Eigenbauten, die den Kanon nicht ERSETZTE,
   sondern ihn je nach Breite anders anzog. Genau deshalb gehoert sie hierher:
   was der Kanon kann, steht beim Kanon — ein Blatt, das ihn in seiner Flaeche
   neu einkleidet, ist eine zweite Bauart (scripts/_muster_test.mjs, 13b).
   WAS SIE TUT, unveraendert uebernommen (Wortlaut der abgeloesten Fassung):
   In einer schmalen Seitenspalte (der Konfigurator-Korb ist 210 px breit und
   kurz) traegt ein Icon-Ring mit Titel und zwei Knoepfen ~45 px Ueberlauf —
   der Waechter «keine Seitenspalte laenger als ihre Hoehe» misst das. Dort
   bleibt der Leerzustand darum der blosse Satz, linksbuendig, ohne Polsterung;
   die Wege sind auf dieser Breite ohnehin schon offen, weil alle Zonen
   nebeneinander stehen. Am Handy IST diese Zone der ganze Schirm — dort gilt
   das volle Muster (Icon-Ring, Titel, Wege), sonst stuenden ~350 px schwarz
   (Owner-Befund 5, 08.08.).
   FLACH STATT KASTEN (Owner «Widget», 13.08.): kein Grund, kein Radius —
   gruppiert wird allein durch Abstand.
   Reihenfolge: NACH `--compact`, dessen `padding: 16px` sie ueberschreibt
   (gleiche Spezifitaet, spaeter gewinnt). Die zweite, zeichengleiche
   `--compact`-Kopie am Dateiende ist dafuer gefallen. */
.empty-state--spalte {
  text-align: left; padding: 0; background: transparent; border-radius: 0;
}
.empty-state--spalte .empty-state__icon,
.empty-state--spalte .empty-state__tun,
.empty-state--spalte h3 { display: none; }
.empty-state--spalte p { margin: 6px 0 0; font-size: 11px; line-height: 1.45; color: var(--text-tertiary); }
/* Eigener Block NACH der Basis (Memory project_css_cascade_mobile), und er
   greift auch auf dem Tablet und an jedem groben Zeigegeraet (Memory
   project_tablet_touch_breakpoint). Die 1080px sind die Breite, ab der die
   Zonen des Konfigurators untereinander stehen. */
@media (max-width: 1080px), (pointer: coarse) {
  .empty-state--spalte {
    text-align: center; padding: 22px 16px; margin-top: 4px;
    background: transparent; border-radius: 0;
  }
  .empty-state--spalte .empty-state__icon { display: grid; }
  .empty-state--spalte h3 { display: block; margin: 0 0 6px; font-size: 15px; }
  .empty-state--spalte p { margin: 0; font-size: 13.5px; line-height: 1.5; color: var(--text-secondary); }
  .empty-state--spalte .empty-state__tun { display: grid; gap: 8px; margin-top: 14px; }
  .empty-state--spalte .empty-state__tun .primary-btn,
  .empty-state--spalte .empty-state__tun .ghost-btn {
    width: 100%; min-height: 44px; justify-content: center;
  }
}
/* ---------- Die ZEILE: ein ABSCHNITT ist leer, nicht die Flaeche ----------
   Gemessen am 21.08.2026: neben dem Block oben gab es diese zweite Aussage
   VIERZEHNMAL unter eigenem Namen — `.vk-leer` `.ck-leer` `.gz-leer`
   `.ao-leer` `.gb-leer` `.sp-leer` `.ag-leer` `.kb-leer` `.kk-leer` und die
   namenlose Fassung `.gz .empty-state` in patch-zentrale.css. Sechs Schriftgroessen
   (12/12.5/13/13.5px), zwei Farben (secondary/tertiary), fuenf Abstaende — fuer
   EINEN Satz. Der Beweis, dass es dieselbe Sache ist: `views/manager-today.js`
   und `views/zentrale.js` trugen denselben Helfer zeichengleich, nur mit
   anderem Klassennamen.
   Warum nicht der Block: EINHEIT.md 4.11 («einzeilig, und nur wenn wirklich
   leer»). 34px Luft mit Icon in einem Panel, das drei gefuellte Abschnitte
   hat, ist der Grund, warum die vierzehn Eigenbauten entstanden sind.
   Warum zwei Klassen im Selektor (0,2,0): drei Blaetter tragen einen eigenen
   `.X .empty-state`-Selektor und stehen in der Kaskade NACH dem Grundstock —
   mit nur `.empty-state--zeile` (0,1,0) haette die Zeile dort verloren.
   Werte: DESIGN.md §4 «Empty-State» (Body 13 secondary), Geometrie aus der
   groessten der abgeloesten Fassungen (`.vk-leer`, 28 Vorkommen). */
.empty-state.empty-state--zeile {
  margin: 0; padding: 6px 0; text-align: left;
  color: var(--text-secondary); font-size: 13px; line-height: 1.5;
}
/* WARUM NICHT DURCHGEHEND `flex`, wie es alle vierzehn Fassungen hatten:
   in einem Flex-Behaelter ist jeder Textknoten ein eigenes Element. Der
   Schlusspunkt hinter einem Link wurde damit zum eigenen Kind — und `gap: 8px`
   schob ihn ab. Im Bildschirmfoto vom 21.08. steht darum
   «… mit der ersten angenommenen Offerte .» mit sichtbarer Luecke vor dem
   Punkt (views/sales-customer-detail.js, Reiter Buchungen). Ein Satz mit
   Textlink ist Fliesstext und bleibt Fliesstext; die Reihe braucht es nur,
   wo ein KNOPF danebensteht und mittig sitzen muss. */
.empty-state.empty-state--zeile:has(.primary-btn),
.empty-state.empty-state--zeile:has(.ghost-btn) {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
}
.empty-state__weg { color: var(--accent-strong); font-weight: 600; text-decoration: none; }
.empty-state__weg:hover { color: var(--accent-bright); }
.empty-state__weg:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: var(--radius-card); }
/* Am Finger 44 — der Block steht NACH der Basis, sonst waere er wirkungslos
   (Memory `project_css_cascade_mobile`), und er greift auch auf dem Tablet
   (Memory `project_tablet_touch_breakpoint`). Uebernommen aus patch-chat.css
   Zeile 365, wo `.ao-leer a` das als einzige der vierzehn Fassungen hielt.
   WARUM NICHT `min-height: 44px`, wie die abgeloesten Fassungen es machten:
   gemessen am 21.08. auf 390px blaeht das den Absatz um 24.5px auf (51 → 75.5),
   weil ein `inline-flex`-Kind mit 44px Hoehe die ganze Zeilenbox mitzieht — im
   Fliesstext reisst das den Satz auseinander. In einer eigenen Reihe (die alten
   Fassungen waren alle `flex`) fiel das nicht auf; als Fliesstext schon.
   Padding schafft die Tapflaeche, der negative Rand nimmt sie aus der Zeilenbox
   wieder heraus: die Flaeche unter dem Finger ist 45.5px, die Zeile bleibt 51px.
   Gemessen mit getBoundingClientRect, nicht geschaetzt. */
@media (max-width: 1024px), (pointer: coarse) {
  .empty-state__weg {
    display: inline-block; padding-block: 13px; margin-block: -13px;
  }
}
/* Ein Knopf statt eines Links als Weg (Kundenportal, «Werbung buchen»): auf
   dem Handy volle Breite statt eines Restknopfs am Zeilenende — die Regel
   stand bis heute als `.kk-leer .primary-btn` in patch-kundenzentrale.css.
   NUR wo wirklich ein Knopf steht (`:has`, wie `.table-wrap table:has(…)`
   weiter oben) — eine Zeile aus Satz + Textlink bleibt eine Zeile und bricht
   von selbst um. */
@media (max-width: 720px) {
  .empty-state.empty-state--zeile:has(.primary-btn) { align-items: stretch; flex-direction: column; }
  .empty-state.empty-state--zeile .primary-btn { width: 100%; }
}
.load-error { color: var(--bad-strong); font-size: 13.5px; padding: 10px 2px; margin: 0; }
/* Buchhaltung · Abschluss: die eine positive Bilanz-Aussage (Welle 4.19). */
.lx-bilanzsumme { color: var(--text-secondary); font-size: 13.5px; padding: 10px 2px; margin: 0; }
/* Buchhaltung · Abschluss «Belege dahinter» (Owner-Befund 20.08.2026: «was
   schulden wir Monat X an Mehrwertsteuer pro Rechnung»). Die Aufklapp-
   Geometrie ist die des P&L-Drilldowns — dieselbe Frage, dasselbe Bauteil,
   darum steht `.lx-belege__monat` oben NEBEN `.pnl-block` statt in einer
   zweiten Fassung. Neu ist hier nur, was es dort nicht gibt. */
.lx-belege__monat + .lx-belege__monat { margin-top: 8px; }
.lx-belege__monat summary .panel-row__main { display: grid; gap: 2px; }
.lx-belege__block + .lx-belege__block { margin-top: 12px; padding-top: 10px; border-top: 1px solid var(--line); }
.lx-belege__block > .panel-row__meta { display: block; padding-bottom: 4px; }
.lx-belegzeile { padding-top: 6px; padding-bottom: 6px; }
/* Die Rundungsdifferenz ist ein HINWEIS, kein Befund: sie entsteht unter dem
   Saldosteuersatz zwangslaeufig, weil Monat und Periode je fuer sich runden.
   In Rot gelesen haette sie nach einem Fehler ausgesehen, den es nicht gibt. */
.lx-belege__diff { color: var(--warn-strong); }
/* Buchhaltung · Kontenplan: Vorschlagsliste beim Erfassen (Welle 4.19). */
.lx-katg-pflege { padding: 10px 2px 12px; border-bottom: 1px solid var(--line); display: grid; gap: 8px; }
.lx-katg-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.lx-katg-chip {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: 12.5px; padding: 4px 6px 4px 10px; border-radius: var(--radius-badge);
  background: rgba(var(--accent-rgb), .10); color: var(--text-primary);
}
.lx-katg-chip button {
  border: 0; background: none; color: var(--text-secondary); cursor: pointer;
  font-size: 14px; line-height: 1; padding: 4px 6px; border-radius: var(--radius-badge);
}
.lx-katg-chip button:hover { color: var(--bad-strong); background: rgba(var(--bad-rgb), .12); }
/* Aufgaben-Zeile: der Bezugs-Chip ist eine Tuer (Welle 4.15-Rest).
   28.08.2026 — GEMESSEN, ZUM ERSTEN MAL: 183.1 x 22 px, auf ALLEN NEUN
   Geraetebreiten. Der Waechter verlangt 24 px am Zeigergeraet und 44 px unter
   dem Finger; dieser Chip lag ueberall darunter. Sechs Monate lang war die
   Tuer von «Heute» zu einer Firma damit am Handy kaum zu treffen — und
   niemand sah es, weil «Heute» in KEINER Messliste dieses Hauses stand
   (nachgetragen am selben Tag, scripts/lib/fundament-buehne.mjs · SCHIRME).
   Er waechst echt statt nur die Trefferflaeche zu strecken: der Waechter
   misst getBoundingClientRect, und ein Pseudo-Element aendert die nicht —
   eine gestreckte Huelle waere hier gruen und in der Hand trotzdem zu klein.

   EINE Regel, kein Basis-plus-@media-Paar: in diesen Blaettern darf jeder
   Selektor genau EINMAL stehen (_stil_einmalig_test.mjs, Grundlinie 1043 —
   der zweite Eintrag liess sie auf 1044 steigen und hat die Auslieferung
   angehalten). 44 px erfuellen beide Grenzen des Waechters zugleich, die
   24 px am Zeigergeraet und die 44 unter dem Finger, und die Aufgabenzeile
   traegt neben dem Chip ohnehin den 44 px hohen Abhak-Knopf
   (.task-row__check) — die Zeilenhoehe aendert sich dadurch nicht. */
.task-row__bezug {
  display: inline-flex; align-items: center; gap: 4px;
  border: 0; padding: 4px 10px; margin: -2px 0; border-radius: var(--radius-card);
  min-height: 44px;
  background: rgba(var(--accent-rgb), .10); color: var(--accent-strong);
  font: inherit; font-size: inherit; cursor: pointer;
}
.task-row__bezug:hover { background: rgba(var(--accent-rgb), .18); }
.task-row__bezug svg { width: 12px; height: 12px; }
/* W2b 30.08.: Der Bezug OHNE offenen Weg (der Berater kommt nicht in die
   Kunden-Akte). Er bleibt die Auskunft, sieht aber nicht mehr aus wie eine
   Tuer — kein Akzent, kein Zeigefinger, kein Hover. Der Griffboden faellt
   mit: eine Textmarke braucht keine 44 px. */
.task-row__bezug--ohneweg {
  background: none; color: var(--muted); cursor: default;
  min-height: 0; padding: 0; margin: 0;
}
.task-row__bezug--ohneweg:hover { background: none; }


/* Buchhaltung · Uebersicht: die drei Wege unter den Zahlen (Welle 4.19). */
.lx-wegzeile { display: flex; flex-wrap: wrap; gap: 8px; margin: 10px 0 16px; }

/* ---------- Login ---------- */
.no-topbar { background: var(--bg); }
.login-shell {
  min-height: 100vh; min-height: 100dvh; display: grid; place-items: center; padding: 24px;
  background: radial-gradient(900px 520px at 50% -80px, rgba(var(--accent-rgb), .07), transparent 65%),
              var(--bg);
}
.login-card { max-width: 400px; width: 100%; padding: 36px 32px; background: var(--surface); box-shadow: var(--shadow-lg); }
.login-logo { color: var(--text); margin-bottom: 22px; }
.login-card .login-logo svg { width: 180px; }
.login-card h1 { margin: 4px 0 20px; font-size: 22px; font-weight: 600; letter-spacing: -.01em; }
.login-card form { display: grid; gap: 14px; }
.login-card .field input { padding: 11px 13px; background: var(--surface-inset); border: 1px solid var(--border); border-radius: var(--radius-button); color: var(--text); }
.login-card .field input:focus { border-color: var(--accent); outline: none; box-shadow: 0 0 0 3px rgba(var(--accent-rgb), .18); }
.login-error { color: var(--bad-strong); margin: 6px 0 0; font-size: 13.5px; }
.login-spinner { animation: none; }
/* S2: «Passwort vergessen?» / «Zurück zur Anmeldung» — Textlink-Optik auf einem
   echten <button> (Aktion, kein Ziel). Touch-Floor via min-height. */
.login-link {
  display: block; width: 100%; min-height: 44px; margin-top: 14px;
  background: none; border: 0; padding: 0;
  color: var(--text-secondary); font-size: 13.5px; cursor: pointer;
}
.login-link:hover { color: var(--accent-strong); }
.login-link:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: var(--radius-card); }
.loading { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 14px; min-height: 50vh; color: var(--text-secondary); font-size: 13.5px; }
.loading-spinner { opacity: .8; }

/* ---------- User-Pill / Profil ---------- */
.user-pill {
  display: flex; align-items: center; gap: 10px;
  background: transparent; border: 1px solid transparent;
  padding: 8px 11px; border-radius: var(--radius-button); font-size: 13.5px;
}
.user-pill__role { text-transform: uppercase; letter-spacing: .06em; font-size: 11px; color: var(--accent-strong); font-weight: 700; }
.user-pill strong { color: var(--text-primary); font-weight: 600; }
.profile-meta { display: grid; gap: 10px; }
.profile-meta > div { display: flex; justify-content: space-between; align-items: center; padding: 8px 0; border-bottom: 1px solid var(--border); }
.profile-meta > div:last-child { border-bottom: 0; }
.profile-meta strong { color: var(--text-tertiary); font-size: 11px; text-transform: uppercase; letter-spacing: .06em; font-weight: 600; }

/* ---------- Bulk-Bar (Pool) ---------- */
.bulk-bar {
  display: flex; justify-content: space-between; align-items: center; gap: 14px;
  padding: 12px 16px; margin-top: 10px;
  background: var(--surface-2); border: 0; border-radius: var(--radius-card);
  box-shadow: inset 2.5px 0 0 var(--accent), var(--shadow-sm);
  flex-wrap: wrap;
}
.bulk-bar__left { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.bulk-bar__left strong { font-size: 16px; color: var(--accent-strong); font-variant-numeric: tabular-nums; }
.bulk-bar__right { display: flex; align-items: end; gap: 10px; flex-wrap: wrap; }
.bulk-bar__right .field { min-width: 220px; }

/* ---------- User-Checkbox-Grid (Assign-Modal) ---------- */
.user-checkbox-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 8px; margin: 6px 0; }
.user-checkbox {
  display: flex; align-items: center; gap: 10px; padding: 10px 12px;
  background: var(--surface-2); border: 1px solid transparent; border-radius: var(--radius-card); cursor: pointer;
  transition: background var(--transition), border-color var(--transition);
}
.user-checkbox:hover { background: var(--surface-3); }
.user-checkbox__body { display: flex; flex-direction: column; gap: 4px; flex: 1; min-width: 0; }
.user-checkbox__body strong { font-size: 13.5px; }
.user-checkbox__body .badge { align-self: flex-start; }
.user-checkbox-actions { display: flex; gap: 6px; margin-top: 6px; }

/* ---------- Status-Strip (Modal) ---------- */
.status-strip { background: var(--surface-2); border: 0; border-radius: var(--radius-card); padding: 16px; box-shadow: inset 2.5px 0 0 var(--accent); }
.status-strip__row { display: flex; gap: 16px; justify-content: space-between; flex-wrap: wrap; }
.status-strip__row > div:first-child { display: flex; flex-direction: column; gap: 8px; }
.status-strip__meta { color: var(--text-secondary); font-size: 12.5px; }
.status-strip__actions { display: flex; gap: 10px; flex-wrap: wrap; align-items: end; }
.status-strip__notes { margin-top: 14px; display: grid; gap: 8px; }
.status-strip__notes-actions { display: flex; gap: 10px; flex-wrap: wrap; }

/* ---------- Gruppen-Header ---------- */
.export-list { display: grid; gap: 8px; margin: 8px 0 0; }

/* ---------- Kanban ---------- */
/* Erwartungswert der offenen Pipeline (pipeline_forecast) — EINE Zeile ueber
   dem Brett, nur im Umfang «Team». Sie traegt ihre ganze Rechnung mit, damit
   niemand die Zahl fuer eine Zusage haelt (FINISH-STANDARD 7). */
.pipeline-erwartung {
  margin: 0 0 10px; font-size: 12.5px; color: var(--text-secondary);
  font-variant-numeric: tabular-nums lining-nums;
}
.pipeline-erwartung b { color: var(--accent-strong); font-weight: 650; }
.kanban {
  display: grid; grid-auto-flow: column; grid-auto-columns: minmax(280px, 1fr); gap: 12px;
  overflow-x: auto; padding-bottom: 12px; -webkit-overflow-scrolling: touch; scroll-snap-type: x mandatory;
}
.kanban__col {
  scroll-snap-align: start; display: flex; flex-direction: column;
  background: rgba(var(--tint-rgb), .025); border: 0; border-radius: var(--radius-card);
  min-height: 200px; max-height: calc(100vh - 280px); max-height: calc(100dvh - 280px);
}
/* Iter 27 Welle B: Spalten-Tonfarbe als Punkt im Kopf (statt 3px-Farbborder oben) */
.kanban__header { display: flex; justify-content: space-between; align-items: center; padding: 11px 14px; border-bottom: 1px solid var(--border); }
.kanban__header h3 { font-size: 13px; }
.kanban__header strong { display: inline-flex; align-items: center; gap: 8px; font-size: 12.5px; font-weight: 600; letter-spacing: .01em; color: var(--text-primary); }
.kanban__header strong::before { content: ""; width: 8px; height: 8px; border-radius: 50%; flex: none; background: var(--tone, var(--text-tertiary)); }
.kanban__count { background: rgba(var(--tint-rgb), .07); color: var(--text-secondary); padding: 2px 9px; border-radius: var(--radius-badge); font-size: 11.5px; font-weight: 600; font-variant-numeric: tabular-nums; }
.kanban__items { flex: 1; overflow-y: auto; padding: 10px; display: flex; flex-direction: column; gap: 8px; }
.kanban__empty { color: var(--text-tertiary); text-align: center; margin: 20px 0 0; font-size: 13px; }
/* FLACH IM RUHEZUSTAND, ERHOBEN NUR BEIM ZIEHEN (Owner «Widget», 2026-08-13).
   Die Kanban-Karte BLEIBT eine Karte — sie ist das einzige Element der
   Software, das man wirklich anfasst und in eine andere Spalte zieht; ohne
   Kartenkoerper waere Ziehen und Ablegen nicht lesbar (Ausnahme bewusst
   getroffen und gemeldet). Was faellt, ist der Schlagschatten im RUHEZUSTAND:
   «schwebend» ist genau das Wort des Owners, und eine Karte, die liegt, soll
   nicht so aussehen wie eine, die man gerade haelt. `is-dragging` und
   `is-touch-clone` behalten ihren Schatten — dort ist er die Wahrheit. */
.kanban-card {
  background: var(--surface-2); border: 1px solid transparent; border-radius: var(--radius-button);
  padding: 11px 12px; cursor: pointer; box-shadow: none;
  transition: background var(--transition), transform var(--transition), box-shadow var(--transition);
}
.kanban-card:hover { background: var(--surface-3); transform: translateY(-1px); }
.kanban-card[draggable="true"] { cursor: grab; touch-action: pan-y; }
.kanban-card[draggable="true"]:active { cursor: grabbing; }
.kanban-card.is-dragging { opacity: 0.4; }
.kanban-card.is-touch-clone {
  position: fixed; z-index: 999; pointer-events: none; opacity: 0.94; transform: scale(1.03);
  box-shadow: var(--shadow-lg); border: 1px solid var(--accent-line); background: var(--surface-2);
}
.kanban__col.is-drop-target { outline: 2px solid var(--accent); outline-offset: -2px; background: rgba(var(--accent-rgb),.05); }
/* Die Akzentkante der Priorität bleibt — sie ist die Aussage. Nur der
   Schlagschatten daneben faellt (siehe `.kanban-card` oben). */
.kanban-card--hoch    { box-shadow: inset 2.5px 0 0 var(--high); }
.kanban-card--mittel  { box-shadow: inset 2.5px 0 0 var(--medium); }
.kanban-card--niedrig { box-shadow: inset 2.5px 0 0 var(--low); }
.kanban-card__head { display: flex; justify-content: space-between; align-items: flex-start; gap: 8px; margin-bottom: 6px; }
.kanban-card__head strong { font-size: 13.5px; line-height: 1.3; color: var(--text-primary); }
.kanban-card__meta { display: flex; gap: 6px; color: var(--text-secondary); font-size: 12px; flex-wrap: wrap; }
.kanban-card__meta .badge { font-size: 11px; padding: 2px 7px; }
.kanban-card__phone { color: var(--accent-strong); font-size: 12px; margin-top: 6px; font-variant-numeric: tabular-nums; }
.kanban-card__note { font-size: 12px; color: var(--text-secondary); margin: 6px 0 0; padding: 6px 8px; background: rgba(var(--tint-rgb), .04); border-radius: var(--radius-card); }
/* Welle 4.18: der nächste Schritt je Offerten-Zustand — leise Zeile am Kartenfuss. */
.kanban-card__next { margin: 6px 0 0; font-size: 11px; color: var(--text-tertiary); }
.kanban-card__last-call { font-size: 11px; color: var(--text-tertiary); margin-top: 6px; }
.kanban-phases { display: none; gap: 6px; overflow-x: auto; padding: 2px 0 10px; margin-bottom: 2px; -webkit-overflow-scrolling: touch; scrollbar-width: none; }
.kanban-phases::-webkit-scrollbar { display: none; }
.kanban-phase {
  flex: 0 0 auto; display: inline-flex; align-items: center; gap: 8px;
  min-height: 44px; padding: 8px 14px; border-radius: var(--radius-badge);
  border: 1px solid var(--border); background: var(--surface-2);
  color: var(--text-secondary); font: 600 13px/1 inherit; cursor: pointer; white-space: nowrap;
}
.kanban-phase__dot { width: 8px; height: 8px; border-radius: 50%; flex: none; }
.kanban-phase__count { background: rgba(var(--tint-rgb), .07); padding: 1px 8px; border-radius: var(--radius-badge); font-size: 12px; font-variant-numeric: tabular-nums; }
.kanban-phase[aria-current="true"] { background: var(--accent-soft); color: var(--accent-strong); border-color: var(--accent-line); }
.kanban-phase[aria-current="true"] .kanban-phase__count { background: rgba(var(--accent-rgb),.2); color: var(--accent-strong); }
@media (max-width: 720px) {
  .kanban { grid-auto-columns: minmax(88vw, 1fr); }
  .kanban__col { max-height: 70vh; }
  .kanban-card[draggable="true"] { touch-action: auto; }
  .kanban-phases { display: flex; }
}

/* ---------- User-Detail-Tabs ---------- */
.user-tabs { display: flex; gap: 2px; padding: 0 20px; border-bottom: 1px solid var(--border); overflow-x: auto; }
.user-tab {
  position: relative; background: transparent; border: 0; color: var(--text-secondary);
  padding: 11px 13px; cursor: pointer; font-weight: 500; font-size: 13.5px; white-space: nowrap;
  border-bottom: 2px solid transparent; margin-bottom: -1px;
}
.user-tab:hover { color: var(--text-primary); }
.user-tab.is-active { color: var(--text-primary); border-bottom-color: var(--accent); }

/* ---------- Conversion-Pills ---------- */
.conv-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 10px; margin-top: 14px; }
.conv-pill {
  display: grid; grid-template-columns: auto 1fr auto; gap: 10px; align-items: center;
  background: rgba(var(--tint-rgb), .03); border: 0; padding: 10px 14px; border-radius: var(--radius-card);
}
.conv-pill__label { color: var(--text-tertiary); font-size: 11px; text-transform: uppercase; letter-spacing: .06em; font-weight: 600; }
.conv-pill__bar { width: 100%; height: 6px; background: rgba(var(--tint-rgb), .07); border-radius: 3px; overflow: hidden; }
.conv-pill__fill { display: block; height: 100%; border-radius: 3px; transition: width .4s var(--ease); }
.conv-pill__pct { font-weight: 600; font-variant-numeric: tabular-nums; }
.status-filter-bar { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 12px; }
.status-filter-bar .ghost-btn--xs.is-active { background: var(--accent); color: var(--on-accent); border-color: var(--accent); }

/* ---------- Switch ---------- */
.switch { position: relative; display: inline-block; width: 40px; height: 22px; }
.switch input { opacity: 0; width: 0; height: 0; }
.switch span { position: absolute; cursor: pointer; inset: 0; background-color: var(--surface-3); border: 1px solid var(--border); transition: var(--dur-fast) var(--ease); border-radius: 999px; }
.switch span:before { position: absolute; content: ""; height: 16px; width: 16px; left: 2px; bottom: 2px; background: var(--text-secondary); border-radius: 50%; transition: var(--dur-fast) var(--ease); box-shadow: 0 1px 3px rgba(2,6,8,.4); }
.switch input:checked + span { background-color: var(--accent); border-color: var(--accent); }
.switch input:checked + span:before { transform: translateX(18px); background: #fff; }
.switch input:focus-visible + span { outline: 2px solid var(--accent); outline-offset: 2px; }

/* ---------- Kalender-Tag / Termin-Karten ---------- */
.appt-card { display: grid; grid-template-columns: 92px 1fr auto; gap: 14px; padding: 13px 16px; border-bottom: 1px solid var(--border); align-items: center; }
.appt-card:last-child { border-bottom: 0; }
@media (max-width: 720px) {
  .appt-card { grid-template-columns: 1fr; }
}

/* ---------- Activity ---------- */
.activity-log { display: grid; gap: 2px; }
.activity-item { display: grid; grid-template-columns: 140px 1fr auto auto; gap: 10px; padding: 8px 10px; border-radius: var(--radius-card); background: transparent; border-bottom: 1px solid var(--border); font-size: 13px; }
.activity-item:last-child { border-bottom: 0; }
.activity-item__time { color: var(--text-tertiary); font-variant-numeric: tabular-nums; font-size: 12px; }
.activity-item__who { color: var(--text); }
.activity-item__action { color: var(--accent-strong); font-weight: 600; }
.activity-item__details { color: var(--text-secondary); font-size: 12px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
@media (max-width: 720px) { .activity-item { grid-template-columns: 1fr; } }
.activity-feed { display: grid; gap: 0; }
.activity-feed__item { display: grid; gap: 3px; background: transparent; border: 0; border-bottom: 1px solid var(--border); border-radius: 0; padding: 10px 2px; font-size: 13px; }
.activity-feed__item:last-child { border-bottom: 0; }
.activity-feed__row { display: flex; gap: 10px; align-items: baseline; flex-wrap: wrap; }
.activity-feed__who { color: var(--text-primary); font-weight: 600; }
.activity-feed__role { color: var(--text-tertiary); font-size: 11px; text-transform: uppercase; letter-spacing: .05em; font-weight: 600; }
.activity-feed__action { color: var(--accent-strong); font-weight: 500; }
.activity-feed__firm { color: var(--text-secondary); }
.activity-feed__when { color: var(--text-tertiary); font-size: 12px; margin-left: auto; font-variant-numeric: tabular-nums; }

/* ---------- Termin-Formular ---------- */
.appt-form { display: grid; gap: 14px; }
.appt-grid { display: grid; gap: 12px; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); }
.appt-conflict-warn {
  background: rgba(var(--bad-rgb), .09); border: 0; box-shadow: inset 2.5px 0 0 var(--bad);
  color: var(--text); padding: 10px 12px; border-radius: var(--radius-card); font-size: 13px; line-height: 1.4; margin: 0;
}
.appt-conflict-warn strong { display: block; margin-bottom: 4px; }
.appt-conflict-warn ul { margin: 6px 0 4px 0; padding-left: 20px; }
.appt-conflict-warn li { margin: 2px 0; }
.appt-conflict-warn small { display: block; margin-top: 6px; color: var(--text-secondary); font-size: 12px; }
.appt-conflict-warn__status { color: var(--text-secondary); font-size: 12px; }

/* ---------- Responsive (Basis) ---------- */
@media (max-width: 900px) {
  .topbar { grid-template-columns: 1fr; align-items: start; }
  .sticky-filters { top: calc(var(--sat) + 8px); }
}
@media (max-width: 720px) {
  .main-shell, .topbar, .footer { padding-left: 14px; padding-right: 14px; }
  .panel__header { flex-wrap: wrap; }
  .panel__header .month-nav { width: 100%; order: 2; justify-content: space-between; }
  /* Der Bodenabstand steht in der Basis-Regel und rechnet aus den
     Höhen-Tokens (Block «Boden-Geometrie») — hier stand bis 09.08. eine
     geratene 80, die eine Zeile tiefer von einer geratenen 70 überstimmt wurde. */
  .main-shell { padding-top: calc(64px + var(--sat)); }
  .filters-toolbar { flex-direction: column; }
  .filters-group { flex-direction: column; align-items: stretch; }
  .field, .field--wide { min-width: 100%; width: 100%; }
  .logo { width: 148px; }
  .toast-stack { left: 14px; right: 14px; align-items: stretch; max-width: none; }
  .modal__body { min-height: 0; -webkit-overflow-scrolling: touch; }
  .modal-actions {
    position: sticky; bottom: 0; z-index: 2; background: var(--surface);
    margin-top: 4px; padding: 12px 0 calc(6px + env(safe-area-inset-bottom));
    border-top: 1px solid var(--border);
  }
  /* ⚠️ DIE HANDLUNGSZEILE WAR EINE KARTE MITTEN IM FORMULAR, KEIN FUSS.
     GEMESSEN am 30.08.2026 auf 390×620, echter «Neuer Kunde»-Dialog auf der
     Fundament-Bühne:
       Dialog  12 – 608 px      Leib (.modal__body, padding: 20px)  72 – 607 px
       Zeile   33 – 357 px breit, 524 – 587 px hoch
     Zwei Löcher, beide aus derselben Wurzel — die Zeile klebt INNEN im
     rollenden Leib, und ein klebender Kasten ist an den INHALTS-Kasten seines
     Vaters gefesselt, während der Leib erst am POLSTER-Kasten abschneidet:
       · unten  20 px Formular laufen UNTER der Zeile weiter sichtbar durch
                (587 → 607). Im Bild «13-kundenformular»: das «CH» des
                Land-Feldes lugt unter «Kunde anlegen» hervor; im Bild
                «06-terminfenster» steht «Telefon vor Ort» unter
                «Abbrechen / Termin speichern». Genau das liest ein Mensch als
                «der Knopf schwebt mitten im Formular».
       · seitlich je 20 px: die Zeile ist 324 px breit in einem 366 px breiten
                Dialog. Die Trennlinie oben hört vor dem Rand auf — eine Karte,
                kein Fuss.
     DIE REPARATUR IST DIESELBE ZWEIMAL: der Fuss trägt den unteren Rand des
     Dialogs SELBST (der Leib gibt sein Bodenpolster ab, aber nur wenn die
     Zeile wirklich das Letzte ist), und er greift mit negativen Seitenrändern
     über die Seitenpolster hinweg bis an die Dialogkante.
     Der Rollplatz bleibt gleich gross: die Zeile behält ihren Platz im Fluss
     (`sticky` verschiebt, es nimmt nichts weg), das letzte Feld ist also
     weiterhin ganz erreichbar — gemessen: am Ende des Rollwegs liegt kein
     Feld mehr hinter der Zeile.
     WAS BEWUSST NICHT: die 60 Rufer bleiben unberührt. Dies ist EIN Ort,
     nicht 60 Dialoge — `.mini-modal__footer` (weiter oben) baut denselben Fuss
     schon richtig, als echtes drittes Kind des Kastens. */
  /* «Das Letzte» heisst: nichts SICHTBARES steht mehr dahinter. `:last-child`
     allein war zu eng — der Bestätigungs-Dialog des Hauses
     (components/app-dialog.js, 52 Rufer) hängt hinter die Handlungszeile eine
     Fehlerzeile, die meistens `hidden` ist. Mit `:last-child` allein bekäme
     ausgerechnet der meistbenutzte Dialog seinen Fuss nicht; wird die
     Fehlerzeile sichtbar, nimmt die Regel das Bodenpolster von selbst wieder
     her — dann steht wirklich etwas dahinter.
     ⚠️ NICHT SCHÖNER SCHREIBEN: `:has(… :not(:has(~ …)))` wäre die kürzere
     Formulierung und ist UNGÜLTIG — `:has()` darf nicht in `:has()` stehen.
     Gemessen am 30.08.2026 in beiden Motoren: der ganze Regelblock fiel
     lautlos aus, das Bodenpolster blieb bei 20 px, und der Fuss hing wieder
     20 px über dem Dialogboden. Ein ungültiger Wähler sagt nichts, er
     schweigt. */
  /* ⚠️ 30.08.2026, ZWEITER GRIFF (Pruefer): DIE ZWEI REGELN MUESSEN DIESELBE
     BEDINGUNG TRAGEN. Die Bedingung stand nur an der ersten (Bodenpolster
     weg); die zweite — volle Breite, unten abgerundet, also die GESTALT eines
     Fusses — galt für JEDE Handlungszeile im Leib. Gemessen an diesem Tag auf
     390×620 in beiden Motoren, mit dem Markup aus den benannten Quellzeilen:
       · views/sales-inventory.js:346 — hinter der Zeile steht ein sichtbarer
         Hinweissatz. Der Balken lag randlos über die ganze Dialogbreite,
         72 px ÜBER dem Dialogboden, und der Satz lief darunter weiter.
       · components/availability-heatmap.js:211 — dahinter ein leerer
         Steckplatz. Randloser Balken, 37 px über dem Boden, darunter nichts.
     Beides ist genau das Bild, das dieser Block beenden sollte («der Knopf
     schwebt mitten im Formular») — mit der Randlosigkeit sogar deutlicher,
     weil ein randloser Balken mit unterer Rundung UNMISSVERSTAENDLICH «hier
     endet der Dialog» sagt. Wo die Zeile NICHT das Letzte ist, sieht sie ab
     hier wieder aus wie vorher: eine Zeile im Fluss, im Seitenpolster.
     UND «das Letzte» kennt jetzt auch den LEEREN Nachbarn (`:empty`) — der
     Steckplatz der Heatmap ist im Ruhezustand ein Knoten ohne Inhalt, also
     steht nichts dahinter; wird er gefuellt, faellt die Regel von selbst
     wieder weg, genau wie bei der sichtbar werdenden Fehlerzeile. */
  .modal__body:has(> .modal-actions:last-child),
  .modal__body:has(> .modal-actions + :is([hidden], :empty):last-child),
  .modal__body:has(> form > .modal-actions:last-child),
  .modal__body:has(> form > .modal-actions + :is([hidden], :empty):last-child) { padding-bottom: 0; }
  .modal__body:has(> .modal-actions:last-child) > .modal-actions,
  .modal__body:has(> .modal-actions + :is([hidden], :empty):last-child) > .modal-actions,
  .modal__body:has(> form > .modal-actions:last-child) > form > .modal-actions,
  .modal__body:has(> form > .modal-actions + :is([hidden], :empty):last-child) > form > .modal-actions {
    margin-left: -20px; margin-right: -20px;
    padding: 12px 20px calc(12px + env(safe-area-inset-bottom));
    border-radius: 0 0 var(--radius-card) var(--radius-card);
  }
  /* Ein LEERER Steckplatz hinter dem Fuss ist im Gitter trotzdem eine Zeile:
     `.modal__body` ist `display: grid; gap: 16px`, also hing der Fuss auch
     ohne Inhalt noch 17 px über dem Dialogboden (gemessen 30.08.2026, beide
     Motoren). Solange nichts drinsteht, nimmt er auch keinen Platz; sobald
     das Modul ihn füllt, greift `:empty` nicht mehr und er ist wieder da —
     dann steht wirklich etwas hinter dem Fuss, und das Bodenpolster oben
     kommt im selben Zug zurück. */
  .modal__body > .modal-actions + :empty:last-child,
  .modal__body > form > .modal-actions + :empty:last-child { display: none; }
  .bulk-bar { flex-direction: column; align-items: stretch; }
  .bulk-bar__right { width: 100%; }
  .view-toggle { width: 100%; overflow-x: auto; flex-wrap: nowrap; -webkit-overflow-scrolling: touch; }
  .view-toggle__btn { flex: 0 0 auto; }
  .section-nav { width: 100%; overflow-x: auto; flex-wrap: nowrap; -webkit-overflow-scrolling: touch; }
  .section-nav__btn { flex: 0 0 auto; white-space: nowrap; }
  .activity-feed__row { gap: 6px; }
  .activity-feed__when { margin-left: 0; flex: 1 1 100%; }
  .view-switch { width: 100%; overflow-x: auto; white-space: nowrap; -webkit-overflow-scrolling: touch; flex-wrap: nowrap !important; }
  .view-switch .nav-tab { padding: 8px 12px; flex: 0 0 auto; }
}
@media (max-width: 520px) {
  .view-switch { width: 100%; }
  .nav-tab { flex: 1 1 auto; }
}
@media print {
  body { background: white; color: black; }
  .topbar, .footer, .filters-panel, .pagination, .modal-backdrop, .sidebar, .sidebar-toggle { display: none !important; }
  .firm-card, .panel { box-shadow: none; border: 1px solid #ccc; background: white; color: black; }
  /* AUFS PAPIER GEHOERT NUR DAS DOKUMENT.
     Prüfer-Bedien-Beweis 13.08.2026, Handy 390 px: das Offerten-Dokument hat
     4 Blätter, die Vorschau zeigt 4, der Download hat 4 — der BROWSER-DRUCK
     hatte 5. Die fünfte war fast leer und trug nur die Fusszeile von Blatt 1.
     Wurzel: das Einladungsband «Als App aufs Handy» (`.lx-install`, seit
     utils/installation.js) und der Toast standen im Druckfluss und schoben
     Blatt 1 über den Seitenumbruch. Am Rechner fiel es nie auf — das Band
     erscheint nur auf dem Telefon. Damit verletzte der Druck genau zwei
     Owner-Regeln auf einmal: «keine fremde oder leere Zwischenseite» und
     «Vorschau == Download == Druck». Nachgemessen nach dieser Regel: 4 = 4 = 4
     auf beiden Breiten. */
  .lx-install, .lx-vorschau, .skip-link,
  .toast-stack, #lx-offline, #lx-unten, .subnav { display: none !important; }
}
/* ============================================================
   Iter 8.1 — Dashboard-Upgrade
   ============================================================ */

/* Kennzahl-Kacheln (Referenz 28.07.): eigene Karte je Zahl, grosse Zahl
   oben, kleines Label darunter, optional schlanker Balken. Der Streifen ist
   nur noch das Raster — trägt das Markup zusätzlich .panel, wird dessen
   Fläche neutralisiert (sonst Karte in Karte). */
/* EINE KACHEL-BAUART (Owner-Urteil 2026-08-25, «kein Leben, keine Ahnung, was»).
   GEMESSEN im Browser ueber 29 gebaute Flaechen bei 1400px: dieselbe Sache —
   «eine Kennzahl zeigen» — stand in ZEHN verschiedenen Gestalten da, verteilt
   auf sieben Klassen (`.stat`, `.gz-kachel`, `.vk-kachel`, `.la-kachel`,
   `.lx-stat`, `.mi-kachel`, `.bs-kachel`): drei Wertgroessen (22/26/27), drei
   Radien (0/12/14), drei Flaechen (keine / `--surface-1` / `--surface`), vier
   Polsterungen. Offerten und Rechnungen sind Nachbarreiter und hatten
   verschiedene Kacheln.

   DIE WURZEL steht woertlich in `public/src/components/kennzahl-kachel.js`:
   das Bauteil vereinheitlicht das VERHALTEN fuer 51 Aufrufer («Die Flaeche
   liefert ihr Symbol-HTML fertig mit ihren eigenen Klassen … dieses Modul
   erfindet kein Aussehen und bringt kein eigenes CSS mit»). Genau darum
   erfand jede Flaeche ihres.

   DIE EINE GESTALT WIRD NICHT ERFUNDEN, SIE WIRD GEWAEHLT: `.lx-stat`
   (weiter unten in dieser Datei) war die einzige der sieben Varianten, die
   der Referenz entspricht — eigene Flaeche `--surface`, Haarlinie,
   `--radius-card` (14), `padding: 18px`, Wert 26px. Die Referenz zeigt
   genau das: docs/design/referenzen/Kundenansichtenportal/«… 13_21_30 (12).png»,
   die vier Kennzahl-Karten oben (Symbol im Soft-Feld, Label, grosse Zahl,
   Delta, Fusszeile — jede eine Karte mit echter Fuge dazwischen).
   `.stat` uebernimmt diese Gestalt; die sechs anderen Klassen bleiben als Ort
   fuer echte Ausnahmen bestehen und verlieren nur ihr eigenes Aussehen.

   `gap: 14px` statt 0: die Karte traegt ihre Kante selbst, eine geteilte
   Haarlinie waere ab jetzt eine doppelte.

   ENTFERNT (einzeln genannt, Rueckweg git): die vier Rest-Strich-Regeln
   `.stat-strip:not(.stat-strip--auto) > .stat:nth-child(3n+1|n+4|2n+1|n+3)`
   in den beiden Geraete-Bloecken unten. Sie haben die linke Haarlinie beim
   Zeilenumbruch weggenommen und eine obere gesetzt — mit einer rundum
   geschlossenen Karte wuerden sie ihr die linke Kante ausschneiden. */
.stat-strip { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 200px), 1fr)); gap: 14px; padding: 0; margin-bottom: 18px; }
.panel.stat-strip { background: transparent; border: 0; box-shadow: none; padding: 0; }
.stat {
  container-type: inline-size; min-width: 0;
  display: flex; flex-direction: column; gap: 3px; padding: 18px;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-card); text-decoration: none; color: inherit;
  transition: background var(--transition), border-color var(--transition);
}
/* ENTFERNT 25.08. (Rueckweg git): `.stat:first-child { border-left: 0;
   padding-left: 0 }`. Die Regel liess die erste Kachel an derselben Kante wie
   der Seitentitel beginnen — mit eigener Karte ist genau das falsch, und ihre
   hoehere Spezifitaet stach am Handy sogar die 16px-Polsterung des
   Geraete-Blocks durch: gemessen am 390er-Bild vom 25.08. lief «CHF 1'200.00»
   im Vertriebsportal 14px aus der ersten Karte, waehrend die beiden Nachbarn
   passten. */
/* Nur was eine Tuer IST, leuchtet unter der Maus auf. Eine reine Anzeige, die
   auf Hover die Flaeche wechselt, behauptet eine Bedienbarkeit, die es nicht
   gibt. Mit eigener Karte ist der Hover die Hover-Flaeche des Hauses. */
a.stat:hover { background: var(--surface-hover); border-color: var(--line-strong); }
.stat:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* DAS LABEL WIRD NICHT MEHR ABGESCHNITTEN (25.08.2026). `nowrap` + Ellipse
   stammt aus der Zeit, als die Kacheln kantenbuendig standen und jede Zeile
   exakt gleich hoch bleiben musste. Mit Karte und Fuge streckt das Raster die
   Zeile ohnehin auf die hoechste Kachel — die Ellipse kostete also nur Wort.
   Gemessen am Bild vom 25.08. («bereich-akquise-1400.png»): «Wiedervorlagen
   he…» statt «Wiedervorlagen heute». Genau das nennt patch-zentrale.css
   selbst «das Billige, das hier weg soll». Jetzt zwei Zeilen, dann erst der
   Deckel — die Hoehe bleibt begrenzt, das Wort bleibt lesbar. */
.stat__label {
  color: var(--text-secondary); font-size: 12.5px; font-weight: 500; letter-spacing: 0;
  white-space: normal; overflow: hidden; text-overflow: ellipsis;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
}
.stat__value { font-size: clamp(18px, 12cqi, 26px); white-space: normal; font-weight: 650; letter-spacing: -.5px; line-height: 1.12; font-variant-numeric: tabular-nums lining-nums; color: var(--text-primary); }
/* Iter 35 Puls: gedämpfte Zusatzzeile unter dem Wert («2 von 5 offenen») */
.stat__sub { color: var(--text-tertiary); font-size: 11.5px; line-height: 1.3; font-variant-numeric: tabular-nums; }
/* Schlanker Fortschrittsbalken in der Kachel (Referenz «3 von 4 laufen») */
.stat__bar { height: 4px; border-radius: 2px; background: rgba(var(--tint-rgb), .12); margin-top: 12px; overflow: hidden; }
.stat__bar > i { display: block; height: 100%; background: var(--accent); border-radius: 2px; }
/* Der Umbruch braucht seit 25.08. keine Rest-Strich-Regeln mehr: die Kachel
   ist rundum geschlossen, die Fuge (`gap`) trennt in beide Richtungen. Die
   vier `nth-child`-Regeln, die hier die linke Haarlinie ab- und eine obere
   angeschaltet haben, sind darum entfallen — sie wuerden der Karte die linke
   Kante ausschneiden. Both strip variants now fill the available width;
   narrow viewports retain the existing two-column layout below. */
/* DAS GLEICHE RASTER — der Kennzahlen-Streifen am Telefon (05.09.2026)
   ---------------------------------------------------------------------------
   ERSETZT «DIE EINE ZEILE» vom 04.09.2026 (Rollreihe, hier gestanden bis
   heute). Sie fiel am eigenen Geraet des Eigentuemers: «auf dem Smartphone ist
   alles ueberlappend … keine Einheitlichkeit, keine Symmetrie» (05.09.).
   NACHGEMESSEN an den Live-Bildern (390 px, beide Motoren): auf den Offerten
   stand die dritte Kachel als «CHF 0.0(» am Rand, auf den Rechnungen
   «Bezahlt (CHF)» halb — und die VIERTE Kachel («Rechnungen», der Rueckweg aus
   jedem Ausschnitt) lag ganz ausserhalb des Bildes. Ein Rollweg macht
   erreichbar, was angeschnitten dasteht; sichtbar macht er es nicht.

   DIE BEGRUENDUNG VOM 04.09. IST HIERMIT ERSETZT, nicht danebengeschrieben:
   sie berief sich auf die Akten-Referenz «13_25_56 (1).png» (acht Kennzahlen in
   EINER flachen Reihe). Die gilt fuer die AKTE AM SCHREIBTISCH. Fuer das
   Telefon gilt das iPhone in docs/design/referenzen/Portaluikomplett/«ChatGPT
   Image 29. Juli 2026, 13_25_27.png»: dort stehen die Kennzahlen als
   gleichmaessiges 2x2-Raster, gleich gross, nichts angeschnitten, kein Rollweg.

   UEBERNOMMEN SIND DIE QUALITAETEN, nicht die Bauteile:
   (1) SYMMETRIE — in einer Reihe ist jede Kachel gleich gross; das Raster
       streckt die Zeile ohnehin auf die hoechste Kachel.
   (2) NICHTS ANGESCHNITTEN — zwei Spalten passen auf 390 px, drei nicht:
       390 - 32 Rand - 2x8 Fuge = 342 / 3 = 114 px je Kachel, davon 22 px
       Polsterung und 2 px Kante -> 90 px fuer «CHF 12'345.00», das bei 20 px
       104 px misst. Bei zwei Spalten bleiben 167 px je Kachel, also Luft.
   (3) KEINE HALB LEERE REIHE — eine ungerade letzte Kachel nimmt beide
       Spalten: 3 -> 2+1, 5 -> 2+2+1; gerade Mengen ergeben 2x2 bzw. 2x3.

   DIE HOEHE, DIE DER 04.09. GEWONNEN HAT, BLEIBT: flach ist flach (Zeichen und
   Unterzeile schweigen weiter, 44 px Mindesthoehe). Vier Kennzahlen messen
   damit 2 x 44 + 8 = 96 px statt der 114 px der alten 2x2-Fassung — und ihre
   vierte ist nicht mehr weggerollt.

   Die Feinregeln sind auf `.stat-strip …` GESCHACHTELT, nicht auf `.stat`
   allein: eine Einzel-Kachel ausserhalb eines Streifens (`.stat--well` im
   P&L) behaelt ihre Polsterung und ihre 22 px. */
@media (max-width: 640px) {
  .stat-strip {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    grid-auto-flow: row;
    gap: 8px; margin-bottom: 8px;
  }
  .stat-strip > * { min-width: 0; }
  .stat-strip > *:last-child:nth-child(odd) { grid-column: 1 / -1; }
  .stat { padding: 15px 16px; }
  .stat__value { font-size: 22px; }
  /* Flach: das Zeichen und die Unterzeile SCHWEIGEN am Telefon — sie
     verschwinden nicht aus dem Haus, am Schreibtisch stehen beide weiter da.
     Eine Kachel ohne sie ist 52 statt 66 px hoch. */
  .stat-strip > .stat { min-height: 44px; padding: 8px 11px; gap: 1px; }
  .stat-strip > .stat > .gz-ic,
  .stat-strip .stat__sub:not(.stat__sub--bleibt) { display: none; }
  /* DIE AUSNAHME, DIE DIE REGEL BRAUCHT (06.09.2026). Eine Unterzeile, die
     ERGAENZT, darf am Telefon schweigen — dafuer steht die Zeile darueber.
     Eine, die die Zahl ueber sich EINSCHRAENKT, darf es nie: «4'000.00» mit
     verschwiegenem «1 Uebung nicht gezaehlt» ist eine andere Zahl als
     «4'000.00». Gemessen am 390er-Bild der Rechnungsliste: der Satz stand am
     Schreibtisch da und fehlte am Telefon — auf dem Geraet, auf dem der Owner
     wirklich arbeitet. `vermittlungen.js:424` hatte genau das notiert
     («Anders als bei den Offerten und Rechnungen …») und liegen lassen; ein
     bekannter Fehler ist ein Auftrag, kein Vermerk. Dieselbe Ausnahme steht in
     patch-verkauf.css und patch-offertenliste.css — Waechter:
     `npm run test:einschraenkung`. */
  /* DIE ZAHL DARF UMBRECHEN — ABER NUR AN EINER LUECKE. Gemessen 04.09.: die
     Kachel «Kosten/Tag trotz Verzug» (bis 06.09. «Partner-Exposure/Tag»; die
     erste deutsche Fassung «Kosten trotz Verzug (CHF/Tag)» war 29 Zeichen
     lang und hob den Kachelblock am Telefon auf 208 px — gemessen von
     `test:handy-verkauf:ui`, das dabei ZWEI Proben zugleich kippte)
     traegt keinen Wert, sondern einen SATZ
     («bis zu CHF 80.00»): 152 px in einem 88 px breiten Kasten, und er lief
     stumm ueber die Kante, weil `.stat__value` `nowrap` traegt. `normal`
     bricht ihn an der Luecke. KEIN `overflow-wrap: anywhere`, KEIN «…» —
     genau das war der Schaden vom 11.08. («CHF 5'600.0 / 0», «ANGENOMM…»).
     Im 2-Spalten-Raster misst eine Kachel 167 px; die Geldzahl bricht damit
     ohnehin nicht mehr. */
  .stat-strip .stat__value { font-size: clamp(16px, 12cqi, 20px); line-height: 1.15; white-space: normal; }
  .stat-strip .stat__label { font-size: 11px; letter-spacing: .04em; }
}
/* 25.08.: auf dem echten Geraet (390px) sind zwei Karten je Reihe 155px breit.
   Die Kante kostet 2px, die Polsterung 32px — es blieben 121px fuer «CHF
   1'200.00», das bei 20px 131px braucht (gemessen, scripts/_fundament_bilder
   meldete «+10px aus dem Kasten»). Darum eine Stufe enger: 14px Polsterung.
   Die Geldzahl bleibt eine Zahl (`nowrap` aus patch-vertraege.css) — genau
   die dort begruendete Entscheidung, «eine zerrissene Geldzahl ist schlimmer
   als eine kleinere». */
@media (max-width: 420px) {
  .stat { padding: 14px; }
}

/* Panel-Titel-Zusatz: gedämpfter Inline-Hinweis statt Eyebrow-Kicker */
.panel__hint { color: var(--text-tertiary); font-size: 12px; font-weight: 500; letter-spacing: 0; margin-left: 6px; }

/* Hier standen die Bausteine des alten Manager-Dashboards — Flow-Leiste,
   Performance-Top5, Runden-Mini-Cards, Playbook/Referenz-Panels, Idle-Warnung.
   Keiner hatte am 03.08.2026 noch einen Traeger in public/src; sie sind mit dem
   Redundanz-Pass gefallen. Rueckweg: git. */

/* ============================================================
   Iter 9 Etappe 12 + 14: Activity-Timeline + Time-Range-Tabs
   ============================================================ */
/* Iter 27 Welle B: Zeitraum-Pills = Segmented-Track mit Thumb (statt solid-Cyan-Pills) —
   EIN Aktiv-Stil app-weit (wie .seg__btn.is-active / .view-toggle__btn.is-active). */
.time-range-tabs {
  display: inline-flex; flex-wrap: nowrap; gap: 2px; padding: 3px;
  background: var(--surface-inset); border: 1px solid var(--border); border-radius: var(--radius-card);
  max-width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; scrollbar-width: none;
}
.time-range-tabs::-webkit-scrollbar { display: none; }
.time-pill {
  flex: 0 0 auto; background: transparent; color: var(--text-secondary); border: 0;
  padding: 6px 13px; min-height: 32px; border-radius: var(--radius-button);
  font-size: 12px; font-weight: 650; letter-spacing: 0; text-transform: none; cursor: pointer;
  transition: background var(--transition), color var(--transition);
}
.time-pill:hover { background: transparent; color: var(--text-primary); }
.time-pill.is-active {
  background: var(--accent-soft); color: var(--text-primary);
  box-shadow: inset 0 0 0 1px var(--accent-line);
}
.time-range-custom { display: flex; gap: 10px; margin-top: 8px; }
.time-range-custom .field { min-width: 140px; }

.filters-toolbar--activity {
  display: grid; gap: 12px;
}
.time-range-slot { width: 100%; }

.activity-timeline {
  display: grid; gap: 18px; padding: 16px;
}
.activity-day {
  display: grid; gap: 8px;
}
.activity-day__title {
  margin: 0; font-size: 13px; font-weight: 700; letter-spacing: .12em;
  text-transform: uppercase; color: var(--text-secondary);
  display: flex; align-items: center; gap: 10px;
}
.activity-day__count {
  background: var(--surface-2); color: var(--text); border-radius: var(--radius-badge);
  padding: 1px 10px; font-size: 11px; font-weight: 600; letter-spacing: 0;
  text-transform: none;
}
.activity-day__list {
  list-style: none; padding: 0; margin: 0; display: grid; gap: 4px;
}
.activity-item-row {
  display: grid; grid-template-columns: 64px 180px 180px 1fr auto;
  gap: 12px; padding: 10px 12px; align-items: center;
  background: var(--surface-1); border: 1px solid var(--border); border-radius: var(--radius-card);
  font-size: 13px;
}
.activity-item-row--clickable { cursor: pointer; }
.activity-item-row--clickable:hover { background: var(--surface-2); border-color: rgba(var(--accent-rgb),.3); }
.activity-item-row__time { font-variant-numeric: tabular-nums; color: var(--text-secondary); font-size: 12px; }
.activity-item-row__user { display: flex; gap: 6px; align-items: center; min-width: 0; overflow: hidden; }
.activity-item-row__user strong { font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.activity-item-row__action { color: var(--text); font-weight: 500; }
.activity-item-row__firm { color: var(--accent); font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.activity-item-row__detail { color: var(--text-secondary); font-size: 12px; }
.activity-item-row__detail em { font-style: normal; }

.activity-loadmore { padding: 14px; text-align: center; }

/* C-01: eine lesbare Fallwahrheit statt Modul-Suche. */
.case-summary {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
  gap: 12px;
  margin: 0;
}
.case-summary > div {
  padding: 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  background: var(--surface-inset);
}
.case-summary dt { color: var(--text-secondary); font-size: 12px; }
.case-summary dd { margin: 5px 0 0; font-weight: 600; overflow-wrap: anywhere; }
.case-links,
.case-timeline { display: grid; gap: 8px; margin: 0; padding: 0; list-style: none; }
.case-links li,
.case-timeline li {
  display: grid;
  gap: 4px;
  padding: 12px;
  border-bottom: 1px solid var(--border);
}
.case-links li:last-child,
.case-timeline li:last-child { border-bottom: 0; }
.case-links code,
.case-timeline code,
.admin-page__hint code { overflow-wrap: anywhere; font-size: 12px; }
.case-timeline time { color: var(--text-secondary); font-size: 12px; }

/* C-01-Arbeitsliste: der Fall wird von hier aus geöffnet, die Frist trägt die
   Dringlichkeit. Gleiche Bad-Farbe wie überall sonst für «zu spät». */
.case-work__link { display: block; font-weight: 600; color: var(--text-primary); text-decoration: none; position: relative; }
.case-work__link:hover { text-decoration: underline; }
/* DIE TAPFLÄCHE OHNE DIE HÖHE (Muster: patch-pool.css «pool-weg»). Am Finger
   trägt der Fallname längst 44 px (Regel weiter unten). Am Rechner mass er
   208 x 21.8 — unter dem Maus-Boden 24. Er ist der TITEL einer Zeile, unter
   ihm steht der Betreff: ihn wirklich höher zu setzen, hiesse die Zeilenhöhe
   der ganzen Arbeitsliste zu ändern. Die Fangfläche wächst, der Satz nicht. */
.case-work__link::after {
  content: ""; position: absolute; left: 0; right: 0; top: 50%;
  height: 24px; transform: translateY(-50%);
}
/* DIESELBE TAPFLÄCHE FÜR DEN ZELL-LINK (28.08.2026, Muster drei Regeln höher).
   Am Rechner mass `.entity-link` 165 x 17 px — die Zeilenhöhe eines Textes,
   sieben Pixel unter dem Maus-Boden 24. Er steht allein in einer Tabellen-
   zelle, ist also KEIN Satz-Link (die WCAG-Ausnahme, die breiten-mass.mjs
   kennt, greift nur, wenn ein Absatz drumherum mehr Text trägt als er selbst).
   Ihn wirklich höher zu setzen hiesse jede Tabellenzeile des Hauses zu
   strecken; die Fangfläche wächst, der Satz nicht. */
.entity-link::after {
  content: ""; position: absolute; left: 50%; top: 50%;
  width: 100%; min-width: 24px; height: 24px; transform: translate(-50%, -50%);
}
/* Am Finger ist der Anker selbst 44 px hoch — dann darf das Kästchen nicht
   quer über den Betreff darunter liegen. Für `.entity-link` braucht es diese
   Ausnahme NICHT: er steht allein in seiner Zelle, das 24er-Kästchen liegt
   mittig in seinen 44 px und deckt nichts zu. Es hier trotzdem zu nennen
   liesse `_stil_einmalig_test.mjs` steigen — für nichts. */
@media (max-width: 1024px), (pointer: coarse) {
  .case-work__link::after { content: none; }
}
.case-work__subject { display: block; color: var(--text-secondary); font-size: 12px; }
.case-work__due--overdue { color: var(--bad-strong); font-weight: 600; }

/* D-03: der Offline-Balken. Oben, ueber allem, in der Warnfarbe — er muss
   auffallen, ohne die Arbeit zu blockieren. */
#lx-offline {
  position: sticky; top: 0; z-index: 9999;
  padding: 10px 14px; text-align: center;
  background: var(--bad); color: #fff;
  font-size: 13.5px; font-weight: 600;
}
#lx-offline[hidden] { display: none; }

/* D-03: mit dem Finger bedienbar. Gemessen 2026-07-25 gegen die Live-App:
   16 Fall-Links und 7 Objekt-Links lagen auf 390px unter 44px Tapflaeche.
   Der Floor gilt bis 1024px UND bei grobem Zeiger — reine 720px-Regeln
   greifen an Tablets nicht (project_tablet_touch_breakpoint). */
@media (max-width: 1024px), (pointer: coarse) {
  .case-work__link,
  .entity-link,
  .firm-link { display: inline-flex; align-items: center; min-height: 44px; min-width: 44px; }
  .case-work__link { display: flex; }
}

/* C-02: der Fallschritt ist die Arbeitsfläche, nicht eine Tabellenzeile.
   Auswahl und Knopf stehen nebeneinander; auf schmalen Geräten untereinander
   mit voller Breite, damit der Knopf die 44px-Tapfläche behält. */
.case-steps { display: grid; gap: 10px; }
.case-step { display: grid; gap: 10px; padding: 14px; background: var(--surface-inset); border-radius: var(--radius-card); }
.case-step__head { display: flex; justify-content: space-between; align-items: flex-start; gap: 12px; }
.case-step__meta { display: block; color: var(--text-secondary); font-size: 12px; margin-top: 3px; }
.case-step__owner { color: var(--text-secondary); font-size: 12px; white-space: nowrap; }
.case-step__do { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.case-step__pick { flex: 1 1 260px; min-width: 0; }
.case-step__pick select,
.case-step__pick input { width: 100%; min-height: 44px; }
.case-step__do .primary-btn { min-height: 44px; }
.case-step__hint { color: var(--text-secondary); font-size: 13px; margin: 0; }
/* Formularschritt: zwei Spalten auf breit, eine auf schmal. Jedes Feld behaelt
   die 44px-Tapflaeche, damit der Schritt auch am Handy bedienbar bleibt. */
.case-step__form { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 8px; }
.case-step__field { display: grid; gap: 4px; min-width: 0; }
.case-step__field > span { color: var(--text-secondary); font-size: 12px; }
.case-step__field input,
.case-step__field select,
.case-step__field textarea { width: 100%; min-height: 44px; }

@media (max-width: 720px) {
  .activity-item-row {
    grid-template-columns: 1fr;
    gap: 4px;
    padding: 12px;
  }
  .activity-item-row__time { font-size: 11px; }
  .activity-item-row__user { font-size: 12px; }
  .activity-item-row__action { font-size: 14px; font-weight: 600; }
  .filters-toolbar--activity .filters-group { display: grid; grid-template-columns: 1fr; gap: 8px; }
  .time-pill { padding: 8px 12px; min-height: 40px; font-size: 13px; }
}

/* ============================================================
   Termin-Zeile (firm-modal.js, advisor-leads.js)
   Iter 27 Welle C: Karten → Hairline-Zeilen (DESIGN.md §1), Rollen-Label
   ruhig statt Mono-Cyan, Überfällig = Inset-Bar + Tint statt Vollborder.
   Die today-*-Bausteine der alten Admin-Heute-Sicht sind am 03.08.2026 ohne
   Traeger gewesen und gefallen; manager-today.js selbst lebt und traegt
   seinen eigenen Namensraum (mt- und ck-) weiter unten im Block
   patch-cockpit.css.
   ============================================================ */

/* Iter 25 W2: einzige .appt-card--compact-Definition. Iter 27 Welle C: Zeile
   statt Box — Hairline zwischen Geschwistern, kein eigener Rahmen. */
.appt-card--compact { display: grid; gap: 8px; grid-template-columns: 80px 1fr auto 1fr auto; align-items: center; padding: 9px 4px; margin: 0; background: transparent; border: 0; border-radius: 0; font-size: 13px; box-shadow: none; }
.appt-card--compact + .appt-card--compact { border-top: 1px solid var(--border); }
.appt-card--compact > strong { font-variant-numeric: tabular-nums; }


/* Iter 15 E4c: überfällige Wiedervorlagen — visuell vom „heute fällig" abgesetzt */

@media (max-width: 720px) {
  .appt-card--compact { grid-template-columns: 1fr; gap: 3px; }
}

/* ============================================================
   Iter 9 Etappe 15: Firm-Modal Tabs + Versuch-Badge
   ============================================================ */
.modal__header { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; padding: 18px 20px 0; }
.modal__header-text { display: grid; gap: 6px; min-width: 0; flex: 1; }
/* Iter 27 Welle F: Eyebrow-Kicker gefallen — der Titel trägt (20/650, DESIGN.md §2) */
.modal__header-text h2 { margin: 0; font-size: 20px; font-weight: 650; letter-spacing: -.01em; line-height: 1.2; }
.modal__header-meta {
  display: flex; flex-wrap: wrap; gap: 6px; align-items: center; font-size: 13px;
}
.modal__header-meta .badge { font-size: 11px; padding: 3px 9px; }
.modal__header-case {
  color: var(--text-secondary); font-size: 12px; text-decoration: none;
  border-bottom: 1px solid currentColor; padding-bottom: 1px;
}
.modal__header-case:hover { color: var(--text-primary); }
.badge--attempt {
  background: rgba(var(--warn-rgb), .16); color: var(--warn-strong); font-weight: 700;
}

/* Iter 27 Welle F: Tabs im Underline-Stil (wie .user-tab / .subnav) —
   aktiv = Text-Primary + Accent-Indikator, kein Cyan-Text-Geschrei. */
.modal__tabs {
  display: flex; gap: 2px; padding: 0 20px;
  border-bottom: 1px solid var(--border);
  overflow-x: auto; overflow-y: hidden;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}
.modal__tabs::-webkit-scrollbar { display: none; }
.modal__tab {
  background: transparent; border: none; color: var(--text-secondary);
  padding: 11px 13px; min-height: 44px;
  font-size: 13.5px; font-weight: 500; cursor: pointer;
  border-bottom: 2px solid transparent; margin-bottom: -1px;
  white-space: nowrap;
  transition: color var(--transition), border-color var(--transition);
}
.modal__tab:hover { color: var(--text-primary); }
.modal__tab.is-active {
  color: var(--text-primary); border-bottom-color: var(--accent); font-weight: 600;
}

.reassign-row { display: grid; grid-template-columns: 1fr 2fr auto; gap: 12px; align-items: end; }
.reassign-row .field--wide { min-width: 200px; }
.appt-note { display: block; padding-top: 4px; color: var(--text-secondary); font-size: 12px; }

@media (max-width: 720px) {
  .modal__header { padding: 14px 14px 0; }
  .modal__header-text h2 { font-size: 18px; }
  .modal__tabs { padding: 0 14px; gap: 0; }
  .modal__tab { padding: 12px 12px; font-size: 13px; }
  .reassign-row { grid-template-columns: 1fr; }
}

/* ============================================================
   Iter 9 Etappe 16: Schnellaktionen + Pflicht-Notiz-Mini-Modal
   ============================================================ */
.kanban-card__actions, .firm-card__qa {
  display: flex; flex-wrap: wrap; gap: 4px; margin-top: 8px; padding-top: 8px;
  border-top: 1px solid var(--border);
}
/* Iter 15 E4a: Quick-Action-Buttons im Firm-Modal Status-Tab — gleicher
   Outcome-Pfad wie Karten-Buttons (Density), ohne den Karten-Border-Top
   (status-strip hat eigenen Frame). */
.status-strip__qa { display: flex; gap: 4px; flex-wrap: wrap; }
.qa-btn {
  background: var(--surface-2); color: var(--text); border: 1px solid var(--border);
  padding: 6px 10px; min-height: 32px; border-radius: var(--radius-card);
  font-size: 12px; font-weight: 500; cursor: pointer;
  transition: all .12s;
  /* 07.09.2026: Zeichen und Wort standen auf dem Handy aufeinander («⊘Niemand»),
     am Schreibtisch nicht. Grund war der Griff-Boden weiter unten: er schaltet
     `.qa-btn` unter 1024px auf inline-flex, und ein Flex-Kasten wirft den
     Wortzwischenraum vor dem Text weg. Der Abstand gehoert darum hierher, wo
     der Knopf beschrieben wird — dann sieht er auf jeder Breite gleich aus,
     statt dass eine Messregel sein Aussehen aendert. */
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
}
.qa-btn:hover { background: var(--surface-3); border-color: rgba(var(--accent-rgb),.35); }
.qa-btn--ok    { color: var(--accent-strong); }
.qa-btn--ok:hover    { background: rgba(var(--accent-rgb),.12); border-color: rgba(var(--accent-rgb),.4); }
.qa-btn--appt  { color: var(--good-strong); }
.qa-btn--appt:hover  { background: rgba(var(--good-rgb),.12); border-color: rgba(var(--good-rgb),.4); }

.kanban-card__cb,
.firm-card__cb {
  display: flex; align-items: center; gap: 5px;
  font-size: 12px; color: var(--warn-strong); margin-top: 4px;
  font-variant-numeric: tabular-nums;
}
/* Iter 15 E4c: überfällige WV — gleiche Akzentfarbe wie „lost", aber dezenter */
.kanban-card__cb--overdue,
.firm-card__cb--overdue { color: var(--low); font-weight: 600; }
.kanban-card__badges { display: flex; gap: 4px; flex-wrap: wrap; }

/* Mini-Modal */
.modal-backdrop--mini { z-index: 1100; }
.mini-modal {
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-card);
  width: 100%; max-width: 460px; max-height: 90vh;
  display: flex; flex-direction: column;
  overflow: hidden; box-shadow: var(--shadow-lg);
  animation: modal-in var(--dur-slow) var(--ease);
}
.mini-modal__header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 16px 18px; border-bottom: 1px solid var(--border);
}
.mini-modal__header h3 { margin: 0; font-size: 16px; }
.mini-modal__body { padding: 18px; display: grid; gap: 14px; overflow-y: auto; }
.mini-modal__body textarea { min-height: 90px; }
.mini-modal__hint { color: var(--text-secondary); font-size: 12px; margin: 0; }
.mini-modal__footer {
  display: flex; gap: 8px; justify-content: flex-end;
  padding: 14px 18px; border-top: 1px solid var(--border);
  padding-bottom: max(14px, env(safe-area-inset-bottom));   /* iOS: über Home-Indicator */
}
.mini-modal__footer .primary-btn,
.mini-modal__footer .ghost-btn { min-height: 44px; }

@media (max-width: 720px) {
  .qa-btn { min-height: 44px; padding: 10px 14px; font-size: 13px; flex: 1 1 calc(33% - 4px); }
  .qa-btn--appt { flex: 1 1 100%; }  /* Termin auf eigene Zeile, prominent */
  /* Iter15 E3: mini-modal mobil = randloses Fullscreen. Das .modal-backdrop hat
     padding:24px → width:100vw ragte 24px rechts raus (H-Overflow). padding:0 auf
     dem mini-Backdrop + width:100% = echtes Fullscreen ohne Überlauf. */
  .modal-backdrop--mini { padding: 0; }
  .mini-modal {
    max-width: 100%; max-height: 100vh; max-height: 100dvh; height: 100vh; height: 100dvh; border-radius: 0;
    width: 100%;
  }
  /* Iter 27 Welle F: Body wächst — Footer (Speichern) ankert unten in Daumen-Reichweite */
  .mini-modal__body { padding: 14px; flex: 1 1 auto; align-content: start; }
}

/* ============================================================
   Iter 13 Etappe 2c: Tap-Outcome-Assessment (null Freitext)
   ============================================================ */
.assessment-q { display: grid; gap: 8px; }
.assessment-q__label { margin: 0; font-size: 13px; font-weight: 600; color: var(--text-primary); }
.assessment-q__req { color: var(--low); margin-left: 4px; }
.assessment-q.is-missing .assessment-q__label { color: var(--low); }
.assessment-q.is-missing .tap-group {
  outline: 1.5px solid var(--low); outline-offset: 4px; border-radius: var(--radius-button);
}
.tap-group { display: flex; flex-wrap: wrap; gap: 8px; }
.tap-group--scale { gap: 6px; }
/* Iter 27 Welle F: Tap-Buttons gross + klar; Auswahl = Accent-Soft + Border
   (echte Selektion, aber kein solid-Cyan-Block — DESIGN.md Kill-Liste). */
.tap-btn {
  min-height: 44px; padding: 10px 16px;
  background: var(--surface-2); color: var(--text);
  border: 1px solid var(--border); border-radius: var(--radius-button);
  font-size: 13.5px; font-weight: 600; cursor: pointer;
  transition: background var(--transition), border-color var(--transition),
              color var(--transition), transform var(--transition);
}
.tap-btn:hover { background: var(--surface-3); }
.tap-btn:active { transform: scale(.985); }
.tap-btn.is-active {
  background: var(--accent-soft); color: var(--accent-strong);
  border-color: var(--accent-line);
  box-shadow: inset 0 1px 0 rgba(var(--accent-rgb), .12);
}
.tap-btn--scale {
  min-width: 44px; flex: 1 1 0;
  display: inline-flex; align-items: center; justify-content: center;
  font-variant-numeric: tabular-nums;
}
.mini-modal__error { color: var(--low); font-size: 13px; margin: 0; }

@media (max-width: 720px) {
  .tap-btn { flex: 1 1 calc(50% - 4px); justify-content: center; }
  .tap-btn--scale { flex: 1 1 0; }
}

/* ============================================================
   Iter 9 Etappe 17: Caller-Activity-Stream
   ============================================================ */
.today-stream {
  padding: 14px 18px;
  display: grid; gap: 10px;
}
.today-stream__head {
  display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap;
}
.today-stream__head strong {
  font-size: 14px; color: var(--text); font-variant-numeric: tabular-nums;
}
.today-stream__list {
  list-style: none; padding: 0; margin: 0; display: grid; gap: 4px;
}
.today-stream__list li {
  display: flex; align-items: baseline; gap: 10px;
  font-size: 12px; color: var(--text-secondary);
  padding: 2px 0;
}
.today-stream__list li span { color: var(--text-secondary); font-variant-numeric: tabular-nums; min-width: 44px; }
.today-stream__list li strong { color: var(--text); font-weight: 600; }
.today-stream__list li em { color: var(--accent); font-style: normal; }

@media (max-width: 720px) {
  .today-stream { padding: 12px; }
  .today-stream__list li { font-size: 13px; flex-wrap: wrap; }
}

/* ============================================================
   Iter 10 Etappe 22: Inline-Edit pro Feld (firm-modal Details-Tab)
   ============================================================ */
.icon-btn--sm { width: 32px; height: 32px; }
.icon-btn--sm svg { width: 14px; height: 14px; }
.modal-section__hint {
  margin: 0 0 12px 0; font-size: 12px; color: var(--text-secondary);
}
.visually-hidden {
  position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0;
}
.editable-grid {
  display: grid; gap: 12px;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
}
.editable-field { padding: 12px 14px; }
.editable-field__head {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  margin-bottom: 6px;
}
.editable-field__head strong {
  margin: 0; font-size: 11px; text-transform: uppercase; letter-spacing: .08em;
  color: var(--text-secondary);
}
.editable-field__value {
  margin: 0; font-size: 14px; color: var(--text); word-break: break-word;
}
.editable-field__editor {
  display: grid; gap: 8px; margin-top: 8px;
  padding-top: 8px; border-top: 1px solid var(--border);
}
.editable-field__editor .field { margin: 0; }
.editable-field__editor input,
.editable-field__editor select {
  width: 100%; min-height: 38px;
  background: var(--surface-inset); color: var(--text);
  border: 1px solid var(--border); border-radius: var(--radius-button); padding: 8px 10px;
  font: inherit;
}
.editable-field__editor input:focus,
.editable-field__editor select:focus {
  outline: none; border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(var(--accent-rgb), .18);
}
.editable-field__actions {
  display: flex; gap: 8px; justify-content: flex-end; flex-wrap: wrap;
}
.editable-field__actions .ghost-btn,
.editable-field__actions .primary-btn { min-height: 44px; padding: 0 16px; }

@media (max-width: 720px) {
  .editable-grid { grid-template-columns: 1fr; }
  .editable-field__editor input,
  .editable-field__editor select { min-height: 44px; font-size: 16px; }
}

/* ============================================================
   Iter 11 Etappe 37: Mobile-Pass Iter-11
   ============================================================ */
@media (max-width: 720px) {
  /* Section-Nav (Analyse) mit 4 Tabs: scrollbar */
  .section-nav {
    overflow-x: auto; flex-wrap: nowrap;
    -webkit-overflow-scrolling: touch;
  }
  .section-nav__btn {
    flex: 0 0 auto; min-height: 44px; padding: 8px 14px; font-size: 14px;
  }
  /* Heatmap-Bar: schmaler aber sichtbar */
  /* Setter-KPIs: 6 KPIs in 2x3 Grid */
  .kpi-strip { gap: 6px; }
}

/* ============================================================
   Iter 11 Etappe 35: Drag-Reschedule (Desktop)
   ============================================================ */
.cal-event { cursor: grab; user-select: none; touch-action: pan-y; }
.cal-event:active { cursor: grabbing; }
.cal-event.is-dragging {
  cursor: grabbing;
  z-index: 5;
  box-shadow: 0 8px 24px rgba(0, 0, 0, .5);
  opacity: .9;
  transition: none;
}

/* ============================================================
   Iter 11 Etappe 32: Lead-Picker-Modal (Quick-Create-Termin)
   ============================================================ */
.modal--lead-picker { max-width: 560px; }
.lp-body { display: grid; gap: 14px; }
.lp-body input[type="search"] {
  min-height: 44px; padding: 10px 12px; font: inherit;
  background: var(--surface-inset); color: var(--text);
  border: 1px solid var(--border); border-radius: var(--radius-button);
}
.lp-results {
  display: grid; gap: 6px; max-height: 50vh; overflow-y: auto;
}
/* Iter 27 Welle F: Ergebnis-Zeilen im Listen-Idiom (Fläche statt Rahmen-Hover) */
.lp-result {
  display: grid; gap: 6px;
  background: var(--surface-2); border: 1px solid transparent;
  border-radius: var(--radius-card); padding: 12px 14px;
  text-align: left; color: var(--text); font: inherit; cursor: pointer;
  transition: background var(--transition);
}
.lp-result:hover { background: var(--surface-3); }
.lp-result strong { font-size: 14.5px; color: var(--text-primary); }
.lp-result__meta {
  display: flex; flex-wrap: wrap; gap: 8px; align-items: center;
  font-size: 12px; color: var(--text-secondary);
}
@media (max-width: 720px) {
  .modal--lead-picker { max-width: 100%; height: 100vh; height: 100dvh; max-height: 100vh; max-height: 100dvh; border-radius: 0; }
  .lp-body input[type="search"] { font-size: 16px; min-height: 48px; }
  .lp-result { padding: 14px; }
}

/* ============================================================
   Iter 10 Etappe 30: Mobile-Polish + Touch-Target-Pass
   ============================================================ */
@media (max-width: 720px) {
  /* KPI-Strip kompakter (mein-Kalender) */
  .kpi-strip {
    gap: 6px;
  }
  .kpi-pill {
    flex: 1 1 calc(50% - 6px);
    min-width: 0;
    padding: 8px 10px;
    font-size: 12px;
  }
  .kpi-pill strong { font-size: 18px; }

  /* Cal-Toolbar Datepicker auf eigene Zeile */
  .cal-toolbar__date {
    flex: 1 1 100%; min-width: 0; order: 4;
  }
  /* Cal-Toolbar Filter: nicht zu klein, beide nebeneinander */
  .cal-toolbar__controls select { font-size: 16px; }

  /* Activity-Item-Row (Edit-Sicht) lesbarer */
  .activity-item-row { gap: 6px; padding: 8px 6px; flex-wrap: wrap; }
  .activity-item-row__detail { width: 100%; }
  .activity-item-row__reason { width: 100%; font-style: italic; color: var(--text-secondary); font-size: 12px; }

  /* Filter-Toolbar Search-Input voll breit */
  .filters-toolbar .field--search { flex: 1 1 100%; }

  /* Modal passt GARANTIERT in den Viewport (E6-Fix 2026-07-03: 100dvh bei
     24px Backdrop-Padding + 12px Alt-Margin ragte unten 36px raus — auf Prod
     gemessen, Pool- UND Standort-Modal betroffen). Eine Geometrie: 12px Luft. */
  .modal-backdrop { padding: 12px; }
  .modal { margin: 0; max-height: calc(100vh - 24px); max-height: calc(100dvh - 24px); }
  /* ⚠️ DIESE ZWEI ZEILEN HABEN DEN TASTATUR-SCHUTZ DES APP-DIALOGS ERSCHLAGEN.
     Weiter oben steht seit dem 09.08.: «.app-dialog { place-items: end center;
     padding-bottom: calc(24px + var(--vv-unten, 0px)) }» — mit dem Kommentar
     «`--vv-unten` hält sie über einer offenen Tastatur». Beide Wähler sind eine
     einzige Klasse (Spezifität 0,1,0); die Regel HIER steht später und gewinnt.
     Der Schutz war damit tot, hausweit, für alle 52 Rufer von `fragen()`,
     `formular()` und `bestaetigen()`.
     GEMESSEN am 25.08.2026 auf 390×620 mit `--vv-unten: 290px` (der Wert, den
     `utils/viewport.js` bei offener iOS-Tastatur schreibt): padding-bottom war
     12 px statt 302, der Kasten reichte bis y=608 — «Abbrechen» und «Anlegen»
     lagen bei y=581, also 251 px hinter der Tastatur. Der Anlege-Dialog für
     einen neuen Kunden war damit am Telefon nicht abzuschliessen; genau das
     meint der Owner mit «ein Kunde erstellen … das ist zu mühsam».
     Zwei Zeilen, beide mit `var(--vv-unten, 0px)`: ohne Tastatur ist der Wert
     0 und die Geometrie dieses Blocks bleibt Pixel für Pixel dieselbe. */
  .modal-backdrop.app-dialog { padding-bottom: calc(12px + var(--vv-unten, 0px)); }
  /* Und der Kasten darf nicht höher sein als das, was von der Seite noch zu
     sehen ist — sonst schiebt ihn die Ausrichtung `end` oben aus dem Bild.
     Sein Leib rollt ohnehin (`.modal__body { overflow-y: auto }`), und die
     Handlungszeile klebt in diesem Block schon unten fest (`.modal-actions`,
     `position: sticky`). Beides greift erst durch diesen Deckel. */
  .modal-backdrop.app-dialog > .modal {
    max-height: calc(100dvh - 24px - var(--vv-unten, 0px));
  }
}

/* Touch-Target-Floor fuer alle interaktiven Buttons in Iter-10-Komponenten */
.cal-toggle,
.cal-toolbar__nav .ghost-btn,
.editable-field__actions .primary-btn,
.editable-field__actions .ghost-btn {
  min-height: 44px;
}

/* ============================================================
   Iter 10 Etappe 28: Visueller Kalender (calendar-grid)
   ============================================================ */
.cal-shell { padding: 0; overflow: hidden; }
.cal-toolbar {
  display: flex; flex-wrap: wrap; gap: 12px; align-items: center;
  padding: 14px 16px; border-bottom: 1px solid var(--border);
  background: var(--surface-2);
}
.cal-toolbar__nav {
  display: flex; align-items: center; gap: 8px; flex: 1 1 auto;
}
.cal-toolbar__nav .ghost-btn { min-height: 44px; padding: 0 14px; }   /* Iter 15: 40→44 Touch */
.cal-toolbar__date {
  min-height: 44px; padding: 0 12px;   /* Iter 15: 40→44 Touch */
  background: var(--surface-1); color: var(--text);
  border: 1px solid var(--border); border-radius: var(--radius-card);
  font: inherit;
}
.cal-toolbar__title { margin: 0 0 0 8px; font-size: 16px; font-weight: 600; }
.cal-toolbar__controls { display: flex; gap: 10px; flex-wrap: wrap; }
.cal-toolbar__controls .field { margin: 0; min-width: 160px; }
.cal-toolbar__controls select { min-height: 44px; }   /* Iter 15: 40→44 Touch */
/* Iter 27 Welle C: EIN Segmented-Vokabular (Thumb-Stil) auch im Kalender */
.cal-toolbar__views { display: flex; gap: 2px; background: var(--surface-inset); border: 1px solid var(--border); border-radius: var(--radius-card); padding: 3px; }
/* Die Arten-Leiste sagt, was im Raster liegt: Termine, Wiedervorlagen, Aufgaben,
   eigene Einträge — jede Zahl ein Schalter. Sie bricht um, statt am Handy aus dem
   Kasten zu laufen (fünf Schalter massen bei 390 px 416 px), und sie sieht bewusst
   anders aus als die Ansichts-Leiste darüber: zwei Bedeutungen, zwei Kleider. */
.cal-arten { display: flex; flex-wrap: wrap; gap: 6px; padding: 8px 0 0; }
.cal-arten .cal-toggle { border: 1px solid var(--border); border-radius: 999px; padding: 6px 12px; min-height: 34px; }
.cal-arten .cal-toggle:not(.is-active) { opacity: .55; }

.cal-toggle {
  appearance: none; background: transparent; color: var(--text-secondary);
  border: 0; padding: 7px 13px; font: 600 12.5px/1.2 inherit; border-radius: var(--radius-card);
  cursor: pointer; transition: background var(--transition), color var(--transition);
  min-height: 30px;
}
.cal-toggle:hover { color: var(--text-primary); }
.cal-toggle.is-active {
  background: var(--surface-3); color: var(--text-primary);
  box-shadow: none;
}

.cal-mode-bar {
  display: flex; justify-content: flex-end; align-items: flex-end;
  gap: 8px; flex-wrap: wrap; padding: 0 0 12px; margin-bottom: 0;
}
.cal-mode-bar__toggle {
  display: flex; gap: 2px; background: var(--surface-inset); border: 1px solid var(--border); border-radius: var(--radius-card); padding: 3px;
}
.cal-mode-bar__toggle + .cal-mode-bar__toggle { margin-left: 8px; }
/* DIE MITARBEITER-WAHL (08.09.2026, Owner 07.09.: «Ich kann keinen Mitarbeiter
   selber filtern»). Sie steht in der Leiste und gilt für Raster UND Liste.
   `flex-wrap` oben ist ihr Zwilling: unter rund 520 px stünden Umschalter und
   Wahl sonst nebeneinander in einer Zeile, die nicht mehr passt — dann rutscht
   die Wahl in die zweite Zeile und behält ihre volle Breite, statt auf eine
   Namensbreite zusammenzufallen. Der Griff-Boden (≥44 px auf Touch) kommt vom
   Haus (`.field select`, Zeile 838) — hier steht KEINE zweite Höhe, sonst
   schlägt dieses Blatt ihn still. */
.cal-mode-bar__wer { min-width: 190px; max-width: 100%; }

.cal-view { padding: 0; }

/* Tag- + Woche-Sicht (Time-Grid) */
.cal-grid {
  display: grid;
  background: var(--surface-1);
}
.cal-grid--day { grid-template-columns: 64px 1fr; height: var(--grid-h, 960px); }
.cal-grid--week { display: block; }
.cal-week-headers {
  display: grid; grid-template-columns: 64px repeat(7, 1fr);
  position: sticky; top: 0; z-index: 2;
  background: var(--surface-2);
  border-bottom: 1px solid var(--border);
}
.cal-week-header {
  text-align: center; padding: 10px 4px;
  border-left: 1px solid var(--border);
  display: flex; flex-direction: column; gap: 2px;
}
.cal-week-header span { font-size: 11px; text-transform: uppercase; color: var(--text-secondary); letter-spacing: .08em; }
.cal-week-header strong { font-size: 14px; }
.cal-week-header.is-today strong { color: var(--accent); }
.cal-week-body { display: grid; grid-template-columns: 64px 1fr; }
.cal-week-cols { display: grid; grid-template-columns: repeat(7, 1fr); height: var(--grid-h, 960px); }

.cal-time-col { position: relative; height: var(--grid-h, 960px); border-right: 1px solid var(--border); }
.cal-time-label {
  position: absolute; left: 0; right: 0;
  font-size: 11px; color: var(--text-secondary);
  padding: 0 6px; line-height: 1;
  transform: translateY(-50%);
}
/* Iter 25 E1.3: erstes Label (06:00, top:0) nicht nach oben unter den sticky
   Wochen-Header ziehen — sonst halb verdeckt. */
.cal-time-label:first-child { transform: none; }

.cal-day-col {
  position: relative;
  border-left: 1px solid var(--border);
  min-height: var(--grid-h, 960px);
}
.cal-day-col__slots { position: relative; height: var(--grid-h, 960px); }
.cal-slot {
  position: absolute; left: 0; right: 0;
  border-bottom: 1px dashed rgba(var(--tint-rgb), .04);
  cursor: pointer;
  transition: background .12s ease;
}
.cal-slot:nth-of-type(odd) { border-bottom-color: rgba(var(--tint-rgb), .08); }
.cal-slot:hover { background: rgba(var(--accent-rgb), .06); }

.cal-now-line {
  position: absolute; left: 0; right: 0; height: 2px;
  background: var(--accent); pointer-events: none;
  z-index: 3;
}
.cal-now-line::before {
  content: ''; position: absolute; left: -4px; top: -4px;
  width: 10px; height: 10px; background: var(--accent); border-radius: 50%;
}

.cal-events { position: absolute; inset: 0; pointer-events: none; }
.cal-event {
  position: absolute; left: 4px; right: 4px;
  display: flex; flex-direction: column; gap: 2px; align-items: flex-start;
  background: var(--surface-2);
  border: 1px solid var(--border); border-left: 4px solid var(--accent);
  border-radius: var(--radius-card);
  padding: 4px 8px;
  color: var(--text); text-align: left;
  cursor: pointer; pointer-events: auto;
  overflow: hidden; font: inherit;
  transition: transform .12s ease, box-shadow .12s ease;
  min-height: 40px;
}
.cal-event:hover { transform: translateY(-1px); box-shadow: 0 4px 12px rgba(0, 0, 0, .35); }
.cal-event strong { font-size: 12px; font-variant-numeric: tabular-nums; }
.cal-event span { font-size: 12px; color: var(--text-secondary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%; }
.cal-event--planned     { border-left-color: var(--accent); }
.cal-event--confirmed   { border-left-color: var(--accent); background: rgba(var(--accent-rgb), .08); }
.cal-event--completed   { border-left-color: var(--text-secondary); }
.cal-event--won         { border-left-color: var(--high, var(--good)); background: rgba(var(--good-rgb), .12); }
.cal-event--lost        { border-left-color: var(--low, var(--bad-deep)); background: rgba(var(--bad-rgb), .08); }
.cal-event--rescheduled { border-left-color: var(--info-muted); background: rgba(var(--info-rgb), .08); }
.cal-event--no_show     { border-left-color: var(--medium); background: rgba(var(--warn-rgb), .08); }
.cal-event--cancelled   { border-left-color: var(--low, var(--bad-deep)); opacity: .6; }

/* Monat */
.cal-month { padding: 0; }
.cal-month__headers {
  display: grid; grid-template-columns: repeat(7, 1fr);
  background: var(--surface-2);
  border-bottom: 1px solid var(--border);
}
.cal-month__headers > div {
  padding: 10px 6px; text-align: center;
  font-size: 11px; text-transform: uppercase; color: var(--text-secondary); letter-spacing: .08em;
  border-left: 1px solid var(--border);
}
.cal-month__grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  grid-auto-rows: minmax(100px, 1fr);
  background: var(--border);
  gap: 1px;
}
.cal-month__cell {
  appearance: none; background: var(--surface-1); border: 0;
  display: flex; flex-direction: column; gap: 4px;
  padding: 6px; text-align: left;
  cursor: pointer; min-height: 100px; color: var(--text); font: inherit;
  transition: background .12s ease;
}
.cal-month__cell:hover { background: rgba(var(--accent-rgb), .06); }
.cal-month__cell.is-other { opacity: .35; }
.cal-month__cell.is-today { background: rgba(var(--accent-rgb), .08); }
.cal-month__cell.is-today .cal-month__day { color: var(--accent); }
.cal-month__day { font-size: 13px; font-weight: 600; }
.cal-month__events { display: flex; flex-direction: column; gap: 2px; }
.cal-month__pill {
  display: flex; gap: 4px; align-items: baseline;
  padding: 2px 6px; border-radius: var(--radius-card);
  background: var(--surface-2); border-left: 3px solid var(--accent);
  font-size: 11px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
}
.cal-month__pill strong { font-variant-numeric: tabular-nums; color: var(--text-secondary); }
.cal-month__pill em { font-style: normal; color: var(--text); overflow: hidden; text-overflow: ellipsis; max-width: 120px; }
.cal-month__pill--won { border-left-color: var(--high, var(--good)); }
.cal-month__pill--lost { border-left-color: var(--low, var(--bad-deep)); }
.cal-month__pill--confirmed { border-left-color: var(--accent); }
.cal-month__pill--no_show { border-left-color: var(--medium); }
.cal-month__pill--rescheduled { border-left-color: var(--info-muted); }
.cal-month__more { font-size: 11px; color: var(--accent); padding: 0 4px; font-weight: 600; }

/* Mobile (<=720px) */
@media (max-width: 720px) {
  .cal-toolbar { padding: 10px; gap: 8px; }
  .cal-toolbar__nav { flex: 1 1 100%; flex-wrap: wrap; }
  .cal-toolbar__title { width: 100%; margin: 0; font-size: 15px; }
  .cal-toolbar__controls { flex: 1 1 100%; }
  .cal-toolbar__controls .field { min-width: 0; flex: 1 1 calc(50% - 5px); }
  .cal-toolbar__views { flex: 1 1 100%; justify-content: space-between; }
  .cal-toggle { flex: 1 1 auto; min-height: 44px; padding: 0 8px; }

  .cal-month__grid { grid-auto-rows: minmax(70px, 1fr); }
  .cal-month__cell { min-height: 70px; padding: 4px; }
  .cal-month__day { font-size: 12px; }
  .cal-month__pill em { display: none; }
  .cal-month__pill strong { font-size: 11px; }

  .cal-event span { font-size: 11px; }

  .cal-mode-bar { padding: 8px 10px; }
}
/* Dieselbe Grenze wie beim Layout unten, und aus demselben Grund: ein Termin,
   den man nicht treffen und nicht lesen kann, ist auf 768 px so unbrauchbar
   wie auf 390. Die Mindestbreite von 720 px gibt jeder der sieben Spalten
   ihre ~94 px zurueck; darunter rollt die Woche waagrecht, statt die Namen
   abzuschneiden. */
@media (max-width: 1024px), (pointer: coarse) {
  .cal-grid--week,
  .cal-week-body { overflow-x: auto; }
  .cal-week-headers,
  .cal-week-cols { min-width: 720px; }
  .cal-event { min-height: 44px; padding: 4px 6px; }
  .cal-slot { min-height: 44px; }
}

/* ============================================================
   Iter 33 B3: Kalender-Seiten-Panel (Notizen & freie To-Dos)
   Zwei-Spalten-Grid neben dem Kalender-Grid; Mobile 1-spaltig +
   aufklappbar. Basisregeln HIER, eigener @media-Block direkt danach
   (Kaskaden-Konvention, Memory project_css_cascade_mobile).
   ============================================================ */
.cal-layout { display: grid; grid-template-columns: minmax(0, 1fr) 320px; gap: 14px; align-items: start; }
.cal-side-panel { position: sticky; top: 14px; align-self: start; }
.cal-side-panel__head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.cal-side-panel__title { margin: 0; font-size: 14px; font-weight: 600; color: var(--text-primary); }
.cal-side-panel__chev { display: none; color: var(--text-secondary); transition: transform var(--dur) var(--ease); }
.cal-side-panel__body { display: flex; flex-direction: column; gap: 16px; margin-top: 12px; }

.cal-note__label { display: flex; gap: 4px; font-size: 12px; color: var(--text-secondary); margin-bottom: 6px; }
.cal-note__status { color: var(--text-tertiary); }
.cal-note__status.is-err { color: var(--bad-strong); }
.cal-note__area {
  width: 100%; resize: vertical; min-height: 96px; font: inherit; line-height: 1.5;
  background: var(--surface-inset); color: var(--text);
  border: 1px solid var(--border); border-radius: var(--radius-card); padding: 10px 12px;
}
.cal-note__area:focus { outline: none; border-color: var(--accent-line); }

.cal-todos__add { display: flex; gap: 6px; margin-bottom: 10px; }
.cal-todos__input {
  flex: 1; min-width: 0; min-height: 40px; font: inherit;
  background: var(--surface-inset); color: var(--text);
  border: 1px solid var(--border); border-radius: var(--radius-card); padding: 0 12px;
}
.cal-todos__input:focus { outline: none; border-color: var(--accent-line); }
.cal-todos__add-btn {
  flex: 0 0 40px; min-height: 40px; display: flex; align-items: center; justify-content: center;
  background: var(--accent-soft); color: var(--accent);
  border: 1px solid var(--accent-line); border-radius: var(--radius-card); cursor: pointer;
  transition: background var(--dur) var(--ease);
}
.cal-todos__add-btn:hover { background: var(--accent-line); }
.cal-todos__add-btn svg { width: 18px; height: 18px; }
.cal-todos__done { margin-top: 10px; }
.cal-todos__done-sum { cursor: pointer; font-size: 12px; color: var(--text-secondary); padding: 4px 0; list-style: none; }
.cal-todos__done-sum::-webkit-details-marker { display: none; }
.cal-todos__done[open] .cal-todos__done-sum { margin-bottom: 8px; }

/* 28.08.2026 — DIE TABLET-BRUCHZONE, ZUM DRITTEN MAL IN DIESEM HAUS.
   Diese Grenze stand auf 720 px. Auf 768 und 1024 px blieb das Seitenpanel
   also mit seinen festen 320 px stehen, und die sieben Tagesspalten der Woche
   teilten sich den Rest: gemessen 35.6 px je Spalte auf 768, 38.4 auf 1024 —
   jeder Termin-Knopf 19 px abgeschnitten, ohne Rollweg, mit unlesbarem Namen.
   Der Kalender ist laut Owner-Wunsch 27 sein Arbeitstag-Zentrum; auf einem
   iPad war er es nie. Gefunden erst, als «kalender» am 28.08. ueberhaupt in
   die Messliste kam (SCHIRME) — davor hat ihn keine Breiten-Messung je
   geoeffnet. Memory-Regel project_tablet_touch_breakpoint, dritter Fall.
   `minmax(0, 1fr)` und nicht `1fr`: eine Grid-Spalte schrumpft von sich aus
   NIE unter ihren Inhalt. Mit blossem `1fr` blies die 720-px-Woche den ganzen
   Kasten auf 786 px auf — 46 px Querlauf, und der Rollweg lief ins Leere. */
@media (max-width: 1024px), (pointer: coarse) {
  .cal-layout { grid-template-columns: minmax(0, 1fr); }
  .cal-side-panel { position: static; min-width: 0; }
  .cal-side-panel__head { cursor: pointer; min-height: 44px; }
  .cal-side-panel__chev { display: inline-flex; }
  .cal-side-panel:not(.is-open) .cal-side-panel__body { display: none; }
  .cal-side-panel.is-open .cal-side-panel__chev { transform: rotate(180deg); }
}
@media (max-width: 1024px), (pointer: coarse) {
  .cal-todos__input, .cal-todos__add-btn { min-height: 44px; }
  /* Die Hoehe stand hier schon; gemessen war 40 x 44 px — zu schmal, nicht zu
     flach. `flex: 0 0 40px` aus der Basisregel haelt die BREITE fest. */
  .cal-todos__add-btn { flex-basis: 44px; min-width: 44px; }
}

/* ============================================================
   Iter 10 Etappe 26: Setter-Briefing-Drawer
   ============================================================ */
.briefing-overlay {
  position: fixed; inset: 0; z-index: 100;
  background: rgba(0, 0, 0, .55);
  display: flex; justify-content: flex-end;
  animation: briefing-fade .15s ease;
}
@keyframes briefing-fade { from { background: rgba(0,0,0,0); } to { background: rgba(0,0,0,.55); } }
.briefing-drawer {
  width: min(600px, 100%);
  height: 100%;
  background: var(--surface-1);
  border-left: 1px solid var(--border);
  display: grid;
  grid-template-rows: auto 1fr auto;
  animation: briefing-slide .2s ease;
}
@keyframes briefing-slide { from { transform: translateX(40px); opacity: .6; } to { transform: translateX(0); opacity: 1; } }
.briefing-drawer__head {
  display: flex; justify-content: space-between; align-items: flex-start;
  padding: 20px 22px 16px;
  border-bottom: 1px solid var(--border);
  gap: 14px;
}
.briefing-drawer__head-text h2 { margin: 0; font-size: 20px; font-weight: 650; letter-spacing: -.01em; }
.briefing-drawer__meta { margin: 8px 0 0; font-size: 13px; color: var(--text-secondary); }
.briefing-drawer__meta strong { color: var(--text); }
.briefing-drawer__body {
  overflow-y: auto;
  padding: 18px 22px 24px;
  display: grid; gap: 22px;
}
.briefing-drawer__actions {
  display: flex; gap: 10px; justify-content: flex-end; flex-wrap: wrap;
  padding: 14px 22px;
  border-top: 1px solid var(--border);
  background: var(--surface-1);
}
.briefing-drawer__actions .primary-btn,
.briefing-drawer__actions .ghost-btn { min-height: 48px; padding: 0 22px; }
.briefing-actions__hint { color: var(--text-secondary); font-size: 13px; align-self: center; }

.briefing-section h3 {
  margin: 0 0 10px;
  font-size: 13px; text-transform: uppercase; letter-spacing: .1em;
  color: var(--text-secondary);
}
.briefing-grid {
  display: grid; gap: 8px;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
}
/* COS-Etappe 0.2 (01.09.2026) — «Was sonst über die Firma bekannt ist».
   Dieses Fenster zeigte acht von einundfünfzig gelieferten Angaben; der Rest
   kam im Browser an und wurde beim Zeichnen weggelassen. Er steht jetzt hier,
   EINGEKLAPPT — das Fenster bleibt so kurz wie bisher, ein Griff öffnet den
   Rest. Gestalt wie `.ku-mehr` und `.la-restwissen`: dieselbe Frage, dasselbe
   Aussehen, derselbe Pfeil. Die Überschrift bleibt ein `h3`, damit der
   Abschnitt in der Gliederung des Fensters steht wie jeder andere. */
.briefing-section > details > summary {
  display: flex; align-items: center; gap: 8px;
  min-height: 46px; cursor: pointer; list-style: none;
}
.briefing-section > details > summary h3 { margin: 0; }
.briefing-section > details > summary::-webkit-details-marker { display: none; }
.briefing-section > details > summary::after {
  content: '';
  margin-left: auto; width: 8px; height: 8px;
  border-right: 1.6px solid var(--text-secondary);
  border-bottom: 1.6px solid var(--text-secondary);
  transform: rotate(45deg) translate(-2px, -2px);
  transition: transform var(--transition);
}
.briefing-section > details[open] > summary::after { transform: rotate(-135deg) translate(-2px, -2px); }
.briefing-section > details > .briefing-grid { margin-top: 10px; }
.briefing-field {
  background: var(--surface-2);
  border: 1px solid var(--border); border-radius: var(--radius-card);
  padding: 10px 12px;
  display: grid; gap: 2px;
}
.briefing-field span {
  font-size: 11px; text-transform: uppercase; letter-spacing: .08em;
  color: var(--text-secondary);
}
.briefing-field strong { font-weight: 500; color: var(--text); font-size: 14px; word-break: break-word; }
.briefing-field strong a { color: var(--accent); }
.briefing-note {
  margin-top: 12px;
  padding: 12px 14px;
  background: rgba(var(--accent-rgb), .08);
  box-shadow: inset 2.5px 0 0 var(--accent);
  border-radius: var(--radius-card);
}
.briefing-note strong {
  display: block; margin-bottom: 6px;
  font-size: 12px; text-transform: uppercase; letter-spacing: .08em;
  color: var(--text-secondary);
}
.briefing-note p { margin: 0; color: var(--text); white-space: pre-wrap; }
.briefing-stats {
  display: flex; gap: 10px; flex-wrap: wrap;
}
.briefing-stat {
  background: var(--surface-2);
  border: 1px solid var(--border); border-radius: var(--radius-card);
  padding: 8px 14px;
  display: grid; gap: 2px; min-width: 120px;
}
.briefing-stat span {
  font-size: 11px; text-transform: uppercase; letter-spacing: .08em;
  color: var(--text-secondary);
}
.briefing-stat strong { font-size: 18px; }

@media (max-width: 720px) {
  .briefing-drawer { width: 100%; border-left: 0; }
  .briefing-drawer__head { padding: 16px; }
  .briefing-drawer__body { padding: 14px 16px 20px; }
  .briefing-drawer__actions { padding: 12px 16px; }
  .briefing-drawer__actions .primary-btn,
  .briefing-drawer__actions .ghost-btn { flex: 1 1 auto; min-height: 52px; font-size: 16px; }
  .briefing-grid { grid-template-columns: 1fr; }
  .briefing-stats { gap: 8px; }
  .briefing-stat { flex: 1 1 calc(50% - 8px); min-width: 0; }
}

/* Das Setter-Dashboard (setter-appt*, setter-day*, setter-section*,
   setter-kpis, setter-filter) ist samt seinem Markup verschwunden; der
   Redundanz-Pass vom 03.08.2026 hat die verwaisten Regeln geschnitten.
   Die Rolle heisst seit dem Sprachvertrag ohnehin Besucher. Rueckweg: git. */



/* ============================================================
   Iter 10 Etappe 24: Outcome-Modal (Setter-Workflow)
   ============================================================ */
.modal--outcome { max-width: 560px; }
.modal__header-sub { margin: 4px 0 0; color: var(--text-secondary); font-size: 13px; }
/* ⚠️ DIE 80 px LAGEN HINTER DEM FUSS, NICHT DAVOR (30.08.2026).
   `.oc-actions` ist das LETZTE Kind dieses Formulars — ein Bodenpolster am
   Formular kommt also NACH der Handlungszeile, nicht vor ihr. Gemessen auf
   390 x 620 in beiden Motoren: Formular-Unterkante 601 px, Fuss-Unterkante
   521 px — 80 px Leere unter den Knoepfen, und am Rechner genauso.
   Gemeint war einmal Luft fuer den durchsichtigen Verlaufs-Fuss von damals;
   der ist seit derselben Runde deckend, und ein deckender Fuss verdeckt
   nichts, vor dem man ihn schuetzen muesste. Sein Bodenpolster traegt er
   selbst (`.oc-actions`, unten). Die 0 steht ausdruecklich da und nicht als
   Weglassen: ohne sie erbt das Formular die 20 px Bodenpolster von
   `.modal__body` — gemessen wieder 20 px Leere unter den Knoepfen. */
.oc-form { display: grid; gap: 18px; padding-bottom: 0; }

/* Iter 13 Etappe 3: Termin-Tap-Assessment (Verloren/Folge-Termin) */
#oc-assess-body { display: grid; gap: 16px; }
.oc-form .field { margin: 0; }
.oc-form input,
.oc-form select,
.oc-form textarea {
  width: 100%; min-height: 44px;
  background: var(--surface-inset); color: var(--text);
  border: 1px solid var(--border); border-radius: var(--radius-button);
  padding: 10px 12px; font: inherit;
}
.oc-form textarea { min-height: 110px; resize: vertical; }
/* ⚠️ DIE DRITTE FUSSLEISTE DES HAUSES — UND SIE WAR DURCHSICHTIG.
   Gemessen am 30.08.2026 auf 390×620 in beiden Motoren, mit dem Markup aus
   components/appointment-outcome-modal.js:112/139: `background-color` war
   `rgba(0,0,0,0)`, die Deckung kam allein aus dem Verlauf — und dessen obere
   30 % sind durchsichtig. Auf halbem Rollweg stand das Feld «Antwort 11»
   mitsamt seinem Rahmen 48 px weit MITTEN IM KNOPF «Abbrechen» und war
   dort zu lesen. Genau das, was eine Handlungszeile nie tun darf: der
   Formularinhalt scheint durch sie hindurch.
   Warum es niemand sah: dieses Fenster heisst `.oc-actions`, nicht
   `.modal-actions` — die Reparatur der Handlungszeile (weiter oben, ab
   720 px) konnte es darum gar nicht erreichen. Ein Fehler, der an EINER
   Stelle geheilt wird und an der dritten stehen bleibt, ist nicht geheilt.
   Deckend heisst hier dasselbe wie dort: die Flaeche des Fensters, dazu die
   Haarlinie, damit die Kante auch als Kante gelesen wird. Der weiche Verlauf
   war Schmuck; Lesbarkeit ist Bedienbarkeit. */
/* …UND ER TRAEGT DEN DIALOGBODEN SELBST (30.08.2026, zweiter Griff).
   Deckend war er nach dem ersten Griff — ein FUSS war er noch nicht. Gemessen
   auf 390 x 620 in beiden Motoren, nachdem die erzwungene Vollhoehe weg war:
   Fuss-Unterkante 521 px, Formular-Unterkante 541 px — 20 px Leere unter den
   Knoepfen, und die Haarlinie hoerte beidseitig 20 px vor der Dialogkante auf.
   Das ist wortgleich der Befund, den `.modal-actions` weiter oben schon hinter
   sich hat: eine Karte im Formular, kein Fuss. Dieselbe Reparatur, dritter
   Ort — das Formular gibt sein Bodenpolster ab (`.oc-form`, oben), der Fuss
   greift mit negativen Seitenraendern bis an die Kante und polstert selbst.
   Warum hier eine EIGENE Regel und nicht die Wähler-Liste von `.modal-actions`
   erweitert: dieses Fenster heisst `.oc-actions`, und die dortige Liste haengt
   an vier `:has()`-Faellen fuer 60 fremde Rufer. Zwei Namen in einer Liste, die
   fuer den einen Namen gebaut ist, waere die schwerere Kopplung. */
.oc-actions {
  display: flex; gap: 8px; justify-content: flex-end; flex-wrap: wrap;
  position: sticky; bottom: 0; z-index: 2;
  background: var(--surface);
  border-top: 1px solid var(--border);
  margin: 0 -20px; padding: 12px 20px calc(12px + env(safe-area-inset-bottom));
  border-radius: 0 0 var(--radius-card) var(--radius-card);
}
.oc-actions .ghost-btn,
.oc-actions .primary-btn { min-height: 48px; padding: 0 22px; }

@media (max-width: 720px) {
  /* ⚠️ DER EINZIGE DIALOG DES HAUSES, DER SICH AUFBLIES (30.08.2026).
     `height: 100dvh` ZWINGT die volle Fensterhoehe — unabhaengig davon, wie
     wenig drinsteht. Gemessen auf 390 x 620 in beiden Motoren, mit dem
     Markup aus components/appointment-outcome-modal.js:101-145:
       Dialog 620 px hoch, Handlungszeile endet bei 521 px
       → 111 px Leere unter den Knoepfen (beim kurzen Baum-Schritt ~230 px),
       und der Dialog ragte mit [12 … 632] sogar 12 px ueber den Schirm,
       weil zu `height: 100dvh` noch sein eigener Rand kam.
     Jede andere Flaeche des Hauses macht es anders: `.modal` deckelt am
     Fenster und laesst die Hoehe dem INHALT folgen (weiter oben in diesem
     Block, `max-height: calc(100dvh - 24px)`). Genau das gilt ab hier auch
     hier — der Deckel bleibt, der Zwang faellt weg.
     Der Rest der Regel bleibt unangetastet: volle Breite und kein Eckenrund
     sind am Handy die Fassung dieses Fensters, nicht sein Fehler.
     NOCH NICHT ANGEFASST, gleicher Bau: `.modal--lead-picker` (weiter oben in
     dieser Datei) erzwingt dieselbe Vollhoehe. Dort traegt eine lange Liste
     den Schirm meist von selbst — geprueft ist es nicht, und es steht
     ausserhalb dieses Auftrags. */
  .modal--outcome { max-width: 100%; max-height: calc(100vh - 24px); max-height: calc(100dvh - 24px); border-radius: 0; }
  /* Am Handy mehr Luft — die Seitenpolster bleiben, sonst stuenden die Knoepfe
     wieder an der nackten Dialogkante (der Fuss reicht seit oben bis dorthin).
     Kein Eckenrund: `.modal--outcome` ist hier randlos. */
  .oc-actions { padding: 14px 20px max(24px, env(safe-area-inset-bottom)); border-radius: 0; }
  .oc-actions .ghost-btn,
  .oc-actions .primary-btn { flex: 1 1 auto; min-height: 52px; font-size: 16px; }
  .oc-form input,
  .oc-form select,
  .oc-form textarea { font-size: 16px; min-height: 48px; }
}

/* ============================================================
   Iter 10 Etappe 23: Edit-Diff (firm_edits in Lead-Verlauf-Tab)
   ============================================================ */
.activity-item--edit { background: rgba(var(--accent-rgb), .06); }
.edit-diff { display: inline-flex; gap: 6px; align-items: baseline; flex-wrap: wrap; }
.edit-diff__old {
  color: var(--text-secondary); text-decoration: line-through;
  max-width: 240px; overflow: hidden; text-overflow: ellipsis;
}
.edit-diff__arrow { color: var(--text-secondary); display: inline-flex; align-self: center; line-height: 0; }
.edit-diff__new {
  color: var(--accent); font-weight: 600;
  max-width: 240px; overflow: hidden; text-overflow: ellipsis;
}
.activity-item__reason {
  color: var(--text-secondary); font-style: italic; font-size: 12px;
  margin-left: auto;
}
@media (max-width: 720px) {
  .edit-diff__old, .edit-diff__new { max-width: 100%; }
  .activity-item__reason { margin-left: 0; width: 100%; }
}

/* ============================================================
   Iter 13 Etappe 7: Outcome-Roh-Feedbacks (Lead-Timeline)
   Score-frei — nur die angeklickten Labels, eingewebt in den Verlauf.
   ============================================================ */
/* Iter 27 Welle F: Akzent als Inset-Bar statt border-left (Kill-Liste) */
.activity-item--outcome {
  display: block;
  background: rgba(var(--accent-rgb), .06);
  box-shadow: inset 2.5px 0 0 var(--accent);
}
.outcome-block__head {
  display: flex; flex-wrap: wrap; gap: 10px; align-items: baseline;
  margin-bottom: 8px;
}
.outcome-block__ctx { color: var(--text-secondary); font-size: 12px; }
.outcome-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.outcome-chip {
  display: inline-flex; flex-direction: column; gap: 1px;
  padding: 4px 8px; border-radius: var(--radius-card);
  background: rgba(var(--tint-rgb), .04); border: 1px solid var(--border);
}
.outcome-chip__dim {
  font-size: 11px; letter-spacing: .04em; text-transform: uppercase;
  color: var(--text-secondary);
}
.outcome-chip__val { font-size: 13px; color: var(--text); font-weight: 600; }

/* Iter 15 E4c: Termin-Eintrag im Verlauf-Tab (lückenlose Chronologie).
   Iter 27 Welle F: Inset-Bar (Token) statt border-left mit Roh-rgba. */
.activity-item--appointment {
  background: rgba(var(--info-rgb), .06);
  box-shadow: inset 2.5px 0 0 var(--info-muted);
}
.outcome-chip__note { font-size: 12px; color: var(--text-secondary); font-style: italic; }

/* =========================================================================
   Ziele / Soll-Ist (Iter 14 Etappe 2) — Editor + Dashboard-Panel
   ========================================================================= */
.month-nav { display: flex; align-items: center; gap: 8px; }
.goal-cards { display: flex; flex-direction: column; gap: 16px; margin-top: 16px; }
.goal-card__head { display: flex; align-items: center; gap: 10px; margin-bottom: 14px; }
.goal-card__head strong { font-size: 15px; font-weight: 600; letter-spacing: -.005em; }
/* Team-Karte: Inset-Accent-Bar statt cyaner Vollborder (DESIGN.md Kill-Liste) */
.goal-card--team { box-shadow: var(--shadow-sm); }
.goal-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px; }
.goal-metric { display: flex; flex-direction: column; gap: 4px; }
.goal-metric__label { font-size: .8rem; color: var(--text-secondary); }
.goal-metric input {
  min-height: 44px; width: 100%; padding: 8px 10px;
  background: var(--surface-inset); border: 1px solid var(--border);
  border-radius: var(--radius-button); color: var(--text-primary);
  font-size: 1rem; font-variant-numeric: tabular-nums; transition: border-color .15s ease;
}
.goal-metric input:focus-visible { outline: 2px solid var(--accent-hover); outline-offset: 1px; border-color: var(--accent-hover); }
.goal-metric input.is-saved { border-color: var(--high); }
.goal-metric__actual { font-size: .78rem; color: var(--text-secondary); font-variant-numeric: tabular-nums; }

/* Soll-Ist-Panel (Dashboard): Fortschrittsbalken pro Metrik */
.soll-ist-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px 20px; }
.soll-ist { display: flex; flex-direction: column; gap: 6px; }
.soll-ist__top { display: flex; justify-content: space-between; align-items: baseline; gap: 8px; }
.soll-ist__label { color: var(--text-secondary); font-size: 13px; }
.soll-ist__nums { font-variant-numeric: tabular-nums; font-size: 13px; }
.soll-ist__nums strong { color: var(--text-primary); }
.soll-ist__bar { height: 8px; border-radius: 999px; background: var(--surface-3); overflow: hidden; }
.soll-ist__fill { height: 100%; border-radius: 999px; transition: width .3s ease; }

/* Pipeline-Forecast (Iter 14 Etappe 3) */
.forecast { display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: 16px; }

@media (max-width: 640px) {
  .goal-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .soll-ist-grid { grid-template-columns: 1fr; }
  .forecast { flex-direction: column; align-items: stretch; }
}

/* Zeitraum-Trend (Iter 14 Etappe 4) */
.seg { display: inline-flex; gap: 2px; background: var(--surface-inset); border: 1px solid var(--border); border-radius: var(--radius-card); padding: 3px; }
.seg__btn { min-height: 30px; padding: 4px 13px; border: 0; background: transparent; color: var(--text-secondary); font-size: 12px; font-weight: 650; letter-spacing: 0; text-transform: none; border-radius: var(--radius-button); cursor: pointer; transition: background var(--transition), color var(--transition); }
.seg__btn:hover { color: var(--text-primary); }
.seg__btn.is-active { background: var(--accent-soft); color: var(--text-primary); box-shadow: inset 0 0 0 1px var(--accent-line); }
@media (max-width: 1024px), (pointer: coarse) { .seg__btn { min-height: 44px; } }

/* DER ZEITRAUM-SCHALTER DARF NIE AUS DEM BILD LAUFEN (Pruefbefund 23.08.2026).
   Der Schalter trug bis zum 23.08. immer genau drei Knoepfe (Monat · Quartal ·
   Jahr) und passte damit an jedes Geraet. Seit `kpiPerioden(abJahr)` kommen bei
   einem Alt-Kunden bis zu vier Jahreszahlen UND «Alles» dazu — bis zu acht.
   GEMESSEN auf der Buehne bei 390 px (Kunde seit 2019): der Schalter wurde
   499 px breit und lief bis x=523. `body { overflow-x: clip }` schnitt ihn ab,
   ohne einen Rollbalken zu geben — «2023», «2022» und ausgerechnet «Alles»
   waren am Telefon UNERREICHBAR. Ein Knopf, den man nicht antippen kann, ist
   eine tote Tuer (BEREICHE §11.10), und «Alles» ist genau der Weg, ueber den
   die weiter zurueckliegenden Jahre ueberhaupt noch sichtbar sind.
   `flex-wrap` loest das ohne jede andere Wirkung: solange alles in eine Zeile
   passt (drei Knoepfe, jede breite Flaeche), aendert die Regel NICHTS — sie
   greift erst, wenn sonst abgeschnitten wuerde. Darum ohne Medienabfrage: auch
   ein schmales Fenster am Rechner ist ein schmales Fenster.
   Nur der Zeitraum-Schalter (`data-akte-teil="zeitraum"`), nicht `.seg`
   ueberall — kein anderer Schalter im Haus waechst aus den Daten.
   Beweis: scripts/_verkauf_ui_test.mjs, «der laengste Schalter (8 Zeitraeume)». */
.seg[data-akte-teil="zeitraum"] { flex-wrap: wrap; }

/* Anruf-Ablauf: «Wie geht es weiter?» — drei gleichwertige Wege untereinander,
   damit jede Wahl auf dem Handy voll erreichbar ist. Der Stapel liegt NACH den
   Basis-Regeln, sonst greift er dort nicht (Lehre aus dem CSS-Kaskaden-Fall). */
.call-when { margin-top: 14px; }
.call-when .so2-chips { margin-top: 6px; }

.sparkline { display: block; width: 100%; height: 30px; overflow: visible; }


/* Stalling-Sicht „Was bleibt liegen" (Iter 14 Etappe 5) */
/* Iter 23 Cockpit-Reskin: SVG-Icons (statt Emoji ⏳📅) sauber inline, Rest-
   Zähler-Link in die Vollansicht, Zähler-Badge in der Gruppen-Überschrift. */
.stalling-more {
  display: inline-flex; align-items: center; gap: 4px;
  margin-top: 10px; min-height: 44px; padding: 6px 2px;
  color: var(--accent-strong); font-size: 13px; font-weight: 600;
}
.stalling-more:hover { color: var(--accent-bright); }
/* Iter 25 W2: dezenter Queue-Hinweis in Termin-Gruppen (kein Sprung-Ziel).
   --text-secondary statt -tertiary: bei 13px hält nur -secondary WCAG-AA
   (−tertiary läge im Dark bei 3.79:1 = AA-Fail; Cockpit-Lehre Iter 23). */
.today-more { margin: 10px 2px 0; color: var(--text-secondary); font-size: 13px; }

/* COS-Etappe 0.1 (01.09.2026) — der Aufklapp-Knopf jeder Tages-Gruppe.
   BEFUND, DER DIESE REGEL AUSLOEST: `today-more--tuer` stand seit Iter 25 im
   Markup des Aufgaben-Ueberlaufs und war in KEINEM Stylesheet definiert
   (gemessen 01.09.: 0 Treffer in grund.css und patch-*.css). Eine unbekannte
   Klasse ist in CSS stumm — kein Fehler, keine Warnung. Der Knopf fiel damit
   auf die native Browser-Schaltflaeche zurueck: graues Kaestchen mit
   Systemrand mitten in einem Precision-Ink-Panel, und ohne Griff-Boden.
   Jetzt tragen ihn sechs Gruppen; er muss also wirklich aussehen wie eine Tuer.
   Gestalt bewusst von `.stalling-more` uebernommen (direkt darueber): dieselbe
   Frage, dieselbe Anmutung — nur als Knopf statt als Verweis, weil er an Ort
   und Stelle aufklappt statt wegzuspringen. min-height 44px ist der
   Griff-Boden (eiserne Regel, jede Bildschirmgroesse). */
.today-more--tuer {
  display: inline-flex; align-items: center; gap: 4px;
  min-height: 44px; padding: 6px 2px;
  background: transparent; border: 0;
  color: var(--accent-strong); font-size: 13px; font-weight: 600;
}
.today-more--tuer:hover { color: var(--accent-bright); }
.today-more--tuer:active { transform: scale(.985); }

/* =========================================================================
   Iter 15 Etappe 1 — Touch-Target-Konsolidierung (≥44px)
   Single source of truth. Schliesst verstreute Alt-Epochen-Lücken, in denen
   spätere Regeln den 44px-Floor unterliefen (per Baseline-Audit @390 belegt).
   Bewusst klein (dichte Desktop-Toolbars, Maus-Kontext): .ghost-btn--xs,
   .icon-btn--sm, .qa-btn/.time-pill/.cal-toggle (≤720px bereits 44px) —
   deren Tablet-Touch (721–1024px) folgt in Etappe 3 (Tablet-Layout).
   ========================================================================= */
input[type="search"] { min-height: 44px; }   /* .field-Regel listet kein type=search → war 30px */
.month-nav .ghost-btn { min-width: 44px; min-height: 44px; justify-content: center; }  /* Ziele ‹ › — Breite war 37px */

/* =========================================================================
   Iter 15 Etappe 3 — Tablet-Touch-Floor (721–1024px) + alle Touch-Geräte.
   Die E1/E2-Fixes sitzen in @media(max-width:720px) und greifen auf Tablets
   (768/1024px) NICHT → dort fielen time-pill(38)/qa-btn(32)/cal-toggle(40)/
   ghost-btn--xs(34)/user-tab(26)/icon-btn--sm(32) unter 44px (holistischer
   Audit @768+@1024 belegt). Nur Mindestmaße + Zentrierung, kein Layout-
   Eingriff: qa-btn behält sein 720px-Flex (flex/padding gewinnen, display nicht
   in Konflikt). `, (pointer:coarse)` deckt echte Touch-Geräte jeder Breite ab;
   Desktop-Maus >1024px bleibt bewusst dicht.
   Bewusste Ausnahmen (Bruch-Risiko > 4px-Gewinn): .cal-event (40px; im Monats-
   Kalender absolut positioniert → 44px ließe Events überlappen = Render-Bug),
   .firm-link (30px; Inline-Link in dichten Listen/Tabellen → bläht Zeilen).
   ========================================================================= */
@media (max-width: 1024px), (pointer: coarse) {
  .time-pill, .cal-toggle, .ghost-btn--xs, .user-tab, .qa-btn {
    min-height: 44px; display: inline-flex; align-items: center; justify-content: center;
  }
  .icon-btn--sm { min-width: 44px; min-height: 44px; }  /* schon grid-zentriert via .icon-btn */
  .check-row label { min-height: 44px; }                /* assign-modal Prio-Filter (Hoch/Mittel/Niedrig) — war 24px */
  /* E6: Die firm-link-Ausnahme (30px, dichte Listen) gilt NICHT für den
     alleinstehenden Goals-Empty-State-CTA — dort ist 44px risikofrei. */
}

/* =========================================================================
   Iter 17 Etappe 2 — Skeleton-Loading (Daily-Driver-Polituren).
   Drei Modi, gemeinsame Pulse-Animation. Wird beim ersten Render gesetzt,
   bevor die echten Daten ankommen (kein Layout-Shift, weil die Skeleton-
   Hoehen den realen Komponenten nahe sind). Animation wird durch den
   E1-prefers-reduced-motion-Block unten auf 0.01ms gedrueckt (statischer
   Grauschimmer ohne Pulse) — wichtig fuer vestibulaere Empfindlichkeit.
   ========================================================================= */
.skeleton, .skeleton-line, .skeleton-card, .skeleton-row td.skeleton-cell {
  background: linear-gradient(90deg,
    rgba(var(--tint-rgb), .04) 0%,
    rgba(var(--tint-rgb), .10) 50%,
    rgba(var(--tint-rgb), .04) 100%);
  background-size: 200% 100%;
  animation: skeleton-pulse 1.5s ease-in-out infinite;
  border-radius: var(--radius-card);
}
.skeleton-line { height: 12px; margin: 10px 0; }
.skeleton-line--lg { height: 22px; }
.skeleton-line--sm { height: 8px; }
.skeleton-line--w50 { width: 50%; }
.skeleton-line--w70 { width: 70%; }
.skeleton-line--w85 { width: 85%; }
.skeleton-card { height: 64px; margin: 8px 0; border-radius: var(--radius-card); }  /* Iter 27: Lead-Zeilen-Dichte (~60px) statt Alt-Karten-92px */
.skeleton-panel { padding: 4px 2px; }
.skeleton-row td.skeleton-cell { height: 18px; padding: 0; border-radius: var(--radius-card); }
@keyframes skeleton-pulse {
  0%   { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}

/* --- P15 (Owner-Video-Audit 09.08.) — Skelette, die HOEHE reservieren ------
   Bis heute war ein Ladezustand eine leere Flaeche mit einem Satz darin: die
   Kennzahl-Kacheln existierten waehrend des Ladens gar nicht und schoben beim
   Erscheinen den ganzen Inhalt nach unten (c1 B8), der Detail-Kopf zeigte ein
   Platzhalter-Wort, das wie ein echter Name aussah (c4 B13), und an drei
   Stellen stand buchstaeblich «…» (c4 B29, c5 B17, c6 B4).

   DIE HOEHE WIRD NICHT GERATEN, SIE WIRD ABGELEITET. Jeder Balken traegt die
   Klasse des Textes, den er vertritt (`stat__value`, `stat__label`,
   `stat__sub`) und ein `&nbsp;` als Inhalt — der Browser rechnet damit exakt
   dieselbe Zeilenhoehe wie spaeter fuer den echten Text. Und weil das Skelett
   zusaetzlich die Container-Klasse der echten Leiste traegt (`vk-kacheln`,
   `stat-strip`, …), gelten alle Handy-Regeln (2×2 statt 4×1, Zeichen aus,
   Unterzeile aus) fuer Skelett und Inhalt gleichermassen. Ein Skelett, das
   seine eigenen Masse mitbrachte, waere genau die zweite Wahrheit, an der die
   Flaechen bisher gesprungen sind.

   Die Nachfahren-Selektoren (`.skeleton-kachel .skeleton`) stehen hier, weil
   `.gz-ic` und Verwandte weiter unten eine `background`-Kurzform setzen, die
   den Verlauf sonst loeschte — zwei Klassen schlagen eine, unabhaengig von
   der Reihenfolge in dieser Datei. */
.skeleton-kachel .skeleton, .skeleton-karte .skeleton, .skeleton-kopf .skeleton {
  background: linear-gradient(90deg,
    rgba(var(--tint-rgb), .04) 0%,
    rgba(var(--tint-rgb), .10) 50%,
    rgba(var(--tint-rgb), .04) 100%);
  background-size: 200% 100%;
  animation: skeleton-pulse 1.5s ease-in-out infinite;
  border-radius: var(--radius-card);
}
/* Der Balken ersetzt Text — er darf nie mehr Hoehe haben als die Zeile, die er
   vertritt. `&nbsp;` liefert die Zeilenhoehe, die Breite kommt von aussen. */
.skeleton--wort, .skeleton--titel, .skeleton--zeile {
  display: inline-block; max-width: 100%; color: transparent;
  -webkit-user-select: none; user-select: none;
}
.skeleton--titel { display: block; font-size: 15px; font-weight: 600; line-height: 1.35; width: 45%; }
.skeleton--zeile { display: block; font-size: 12.5px; line-height: 1.4; width: 70%; }
.skeleton--w50 { width: 50%; }
.skeleton--w70 { width: 70%; }
.skeleton--w85 { width: 85%; }
/* Das Zeichen-Quadrat der Kachel: dieselbe Kantenlaenge wie das echte, damit
   die Kachel nicht beim Erscheinen des Zeichens waechst. */
.skeleton-kachel .skeleton--zeichen { border-radius: calc(var(--gz-ic-gr, 32px) * .3); }
/* Die Kachel selbst bleibt die ECHTE Kachel (Klasse kommt von der Flaeche) —
   hier faellt nur weg, was ohne Inhalt luegen wuerde: Zeigefinger und
   Hover-Reaktion auf etwas, das man nicht anfassen kann. */
.skeleton-kachel, .skeleton-karte { cursor: default; pointer-events: none; }
.skeleton-liste { display: grid; gap: 10px; pointer-events: none; }
/* Skeleton-Karten tragen NIE die Identitaets-Klasse echter Karten
   (firm-card, vk-karte, …) — Attrappen-Falle: Tests und App-Logik
   selektieren darueber. Geometrie kommt von eigenen Klassen. */
.skeleton-karte--lead { min-height: 108px; }
/* Ohne eigene Karten-Klasse traegt das Skelett selbst den Rahmen — sonst
   stuenden nackte Balken im Nichts. */
.skeleton-karte {
  display: grid; gap: 8px; padding: 14px 16px;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-card);
}
.skeleton-kopf { display: block; }
/* Der Reiter-Platzhalter traegt die Klasse des echten Reiters (Polsterung,
   44px Mindesthoehe) — die zwei Klassen hier schlagen dessen `background`. */
.skeleton.skeleton--reiter {
  display: inline-block; color: transparent; pointer-events: none;
  -webkit-user-select: none; user-select: none;
  background: linear-gradient(90deg,
    rgba(var(--tint-rgb), .04) 0%,
    rgba(var(--tint-rgb), .10) 50%,
    rgba(var(--tint-rgb), .04) 100%);
  background-size: 200% 100%;
  animation: skeleton-pulse 1.5s ease-in-out infinite;
}

/* =========================================================================
   Iter 18 Etappe 2 — Termin-Action-Buttons (Maps + iCal).
   Mini-Buttons in Termin-Listen / Kalender-Items / Briefing-Headers.
   Touch-Floor 32px Desktop / 44px Mobile (Memory project_tablet_touch_breakpoint).
   ========================================================================= */
.appt-link-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 32px;
  min-height: 32px;
  padding: 0 6px;
  border: 1px solid var(--border);
  background: transparent;
  border-radius: var(--radius-button);
  cursor: pointer;
  font-size: 14px;
  line-height: 1;
  text-decoration: none;
  color: var(--text);
  transition: background-color 0.15s ease, border-color 0.15s ease;
}
.appt-link-btn:hover { background: rgba(var(--tint-rgb), 0.05); border-color: var(--line-strong); }
.appt-link-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.appt-link-btn:disabled { opacity: 0.5; cursor: not-allowed; }
.appt-link-btns { display: inline-flex; gap: 6px; align-items: center; }
.briefing-drawer__head-actions { display: inline-flex; gap: 6px; align-items: center; margin-left: auto; }
@media (max-width: 1024px), (pointer: coarse) {
  .appt-link-btn { min-width: 44px; min-height: 44px; font-size: 16px; }
}

/* =========================================================================
   Iter 19 Etappe 2 — Einwand-Köcher (Caller-Tab im firm-modal).
   Kompakte tappbare Label-Karten; Tap markiert + klappt die Antwort gross auf.
   Touch-Floor 44px ab Tablet/Coarse (Memory project_tablet_touch_breakpoint).
   ========================================================================= */
.objection-hint {
  color: var(--text-secondary);
  font-size: 13px;
  line-height: 1.5;
  margin: 0 0 12px;
}
.objection-cards { display: flex; flex-direction: column; gap: 8px; }
/* Iter 27 Welle F: Zeilen-Idiom (Fläche statt Rahmen); markiert = Accent-Tint
   + Inset-Bar links (Vollborder-Selektion gefallen, DESIGN.md Kill-Liste). */
.objection-card {
  display: flex;
  flex-direction: column;
  gap: 6px;
  width: 100%;
  text-align: left;
  padding: 12px 14px;
  border: 1px solid transparent;
  border-radius: var(--radius-card);
  background: var(--surface-2);
  color: var(--text);
  font: inherit;
  cursor: pointer;
  transition: background var(--transition), box-shadow var(--transition);
}
.objection-card:hover { background: var(--surface-3); }
.objection-card:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.objection-card--marked {
  background: linear-gradient(180deg, rgba(var(--accent-rgb), .09), rgba(var(--accent-rgb), .05));
  box-shadow: inset 2.5px 0 0 var(--accent);
}
/* Fremdes Lead (Manager/Admin-Ansicht): nicht tappbar — kein Pointer/Hover-Reiz. */
.objection-card--readonly { cursor: default; }
.objection-card--readonly:hover { background: var(--surface-2); }
.objection-card--readonly.objection-card--marked:hover {
  background: linear-gradient(180deg, rgba(var(--accent-rgb), .09), rgba(var(--accent-rgb), .05));
}
.objection-card__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}
.objection-card__label { font-size: 15px; font-weight: 600; line-height: 1.35; min-width: 0; overflow-wrap: anywhere; }
.objection-badge {
  flex: none;
  font-size: 12px;
  font-weight: 600;
  color: var(--accent);
  white-space: nowrap;
}
.objection-response {
  display: none;
  font-size: 15px;
  line-height: 1.6;
  padding: 10px 12px;
  box-shadow: inset 2.5px 0 0 var(--accent);
  border-radius: var(--radius-card);
  background: rgba(var(--accent-rgb), 0.10);
  color: var(--text);
  white-space: pre-wrap;       /* mehrzeilige Admin-Antworten (textarea) behalten Absätze */
  overflow-wrap: anywhere;     /* lange URLs/Wörter sprengen das Modal nicht */
}
.objection-response.is-open { display: block; }
@media (max-width: 1024px), (pointer: coarse) {
  .objection-card { padding: 14px; }
  .objection-card__label { font-size: 16px; }
  .objection-response { font-size: 16px; }
}

/* Iter 19 E3 — Manager-Heatmap (user-detail-modal) + Lead-Drill-Down-Modal.
   Bucket-Farben spiegeln die Konversion: termin=grün, offen=grau, verloren=rot. */
.objection-heatmap { display: flex; flex-direction: column; gap: 8px; }
.objection-heat-row {
  display: flex;
  flex-direction: column;
  gap: 8px;
  width: 100%;
  text-align: left;
  padding: 12px 14px;
  border: 0;
  border-radius: var(--radius-card);
  background: rgba(var(--tint-rgb), .025);
  color: var(--text);
  font: inherit;
  cursor: pointer;
  transition: background-color var(--transition);
}
.objection-heat-row:hover { border-color: var(--text-secondary); background: rgba(var(--tint-rgb), 0.04); }
.objection-heat-row:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.objection-heat-row__top {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
}
.objection-heat-row__label { font-size: 15px; font-weight: 600; line-height: 1.35; min-width: 0; overflow-wrap: anywhere; }
.objection-heat-row__count { flex: none; font-size: 13px; font-weight: 600; color: var(--text-secondary); white-space: nowrap; }
.objection-heat-bar {
  display: flex;
  height: 8px;
  border-radius: var(--radius-card);
  overflow: hidden;
  background: var(--surface-2);
}
.objection-heat-bar__seg { height: 100%; }
.objection-heat-bar__seg.is-termin  { background: var(--high); }
.objection-heat-bar__seg.is-neutral { background: var(--text-secondary); }
.objection-heat-bar__seg.is-lost    { background: var(--low); }
.objection-heat-row__legend { display: flex; flex-wrap: wrap; gap: 6px 12px; font-size: 12px; }
.objection-bucket { display: inline-flex; align-items: center; gap: 4px; font-size: 12px; font-weight: 600; white-space: nowrap; }
.objection-bucket.is-termin  { color: var(--high); }
.objection-bucket.is-neutral { color: var(--text-secondary); }
.objection-bucket.is-lost    { color: var(--low); }

/* Lead-Drill-Down-Liste (objection-lead-list-modal) */
.objection-lead-list { display: flex; flex-direction: column; gap: 6px; }
.objection-lead-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  width: 100%;
  text-align: left;
  padding: 12px 14px;
  border: 1px solid transparent;
  border-radius: var(--radius-card);
  background: var(--surface-2);
  color: var(--text);
  font: inherit;
  cursor: pointer;
  transition: background var(--transition);
}
.objection-lead-row:hover { background: var(--surface-3); }
.objection-lead-row:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.objection-lead-row__main { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.objection-lead-row__main strong { overflow-wrap: anywhere; }
.objection-lead-row__meta { font-size: 12px; color: var(--text-secondary); }
.objection-lead-row__tags { display: flex; align-items: center; gap: 8px; flex: none; flex-wrap: wrap; justify-content: flex-end; }
@media (max-width: 1024px), (pointer: coarse) {
  .objection-heat-row, .objection-lead-row { min-height: 44px; padding: 14px; }
  .objection-heat-row__label { font-size: 16px; }
}

/* Standortansicht (Iter 21 E1) — sl-* Namespace.
   Modal-Teile nutzen bestehende .modal / .modal__header / .modal__body /
   .modal-section / .modal-grid / .info-card / .panel__eyebrow / .icon-btn
   Klassen aus style.css (NICHT neu gestylt hier). .view-toggle ebenfalls
   bestehend (siehe style.css ~L832, genutzt in caller-leads.js) — sl-seg ist
   nur ein schlanker Wrapper mit Abstand.
   Platzierung: VOR dem prefers-reduced-motion-Schlussblock (der muss laut
   eigenem Kommentar letzter Block bleiben), NICHT dahinter anhaengen. */

/* .admin-page / .admin-page__head / .admin-page__hint sind bereits als Klassen
   in admin-objections.js im Einsatz, hatten dort aber NIE zugehoeriges CSS
   (verifiziert: 0 Treffer fuer "admin-page" in style.css vor diesem Patch —
   bestehende Codebase-Luecke, nicht durch E1 verursacht). Minimal-Grundgeruest
   hier ergaenzt, damit BEIDE Views (Einwand-Koecher + Standorte) endlich einen
   layouteten Seitenkopf bekommen — kein neues Farb-Token, nur Layout. */
.admin-page { padding: 0; }
.admin-page__head { margin-bottom: 18px; }
/* EINHEIT.md 1.5 schlichtet den Seitentitel auf EINEN Grad: 26/650/-.02em
   (.gz-kopf h1) — «innen und aussen gleich gross». Die Iter-27-Skala (20/650
   aus DESIGN.md §2) war der zweite Grad, den 1.5 ausdrücklich verbietet. */
.admin-page__head h1 { margin: 0 0 4px; font-size: 26px; font-weight: 650; letter-spacing: -.02em; color: var(--text-primary); }
.admin-page__hint { margin: 0; color: var(--text-secondary); font-size: 13px; line-height: 1.5; max-width: 780px; }

/* .page-head griff seit dem 29.07. ins Leere (acht Views nutzen sie, keine
   Definition — Prüfblick 10.08., Querschnitt Q1/Q2): der Titel fiel auf den
   Browser-Default (28px/700), Primärknopf und Hinweis stapelten sich ohne
   Ordnung. Ab hier ist sie dieselbe Bauart wie .admin-page__head, samt der
   Handy-Regel vom 06.08. (die Kopfzeile der App trägt den Namen bereits). */
.page-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 12px; flex-wrap: wrap; margin-bottom: 18px; }
.page-head h1 { margin: 0; font-size: 26px; font-weight: 650; letter-spacing: -.02em; color: var(--text-primary); }
@media (max-width: 900px) {
  .page-head h1 { display: none; }
  .page-head { margin-bottom: 0; }
  .page-head:has(> h1:only-child) { display: none; }
  .page-head:has(.primary-btn, .ghost-btn) { margin-bottom: 12px; }
}

/* Iter 27 Welle D: Die Icon-Quadrat-KPI-Karten (.sl-kpis/.sl-kpi) sind abgebaut —
   alle Verkaufs-Views rendern den Foundation-.stat-strip (EIN Panel, Hairlines). */

/* Filterbar */
.sl-filters {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  align-items: end;
  margin-bottom: 14px;
}
.sl-filters .field { min-width: 150px; }
/* Full-Width-Kanon: Suchfeld waechst mit, aber kippt nicht ins Absurde
   (Review-Fund 2026-07-05: 2700px-Suchfeld auf 3440er neben 4 schmalen Selects). */
.sl-filters .field--wide { min-width: min(320px, 100%); flex: 1 1 260px; max-width: 720px; }
/* IDs (LOC-0075) brechen nie um (Review-Fund: zweizeilig bei 768). */
.sl-table td[data-label="ID"] { white-space: nowrap; }

/* Segment-Umschalter Wrapper */
.sl-seg { margin-bottom: 4px; }

/* Ergebnis-Zaehler */
.sl-count {
  margin: 0 0 10px;
  color: var(--text-secondary);
  font-size: 13px;
  font-variant-numeric: tabular-nums lining-nums;
}

/* Tabelle — erbt .team-table Grundstil (Border/Header), sl-table ergaenzt
   Klick-Zeilen. */
.sl-table tr[data-id],
.sl-table tr[data-ort],
.sl-table tr[data-month],
.sl-table tr[data-expense] {
  cursor: pointer;
  transition: background var(--transition);
}
.sl-table tr[data-id]:hover td,
.sl-table tr[data-ort]:hover td,
.sl-table tr[data-month]:hover td,
.sl-table tr[data-expense]:hover td,
.sl-table tr[data-id]:focus-visible td,
.sl-table tr[data-ort]:focus-visible td,
.sl-table tr[data-month]:focus-visible td,
.sl-table tr[data-expense]:focus-visible td {
  background: rgba(var(--accent-rgb),.08);
}
.sl-table tr[data-id]:focus-visible,
.sl-table tr[data-ort]:focus-visible,
.sl-table tr[data-month]:focus-visible,
.sl-table tr[data-expense]:focus-visible {
  outline: 2px solid var(--accent-hover);
  outline-offset: -2px;
}

/* Badges — sl-badge: Alpha-Fläche + Strong-Text, seit W-B GERAHMT
   (EINHEIT 4.7 schlägt das ältere DESIGN.md §3/§4: nie ein farbiges
   Wort ohne Rahmen). */
.sl-badge {
  display: inline-flex;
  align-items: center;
  padding: 4px 10px;
  border-radius: var(--radius-badge);
  /* Seit v395 dasselbe Chip-Kleid wie `.badge`: gesperrte Versalien (Stil, nie
     Text — die Wörter bleiben gemischt im DOM), Referenz Bild 02 «STARTKLAR». */
  font-size: 11px;
  font-weight: 650;
  letter-spacing: .12em;
  text-transform: uppercase;
  line-height: 1.3;
  /* EINHEIT 4.7 (Rahmenpflicht bleibt): nie ein farbiges Wort ohne Rahmen. */
  border: 1px solid var(--line-strong);
  white-space: nowrap;
}
.sl-badge--aktiv { background: rgba(var(--good-rgb),.13); color: var(--good-strong); border-color: rgba(var(--good-rgb),.35); }
.sl-badge--pipeline { background: rgba(var(--warn-rgb),.13); color: var(--warn-strong); border-color: rgba(var(--warn-rgb),.35); }
.sl-badge--storniert { background: rgba(var(--bad-rgb),.13); color: var(--bad-strong); border-color: rgba(var(--bad-rgb),.35); }

/* =========================================================================
   Mobile (Projekt-Cascade-Regel: eigener Block NACH den Basis-Regeln oben,
   siehe Memory project_css_cascade_mobile).
   ========================================================================= */
@media (max-width: 720px) {
  /* Iter 27 Welle D: 2-spaltiges Filter-Grid (Welle-B-Muster) statt Spalten-Flex.
     Wurzel-Fix: flex-direction:column machte die flex-basis 260px der .field--wide
     zur HÖHE → ~260px Leerraum zwischen Suche und Kanton (iPhone-Beleg). */
  .sl-filters { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; align-items: end; }
  .sl-filters .field,
  .sl-filters .field--wide { min-width: 0; width: 100%; }
  .sl-filters .field--wide { grid-column: 1 / -1; }
  /* Die Wahl-Leiste (gespeicherte Ansichten) bekam hier EINE der zwei
     Spalten — 170 px für «Ansicht: keine gewählt ▾» plus zwei Knöpfe; der
     Text stand als «keine gew» da (Standorte, Vermittlungen, Vertriebe,
     Stammdaten auf 390 px; Prüfer-Fund 05.09.). Die Leiste ist eine Zeile,
     wie das breite Suchfeld. */
  .sl-filters > [data-slot="ansichten"] { grid-column: 1 / -1; }

  /* Tabelle -> gestapelte Zeilenblöcke. min-width:0 zwingend: .sl-table erbt
     min-width:640px von .team-table -> ohne Reset scrollt die Karten-Liste
     bei 375px horizontal (Review-Finding E1, Playwright-belegt).
     Iter 27: Hairline-Blöcke statt Box-in-Box-Karten (DESIGN.md §1 — Zeilen
     mit Separatoren IN der Liste, kein Rahmen um jeden Datensatz). */
  .sl-table thead { display: none; }
  .sl-table { min-width: 0; }
  .sl-table, .sl-table tbody, .sl-table tr, .sl-table td { display: block; width: 100%; }
  .sl-table tr {
    border: 0;
    border-bottom: 1px solid var(--border);
    border-radius: 0;
    margin: 0;
    padding: 6px 0;
    background: transparent;
  }
  .sl-table tr:last-child { border-bottom: 0; }
  .sl-table td {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 12px;
    padding: 7px 14px;
    border-bottom: 0;
    text-align: right;
  }
  .sl-table td::before {
    content: attr(data-label);
    color: var(--text-tertiary);
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: .06em;
    font-weight: 600;
    text-align: left;
  }
}

/* Touch-Floor (Tablet-Bruchzone + coarse Pointer, siehe Memory
   project_tablet_touch_breakpoint — @720px allein reicht nicht). */
@media (max-width: 1024px), (pointer: coarse) {
  .sl-table tr[data-id],
  .sl-table tr[data-ort],
  .sl-table tr[data-month],
  .sl-table tr[data-expense] {
    min-height: 44px;
  }
  .sl-filters select,
  .sl-filters .search-input,
  .sl-filters input {
    min-height: 44px;
  }
}

/* Standort-Admin-Edit (Iter 21 E1b) — Zusatz zu sales-locations.css.
   Nutzt ansonsten ausschliesslich bestehende Klassen: .field / .primary-btn /
   .ghost-btn / .info-card / .modal-grid / .modal-actions / .modal-section
   (alle bereits in style.css definiert, siehe user-modal.js-Vorbild).
   Nur 2 neue Klassen noetig: sl-edit-grid (Formular-Layout) + sl-history
   (Verlauf-Liste). Einfuegen: an sales-locations.css anhaengen bzw. gemeinsam
   ans Ende von style.css. */

.sl-edit-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 14px;
  align-items: start;
}
.sl-edit-grid .field--wide { grid-column: 1 / -1; }
.sl-edit-grid .modal-actions { grid-column: 1 / -1; }
.sl-edit-grid textarea { min-height: 90px; resize: vertical; }

/* Verlauf-Liste (Aenderungen) — wiederverwendet .info-card-Optik, aber als
   Stapel statt Grid (chronologische Liste ist besser lesbar einspaltig). */
.sl-history {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.sl-history .info-card { padding: 10px 12px; }

/* Touch-Floor fuer Edit-Formular (Memory project_tablet_touch_breakpoint) */
@media (max-width: 1024px), (pointer: coarse) {
  .sl-edit-grid input,
  .sl-edit-grid select,
  .sl-edit-grid .primary-btn,
  .sl-edit-grid .ghost-btn {
    min-height: 44px;
  }
}

/* Offertenrechner (Iter 21 E2) — so-* Namespace.
   Baut auf sl-*-Basis (Badges/KPIs/Tabellen) + bestehenden Klassen auf
   (.panel/.field/.view-toggle/.info-card). Eigene @media-Blöcke NACH den
   Basis-Regeln (Memory project_css_cascade_mobile), Touch-Floor über
   (max-width:1024px),(pointer:coarse) (Memory project_tablet_touch_breakpoint).
   Platzierung: VOR dem prefers-reduced-motion-Schlussblock. */

.so-toolbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  margin: 14px 0;
}
/* Die Steuerungs-Reihe INNERHALB der Leiste (Ansicht · Filter · Ordnung).
   Sie trug ihre Vorgaben bis zum 04.09.2026 als `style="…"` im Markup
   (views/sales-invoices.js) — und war damit fuer jedes Blatt unerreichbar:
   eine Inline-Vorgabe schlaegt auch die spaeteste Regel. Am Handy blieb die
   Leiste deshalb bei 224 px, obwohl «DIE EINE ZEILE» sie laengst auf eine
   Reihe gestellt haette (patch-handy-verkauf.css). Hier steht dasselbe
   Aussehen wie vorher, nur an einem Ort, den der Stil erreichen kann. */
/* SIE ROLLT, STATT UMZUBRECHEN — auf JEDER Breite, ohne Geraeteblock
   (04.09.2026). Gemessen: mit `flex-wrap: wrap` stapelte die Werkzeugleiste
   der Rechnungen am Telefon auf 224 px (drei Reihen) vor der ersten Rechnung.
   Es braucht dafuer keine zweite Fassung im Handy-Block: am Schreibtisch ist
   Platz genug, dort rollt nichts — dieselbe Regel, zwei Bilder. Und eine
   Wahrheit an EINEM Ort ist der Grund, warum `.so-toolbar__reihe` ueberhaupt
   entstanden ist (der Inline-Stil davor war fuer jedes Blatt unerreichbar).
   `flex: 0 0 auto` ist tragend: ohne sie schrumpfen die Griffe auf ihre
   Mindestbreite, statt zu rollen. */
.so-toolbar__reihe {
  display: flex; align-items: center; gap: 12px;
  flex-wrap: nowrap; overflow-x: auto;
  overscroll-behavior-x: contain; scrollbar-width: none;
}
.so-toolbar__reihe::-webkit-scrollbar { width: 0; height: 0; }
.so-toolbar__reihe > * { flex: 0 0 auto; }
/* Iter 27: Badge ohne Border (Foundation-Vokabular) */
.so-badge--gesendet {
  background: rgba(var(--info-rgb), 0.15);
  color: var(--info-strong);
  border: 0;
}

/* Dokument-View: der Editor deckelt sich selbst (Lesbarkeit der Formulare) —
   normales Block-Element, kein Grid-Item ⇒ margin:auto zentriert klassisch.
   Arbeitsflächen (Listen/Tabellen/Cockpit) bleiben full-width (DESIGN.md §7). */
.so-editor { max-width: 1560px; margin-inline: auto; }

.so-editor .so-head {
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  gap: 14px;
  flex-wrap: wrap;
}
.so-editor h1 { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
/* Zurück-Link: SVG-Chevron statt Unicode-Pfeil (Iter 27, Kill-Liste) */
.so-back {
  display: inline-flex; align-items: center; gap: 3px;
  color: var(--text-secondary); text-decoration: none;
  font-size: 12.5px; font-weight: 500; margin-bottom: 2px;
}
.so-back::before {
  content: ""; width: 13px; height: 13px; flex: none;
  background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%238a9ba3' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'><path d='m15 18-6-6 6-6'/></svg>") center / contain no-repeat;
}
.so-back:hover { color: var(--text-primary); }
.so-actions { display: flex; gap: 10px; flex-wrap: wrap; }
/* Iter 37 (F3): der «Senden»-Grund als sichtbarer Hinweis bricht auf eigene Zeile um. */
.so-actions .so-hint { flex-basis: 100%; margin: 2px 0 0; }
/* Iter 27: Danger-Ghost analog Foundation .ghost-btn--danger (kein Vollrot-Rahmen) */
.so-danger { color: var(--bad-strong); border-color: rgba(var(--bad-rgb), .3); }
.so-danger:hover { background: rgba(var(--bad-rgb), .10); border-color: var(--bad-strong); }
/* Iter 27: Status-Hinweis als ruhiger Well mit Info-Akzentbalken (inset, kein Rahmen) */
.so-frozen-hint {
  margin: 0 0 14px;
  padding: 10px 14px;
  background: var(--surface-inset);
  box-shadow: inset 2.5px 0 0 var(--info-muted);
  border: 0;
  border-radius: var(--radius-card);
  color: var(--text-secondary);
}

.so-panel h3 { margin: 0 0 12px; }

.so-fields {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 12px;
  align-items: start;
}
.so-fields .field--wide { grid-column: 1 / -1; }
.so-inline { display: flex; gap: 8px; align-items: center; }
.so-inline select { flex: 1; min-width: 0; }
.so-hint { color: var(--text-secondary); font-size: 12px; }
.so-toggle { flex-direction: row; align-items: center; justify-content: space-between; gap: 10px; }
.so-toggle input[type="checkbox"] { width: 20px; height: 20px; }
.so-newcustomer {
  margin-top: 14px;
  padding-top: 14px;
  border-top: 1px solid var(--border);
}
.so-newcustomer h4 { margin: 0 0 10px; }

.so-presets { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 12px; }
.so-preset { font-size: 13px; }

.so-loclist { margin-top: 12px; }
.so-loclist summary {
  cursor: pointer;
  color: var(--text-secondary);
  padding: 8px 0;
  list-style: none;
  display: flex; align-items: center; gap: 6px;
}
.so-loclist summary::-webkit-details-marker { display: none; }
/* Iter 27: EIN Chevron-Idiom (SVG + Rotation) für alle Aufklapper der Welle */
.so-loclist summary::before {
  content: ""; width: 14px; height: 14px; flex: none;
  background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%238a9ba3' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='m9 6 6 6-6 6'/></svg>") center / contain no-repeat;
  transition: transform var(--dur-fast) var(--ease);
}
.so-loclist[open] > summary::before { transform: rotate(90deg); }
.so-loclist__rows {
  max-height: 320px;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 2px;
  background: var(--surface-inset);   /* Iter 27: Well statt Rahmen */
  border: 0;
  border-radius: var(--radius-card);
  padding: 6px;
}
.so-locrow {
  display: flex;
  gap: 10px;
  align-items: center;
  padding: 6px 8px;
  border-radius: var(--radius-card);
  font-size: 13px;
}
.so-locrow:hover { background: rgba(var(--tint-rgb), 0.04); }
.so-locrow input[type="checkbox"] { width: 18px; height: 18px; flex-shrink: 0; }

/* §16 Individuelle Standort-Auswahl (Iter 34) */
.so2-individual { margin-top: 4px; display: flex; flex-direction: column; gap: 8px; }
.so2-indivsearch { max-width: 420px; margin-bottom: 4px; }
.so2-indivresults {
  max-height: 260px;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 2px;
  background: var(--surface-inset);
  border-radius: var(--radius-card);
  padding: 6px;
  overscroll-behavior: contain;
}
.so2-indivadd {
  display: flex;
  gap: 10px;
  align-items: center;
  padding: 7px 8px;
  border: 0;
  background: none;
  border-radius: var(--radius-card);
  font-size: 13px;
  color: var(--text-primary);
  text-align: left;
  cursor: pointer;
  width: 100%;
}
.so2-indivadd:hover { background: rgba(var(--tint-rgb), 0.06); }
.so2-indivadd__plus {
  flex-shrink: 0;
  width: 20px; height: 20px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: var(--radius-card);
  background: rgba(var(--tint-rgb), 0.14);
  color: var(--accent-hover);
  font-weight: 600; line-height: 1;
}
.so-loclist--chosen { margin-top: 12px; }
.so-loclist__head { font-size: 12.5px; color: var(--text-secondary); margin: 0 0 6px; }
.so-locrow--chosen { justify-content: space-between; }
.so-locrm {
  flex-shrink: 0;
  width: 26px; height: 26px;
  border: 0; border-radius: var(--radius-card);
  background: none; color: var(--text-tertiary);
  font-size: 18px; line-height: 1; cursor: pointer;
}
.so-locrm:hover { background: rgba(var(--bad-rgb), .14); color: var(--danger); }

.so-resultbar {
  display: flex;
  gap: 16px;
  align-items: center;
  flex-wrap: wrap;
  margin-bottom: 12px;
  color: var(--text-secondary);
}
.so-resultbar strong { color: var(--text-primary); }
.so-posmode { margin-left: auto; }

.so-postable .so-price-input { width: 110px; text-align: right; }
.so-freecell {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}
.so-freecell input[type="checkbox"] { width: 18px; height: 18px; }
.so-row--free td { opacity: 0.85; }
.so-strike { text-decoration: line-through; color: var(--text-secondary); }
.so-reset { margin-top: 10px; font-size: 13px; }

.so-sums { max-width: 420px; }
.so-sumrow {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  padding: 6px 0;
  border-bottom: 1px solid var(--border);
}
.so-sumrow--total {
  border-bottom: none;
  border-top: 1px solid var(--line-strong);   /* Iter 27: Hairline-strong statt 2px-Balken */
  margin-top: 4px;
  padding-top: 10px;
  font-size: 17px;
}
.so-sumrow--total strong { font-variant-numeric: tabular-nums lining-nums; }
.so-warnings { margin-top: 14px; }
.so-warnings h4 { margin: 0 0 8px; }
/* Iter 27: Warnungen als Alpha-Fläche + Strong-Text, ohne Border (Badge-Idiom) */
.so-warning { margin: 4px 0; padding: 8px 12px; border-radius: var(--radius-card); font-size: 13px; border: 0; }
.so-warning--warnung { background: rgba(var(--warn-rgb), 0.12); color: var(--warn-strong); }
.so-warning--kritisch { background: rgba(var(--bad-rgb), 0.12); color: var(--bad-strong); }

/* Kunden-View (Iter 21 E3): klickbare Offerten-Karten im Kunden-Modal.
   E7: Karten tragen direkte Aktionen (Angenommen / Rechnung erstellen /
   Dokument). */
.scu-offer { display: block; text-decoration: none; color: inherit; }
.scu-offer:hover { background: var(--surface-3); }   /* Iter 27: Hover-Fläche statt Accent-Vollborder */
.scu-offer-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 10px;
}
.scu-offer-actions .primary-btn,
.scu-offer-actions .ghost-btn { min-height: 44px; }

/* E7: Zeilen-Aktionen der Offerten-Liste + Rechnungs-Toolbar */
.si-toolbar-actions { display: flex; gap: 10px; flex-wrap: wrap; }

/* =========================================================================
   Iter 21 E5b — Offertenrechner-Neuaufbau (so2-*): geführte Schritte,
   Desktop-Breite (2 Spalten + sticky Ergebnis-Rail), Cluster-Chips,
   Screens-Stepper, gruppierte Positionsliste, Preis-Herleitung, Mobile-Bar.
   @media NACH den Basis-Regeln (Memory project_css_cascade_mobile).
   ========================================================================= */
.so2-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 360px;
  gap: 14px;
  align-items: start;
}
.so2-main { display: flex; flex-direction: column; gap: 14px; min-width: 0; }
.so2-rail { position: sticky; top: 14px; }
.so2-railcard { display: flex; flex-direction: column; gap: 12px; }
.so2-rail .so-sums { max-width: none; }
.so2-rail__meta { display: flex; gap: 12px; align-items: center; flex-wrap: wrap; color: var(--text-secondary); }
.so2-rail__meta strong { color: var(--text-primary); }
.so2-rail__ots h4 { margin: 0 0 6px; }
.so2-rail__ots p { margin: 2px 0; font-size: 13px; }
.so2-rail__ots p > span { color: var(--text-secondary); display: inline-block; min-width: 118px; }
/* Iter 22: interne Reichweiten-Kennzahlen (Kunden im Blickfeld · Modellierte
   Kontaktchancen · CPM_OTS · CPR_VAC) aus buildOfferView('internal').
   Iter 30 UI-Politur (Owner 2026-07-05): Stat-Rows statt 2×2-Card-Grid —
   DESIGN.md §4 «Stat-in-Rail»: in <400px-Spalten quetschten die Kacheln
   10.5px-Text unter den 11px-Schrift-Floor; Cyan war Deko auf Nicht-Interaktivem. */
.so-stats { margin: 6px 0 4px; }
.so-stat { padding: 8px 0 9px; display: flex; flex-direction: column; gap: 2px; }
.so-stat + .so-stat { border-top: 1px solid var(--border); }
.so-stat__row { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; }
.so-stat .l { font-size: 11px; letter-spacing: .04em; text-transform: uppercase; color: var(--text-tertiary); font-weight: 600; }
.so-stat .v { font-size: 17px; font-weight: 650; color: var(--text-primary); font-variant-numeric: tabular-nums lining-nums; white-space: nowrap; }
.so-stat small { font-size: 11px; color: var(--text-secondary); }
.so-stat .so-reach-basis { color: var(--text-secondary); }

.so2-step__head { display: flex; gap: 12px; align-items: flex-start; margin-bottom: 12px; }
/* Iter 27: Schritt-Nummer als Soft-Quadrat statt Kreis-mit-Border (Kill-Liste) */
.so2-step__nr {
  flex-shrink: 0;
  width: 26px; height: 26px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: var(--radius-button);
  border: 0;
  background: var(--accent-soft);
  color: var(--accent-strong);
  font-weight: 700; font-size: 13px;
  font-variant-numeric: tabular-nums;
}
.so2-step__head h3 { margin: 0; }
.so2-step__sub { margin: 2px 0 0; color: var(--text-secondary); font-size: 13px; }

/* Cluster-Chips (Region/Kanton/Ort — Mehrfachauswahl §9-E5b.3) */
.so2-cluster { display: flex; flex-direction: column; gap: 10px; margin-bottom: 12px; }
.so2-chipgroup__label { display: block; color: var(--text-secondary); font-size: 12px; margin-bottom: 6px; }
.so2-chips { display: flex; gap: 6px; flex-wrap: wrap; }
/* Iter 30 UI-Politur: 132px schnitt Reihe 4 hart mitten durch (wirkte kaputt,
   nicht scrollbar — Owner 2026-07-05). Höhe auf ~4 Reihen; .has-more (JS-Toggle
   der View) blendet unten aus, solange weitere Orte folgen (DESIGN.md §7
   Scroll-Affordance). */
.so2-chips--scroll { max-height: 168px; overflow-y: auto; padding: 2px; overscroll-behavior: contain; }
.so2-chips--scroll.has-more {
  -webkit-mask-image: linear-gradient(to bottom, #000 calc(100% - 28px), transparent);
  mask-image: linear-gradient(to bottom, #000 calc(100% - 28px), transparent);
}
.so2-chip {
  padding: 6px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius-badge);
  background: transparent;
  color: var(--text-secondary);
  font-size: 13px;
  cursor: pointer;
}
.so2-chip:hover { border-color: var(--line-strong); color: var(--text-primary); background: rgba(var(--tint-rgb), .04); }
/* Iter 27: Aktiv-Zustand wie Foundation .toggle-btn.active (Soft-Tint + Strong-Text) */
.so2-chip.is-on {
  border-color: var(--accent-line);
  background: var(--accent-soft);
  color: var(--accent-strong);
  font-weight: 600;
}
.so2-ortsearch { margin-bottom: 8px; max-width: 320px; }

/* Schritt-2-Filter: klarer Hinweis, dass die Selektoren FILTERN (welche
   Standorte), plus «Erweitert»-Deckel für die seltene Screen-Kappung. */
.so2-filterhint { margin: 2px 0 10px; }
.so2-advanced {
  margin-top: 4px;
  background: var(--surface-inset);   /* Iter 27: Well statt Rahmen */
  border: 0;
  border-radius: var(--radius-card);
  padding: 0 12px;
}
.so2-advanced > summary {
  cursor: pointer;
  padding: 10px 0;
  color: var(--text-secondary);
  list-style: none;
  min-height: 44px;
  display: flex;
  align-items: center;
}
.so2-advanced > summary::-webkit-details-marker { display: none; }
/* Iter 27: SVG-Chevron mit Rotations-Transition statt Unicode-Dreieck */
.so2-advanced > summary::before {
  content: ""; width: 14px; height: 14px; flex: none; margin-right: 6px;
  background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%238a9ba3' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='m9 6 6 6-6 6'/></svg>") center / contain no-repeat;
  transition: transform var(--dur-fast) var(--ease);
}
.so2-advanced[open] > summary::before { transform: rotate(90deg); }
.so2-advanced .field { padding: 0 0 12px; }

/* Laufzeit-Buttons: umbrechen statt Nachbarfeld überlappen (4+ Laufzeiten) */
.so-laufzeit { flex-wrap: wrap; }
.so-laufzeit .view-toggle__btn { flex: 0 0 auto; }

/* Iter 22 E3: Schritt 3 in benannte Sinneinheiten (Buchung / Rabatte & Spot /
   Kundenpreis) — vorher eine flache Feldwiese («entwirren», Owner-Mandat). */
.so3-group { margin-bottom: 14px; }
/* Iter 27: Mono-Uppercase-Kicker abgebaut (DESIGN.md §2) — ruhiger Gruppentitel */
.so3-group__title {
  margin: 0 0 8px; font-size: 12.5px; font-weight: 600; letter-spacing: 0;
  text-transform: none; color: var(--text-secondary); font-family: inherit;
}
/* Rabatt-Schalter als Karten statt verlorener Mini-Checkboxen: ganze Fläche
   tappbar, checked-Zustand deutlich (Cyan-Soft). */
.so3-group .so-toggle {
  border: 1px solid var(--border); border-radius: var(--radius-card); padding: 10px 12px;
  background: var(--surface-inset); cursor: pointer; min-height: 46px;
  transition: background var(--transition), border-color var(--transition);
}
.so3-group .so-toggle:hover { background: var(--surface-hover); }
.so3-group .so-toggle:has(input:checked) {
  background: rgba(var(--accent-rgb),.12); border-color: var(--accent-line);
}
.so3-group .so-toggle:has(input:checked) span { color: var(--accent-strong); }
/* Iter 27: Toggle-Karten-Label ist eine Option, kein Micro-Label — lesbar
   statt uppercase-10.5px (das .field span-Idiom bleibt für echte Feldlabel). */
.so3-group .so-toggle > span {
  text-transform: none; letter-spacing: 0;
  font-size: 13px; font-weight: 500; color: var(--text);
}
/* Slots-Stepper: −/+ plus direktes Feld; die Formel-Zeile darunter macht die
   degressive Preislogik sichtbar (1. Slot voll, jeder weitere ×Faktor). */
.so3-slots { align-self: flex-start; background: var(--surface-2); }
.so3-slots input[type=number] {
  width: 56px; border: 0; background: transparent; text-align: center;
  font-weight: 700; font-size: 16px; color: var(--text-primary);
  font-variant-numeric: tabular-nums; -moz-appearance: textfield; appearance: textfield;
  min-height: 34px;
}
.so3-slots input::-webkit-outer-spin-button, .so3-slots input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.so3-slots button { min-width: 44px; min-height: 44px; }

/* Preis-Freiheit (§9-E5b.5) — Iter 27: erhabene neutrale Fläche mit
   Cyan-Hairline-Akzent (inset) statt gestricheltem Cyan-Rahmen (DESIGN.md §3). */
.so2-freedom {
  margin-top: 14px;
  padding: 12px 14px;
  background: var(--surface-2);
  border: 0;
  border-radius: var(--radius-card);
  box-shadow: inset 2.5px 0 0 var(--accent-line);
}
.so2-freedom h4 { margin: 0 0 6px; font-size: 13px; font-weight: 600; }
.so2-freedom__ovr { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; min-height: 34px; }
.so2-freedom__ovr .so-reset { margin-top: 0; }

/* Freie Positionen (Iter 22 Preis-Freiheit): Zeile = Text · CHF · Rhythmus ·
   Total · Entfernen. Negativ (Abzug/Gegenleistung) mit warn-Akzentkante. */
.so2-customs {
  margin-top: 14px;
  padding: 12px 14px;
  background: var(--surface-2);
  border: 0;
  border-radius: var(--radius-card);
  box-shadow: inset 2.5px 0 0 var(--accent-line);
}
.so2-customs h4 { margin: 0 0 8px; font-size: 13px; font-weight: 600; }
.so2-custom {
  display: grid;
  grid-template-columns: minmax(180px, 1fr) 120px auto auto auto;
  gap: 8px;
  align-items: center;
  padding: 6px 0;
}
.so2-custom input, .so2-custom select { min-height: 44px; }
.so2-custom--neg { box-shadow: inset 2.5px 0 0 var(--warn); padding-left: 8px; border-radius: var(--radius-card); }   /* Iter 27: inset statt border-left */
.so2-custom__total { white-space: nowrap; font-variant-numeric: tabular-nums; }
.so2-custom__del { min-width: 44px; min-height: 44px; }
.so2-customs__add { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 8px; }
@media (max-width: 720px) {
  .so2-custom { grid-template-columns: 1fr auto auto; }
  .so2-custom [data-cfield="text"] { grid-column: 1 / -1; }
  .so2-custom__total { grid-column: 1; }
}

/* Positionsliste: Gruppen (Ort/Aggregat) + Zeilen + Herleitung.
   Iter 27: Wells ohne Rahmen (Hairlines nur IN der Liste, DESIGN.md §1). */
.so2-poslist { display: flex; flex-direction: column; gap: 8px; }
.so2-group {
  border: 0;
  border-radius: var(--radius-card);
  background: var(--surface-inset);
}
.so2-group > summary {
  display: flex; justify-content: space-between; align-items: center; gap: 12px;
  padding: 10px 14px; cursor: pointer; min-height: 44px; list-style: none;
  flex-wrap: wrap;
}
.so2-group > summary::-webkit-details-marker { display: none; }
.so2-group > summary::before {
  content: ""; width: 14px; height: 14px; flex: none; margin-right: 2px;
  background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%238a9ba3' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='m9 6 6 6-6 6'/></svg>") center / contain no-repeat;
  transition: transform var(--dur-fast) var(--ease);
}
.so2-group[open] > summary::before { transform: rotate(90deg); }
.so2-group__name { font-weight: 600; }
.so2-group__agg { color: var(--text-secondary); font-size: 13px; font-variant-numeric: tabular-nums; }
.so2-group__agg b { color: var(--text-primary); }
.so2-group__rows { border-top: 1px solid var(--border); padding: 6px 8px; display: flex; flex-direction: column; gap: 4px; }

.so2-pos { border-radius: var(--radius-card); }
.so2-poslist > .so2-pos { border: 0; background: var(--surface-inset); padding: 4px 8px; }
.so2-pos--free { opacity: 0.8; }
.so2-pos__row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto auto auto;
  gap: 10px;
  align-items: center;
  padding: 6px 6px;
  min-height: 44px;
}
.so2-pos__row:hover { background: rgba(var(--tint-rgb), 0.03); }
.so2-pos__main { min-width: 0; font-size: 13px; }
.so2-pos__main strong { font-weight: 600; }
.so2-pos__screens { color: var(--text-secondary); font-size: 13px; white-space: nowrap; }
.so2-pos__price { display: flex; gap: 8px; align-items: baseline; justify-content: flex-end; white-space: nowrap; font-size: 13px; }
.so2-pos__price small { color: var(--text-secondary); }
.so2-pos__price small b { color: var(--text-primary); font-variant-numeric: tabular-nums; }
.so2-price-fix { font-variant-numeric: tabular-nums; }
.so-freecell span { font-size: 12px; color: var(--text-secondary); margin-left: 4px; }

.so2-why {
  border: none; background: none; cursor: pointer;
  color: var(--text-secondary); font-size: 12px;
  text-decoration: underline dotted;
  padding: 6px;
}
.so2-why:hover, .so2-why.is-on { color: var(--accent); }

.so2-pos__calc { padding: 4px 8px 10px; }
/* Iter 27: Herleitung mit inset Accent-Balken statt border-left (Kill-Liste) */
.so2-calc {
  color: var(--text-secondary);
  font-size: 12.5px;
  line-height: 1.7;
  padding: 6px 10px;
  border-left: 0;
  box-shadow: inset 2.5px 0 0 var(--accent-line);
  border-radius: var(--radius-card);
  margin: 4px 0;
}
.so2-calc b { color: var(--text-primary); }
.so2-calc__sep { opacity: 0.5; }
.so2-calc--ovr { box-shadow: inset 2.5px 0 0 var(--warn); }
.so2-sub {
  display: flex; gap: 12px; align-items: center; justify-content: space-between;
  padding: 6px 10px; margin-top: 6px;
  border-top: 1px solid var(--border);
  font-size: 13px;
}
.so2-sub__name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.so2-sub__price { color: var(--text-secondary); font-variant-numeric: tabular-nums; white-space: nowrap; }

/* Screens-Stepper (§9-E5b.2) */
.so2-stepper {
  display: inline-flex; align-items: center; gap: 2px;
  border: 1px solid var(--border); border-radius: var(--radius-card);
  overflow: hidden;
}
.so2-stepper button {
  width: 34px; height: 34px;
  border: none; background: transparent; color: var(--text-primary);
  font-size: 16px; cursor: pointer;
}
.so2-stepper button:hover:not(:disabled) { background: rgba(var(--accent-rgb), 0.18); }
.so2-stepper button:disabled { opacity: 0.35; cursor: default; }
.so2-stepper span {
  min-width: 42px; text-align: center; font-variant-numeric: tabular-nums; font-size: 13px;
}
.so2-stepper span small { color: var(--text-secondary); }
.so2-stepper.is-override { border-color: var(--accent); }
.so2-stepper.is-override span { color: var(--accent); font-weight: 600; }

/* Mobile-Ergebnisleiste: Total/OTS immer sichtbar (§9-E5b.1) */
.so2-mobilebar {
  display: none;
  position: fixed;
  left: 0; right: 0;
  /* Nicht der Fensterboden, sondern der SICHTBARE Boden: mit offener Tastatur
     steht das Layout-Fenster still, das sichtbare schrumpft — die Leiste klebte
     danach hinter der Tastatur bzw. auf halber Höhe (c3 B10, c2 B18). */
  bottom: var(--vv-unten, 0px);
  z-index: 40;
  padding: 10px 14px calc(10px + var(--sab));   /* Iter 26: var statt env */
  background: var(--topbar-bg);   /* Iter 27: Token statt Roh-Farbe, themetreu */
  border-top: 1px solid var(--border);
  backdrop-filter: blur(14px);
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}
.so2-mobilebar__sums { display: flex; flex-direction: column; min-width: 0; }
.so2-mobilebar__sums strong { font-size: 17px; font-variant-numeric: tabular-nums; }
.so2-mobilebar__sums span { color: var(--text-secondary); font-size: 12px; }
/* computeError leert die Bar (set('')) — eine leere fixe Leiste darf nie über
   dem Seitenende schweben (Review-Finding E5b). :empty schlägt die
   display:flex-Media-Regel per Spezifität. */
.so2-mobilebar:empty { display: none; }

/* ===== Iter 24: Mobile-Offerten-Wizard (Fokus-Schritte, Owner-UX) ===== */
/* Wizard-Chrome nur ≤1100px sichtbar; Editor blendet global das «+ Neu»-FAB
   aus (kollidiert mit der Ergebnis-Bar, man ist mitten im Erstellen). */
.so-wiz, .so-sheet-backdrop { display: none; }
/* 05.09.2026: `.qc` -> `.qc__fab`. Was hier abtritt, ist der SCHWEBENDE KNOPF
   (er lag auf der Ergebnis-Bar) — nicht das Menue. Seit «Neu» am Telefon in
   der Leiste am Daumen steht, wohnt in `.qc` auch die Schnellwahl dieses
   Ziels; haette die Huelle hier weiter `display: none`, waere das Ziel im
   Offerten-Editor ein Griff, der nichts tut. Sichtbar aendert sich nichts:
   ein schwebender Knopf steht hier so wenig wie vorher. */
body.so-editor-open .qc__fab { display: none; }
/* Wer den Knopf ausblendet, gibt seinen Platz auch frei — sonst hielte die
   Fläche 64px für etwas frei, das nicht da ist (Boden-Geometrie). */
body.so-editor-open.has-quick-create { --fab-h: 0px; }
/* Summe ist jetzt ein antippbarer Button (öffnet das Ergebnis-Sheet). */
.so2-mobilebar__sums {
  border: 0; background: transparent; padding: 0; margin: 0;
  text-align: left; font: inherit; color: inherit; cursor: pointer;
}
.so2-mobilebar__sums span { color: var(--accent-strong); }

/* Preisregel-Editor (#/v/pricing, admin-only §9-E5b.6) */
.sp-page .panel { margin-bottom: 14px; }
.sp-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
  gap: 14px;
  align-items: start;
}
.sp-grid .panel { margin-bottom: 0; }
.sp-matrix td { vertical-align: top; }
/* Welle 4.18: die erste Spalte (Zeilen-Beschriftung) bleibt beim horizontalen
   Scrollen stehen — sonst weiss auf schmalen Schirmen niemand mehr, welcher
   Preis zu welcher Zeile gehoert. Eigener Grund, damit nichts durchscheint. */
.sp-matrix th:first-child, .sp-matrix td:first-child {
  position: sticky; left: 0; z-index: 1;
  background: var(--surface);
}
.sp-matrix .sp-price { width: 110px; text-align: right; }
.sp-eb { display: block; color: var(--text-secondary); font-size: 11.5px; margin-top: 2px; font-variant-numeric: tabular-nums; }
.sp-aktiv { display: flex; gap: 6px; align-items: center; font-size: 11.5px; color: var(--text-secondary); margin-top: 4px; cursor: pointer; }
.sp-aktiv input[type="checkbox"] { width: 16px; height: 16px; flex: none; }
.sp-cell--off { opacity: 0.45; }
.sp-laufzeiten { display: flex; flex-direction: column; gap: 6px; margin-bottom: 10px; }
.sp-lz { display: flex; gap: 10px; align-items: center; }
.sp-lz > span:first-child { min-width: 90px; }
.sp-lz input { width: 110px; }
.sp-lz-del { padding: 4px 10px; }
.sp-lz-add { flex-wrap: wrap; }
.sp-lz-add input { max-width: 150px; min-width: 0; flex: 1 1 120px; }
/* Dunkle Feld-Optik für Inputs AUSSERHALB von label.field (Matrix, Laufzeiten,
   Ortsuche, Zeilen-Preis): die globale Regel deckt nur select/.search-input/
   textarea — diese Felder waren weiss-auf-weiss unlesbar (Review-Finding
   E5b, hoch). */
.sp-matrix .sp-price, .sp-lz input, .sp-lz-add input, .so2-ortsearch, .so-price-input {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  padding: 6px 10px;
  color: var(--text);
}
.sp-matrix .sp-price:focus, .sp-lz input:focus, .sp-lz-add input:focus,
.so2-ortsearch:focus, .so-price-input:focus { border-color: var(--accent-hover); outline: none; }
@media (max-width: 1024px), (pointer: coarse) {
  .sp-matrix .sp-price, .sp-lz input, .sp-lz-add input, .sp-lz-add .ghost-btn { min-height: 44px; }
  /* E6-Mobile-Pass 2026-07-02: 32px unterschritt das 44px-Mandat — gemessen
     25 Checkbox-Labels 16px, Laufzeit-Löschknopf 32px, EB-Default-Toggle. */
  .sp-aktiv { min-height: 44px; }
  .sp-lz-del { min-height: 44px; min-width: 44px; }
  .so-toggle { min-height: 44px; }
}

/* Desktop schmal / Tablet: Rail unter den Inhalt — einspaltig steht das
   Ergebnis unter Schritt 4, also übernimmt die Bottom-Bar «Total immer
   sichtbar» (§9-E5b.1) auch im Tablet-Band 721–1100px (Review-Finding E5b). */
@media (max-width: 1100px) {
  .so2-layout { grid-template-columns: 1fr; }
  .so2-rail { position: static; }
  .so2-mobilebar { display: flex; }
  /* Die Leiste MELDET ihre Höhe — 65px gemessen (Playwright, 390px). Die
     Schale hält sie über `--boden-abstand` frei. Bis 09.08. stand hier eine
     geratene 84 für real 68 (Daumenleiste) + 65 (diese Leiste) + sichere
     Zone — darum lag die letzte Zeile jeder Liste unter der Leiste, und der
     Knopf «Entwurf zurücksetzen» stand nur zur Hälfte da (c1 B13, c2 B5). */
  body:has(.so2-mobilebar:not(:empty)) { --leiste-h: 65px; }

  /* --- Wizard-Leiste: [‹] Punkte + Titel [›], sticky oben --- */
  .so-editor.is-wizard .so-wiz {
    display: flex; align-items: center; gap: 8px;
    /* Unter der klebenden Kopfzeile, nicht darunter VERSCHWINDEND: `--kopf-h`
       ist am Rechner 0, am Handy die gemessene Kopfhöhe (Boden-Geometrie). */
    position: sticky; top: var(--kopf-h, 0px); z-index: 25;
    margin: 0 0 12px; padding: 8px 2px;
    background: var(--bg); border-bottom: 1px solid var(--border);
  }
  /* Iter 27: Quadrat-Icon-Buttons statt Kreis-mit-Border (Kill-Liste) */
  .so-wiz__arrow {
    flex: 0 0 auto; width: 44px; height: 44px; border-radius: var(--radius-button);
    border: 1px solid var(--border); background: var(--surface-2);
    color: var(--text); font-size: 20px; line-height: 1; display: grid; place-items: center;
  }
  .so-wiz__arrow:active:not(:disabled) { transform: scale(.94); }
  .so-wiz__arrow:disabled { opacity: .3; }
  .so-wiz__center { flex: 1; min-width: 0; display: flex; flex-direction: column; align-items: center; gap: 5px; }
  .so-wiz__dots { display: flex; align-items: center; gap: 6px; }
  .so-wiz__dot {
    width: 26px; height: 26px; border-radius: var(--radius-card); padding: 0;
    border: 0; background: var(--surface-inset);
    color: var(--text-tertiary); font-weight: 600; font-size: 12px;
    display: grid; place-items: center; font-variant-numeric: tabular-nums;
    transition: background var(--transition), color var(--transition);
  }
  .so-wiz__dot.is-done { color: var(--accent-strong); background: var(--accent-soft); }
  .so-wiz__dot.is-active { color: var(--on-accent); background: var(--accent); }
  .so-wiz__title { font-size: 13px; font-weight: 600; color: var(--text-secondary); }

  /* --- Nur der aktive Schritt sichtbar --- */
  .so-editor.is-wizard .so2-step:not(.is-current) { display: none; }
  .so-editor.is-wizard .so2-main { gap: 0; }

  /* --- Swipe: aktiver Schritt folgt dem Finger, snapt/wechselt mit Slide --- */
  .so-editor.is-wizard .so2-layout { overflow-x: hidden; }
  .so-editor.is-wizard .so2-step.is-current { transition: transform .22s cubic-bezier(.2, .8, .2, 1); }
  .so-editor.is-wizard .so2-layout.so-dragging .so2-step.is-current { transition: none; }  /* Finger-folgt ohne Lag */
  .so-editor.is-wizard .so2-step.so-slide-fwd { animation: soSlideFwd .26s cubic-bezier(.2, .8, .2, 1); }
  .so-editor.is-wizard .so2-step.so-slide-bwd { animation: soSlideBwd .26s cubic-bezier(.2, .8, .2, 1); }

  /* --- Ergebnis-Rail als Bottom-Sheet (per «Details») --- */
  .so-editor.is-wizard .so2-rail {
    position: fixed; left: 0; right: 0; bottom: 0; top: auto; z-index: 60;
    max-height: 82vh; overflow-y: auto;
    padding: 8px 14px calc(16px + env(safe-area-inset-bottom, 0px));
    background: var(--surface); border-top: 1px solid var(--line-strong);
    border-radius: var(--radius-card) var(--radius-card) 0 0; box-shadow: var(--shadow-md);
    transform: translateY(101%); transition: transform .3s cubic-bezier(.2,.8,.2,1);
    pointer-events: none;   /* versteckt: fängt keine Klicks ab (sonst blockiert es die Bar) */
  }
  .so-editor.is-wizard .so2-rail::before {
    content: ''; display: block; width: 40px; height: 4px; border-radius: 2px;
    background: var(--line-strong); margin: 2px auto 12px;
  }
  .so-editor.is-wizard .so2-rail.is-open { transform: translateY(0); pointer-events: auto; }
  .so-sheet-backdrop {
    display: block; position: fixed; inset: 0; z-index: 55;
    background: rgba(0, 0, 0, .5); backdrop-filter: blur(2px);
  }
  .so-sheet-backdrop[hidden] { display: none; }

  /* --- doppelter Speichern: Header-Save weg (Save lebt in der Mobile-Bar) --- */
  .so-editor.is-wizard .so-actions #so-save { display: none; }
}
@keyframes soSlideFwd { from { transform: translateX(34px); opacity: .35; } to { transform: none; opacity: 1; } }
@keyframes soSlideBwd { from { transform: translateX(-34px); opacity: .35; } to { transform: none; opacity: 1; } }
@media (max-width: 1100px) and (prefers-reduced-motion: reduce) {
  .so-editor.is-wizard .so2-rail { transition: none; }
  .so-editor.is-wizard .so2-step.is-current { transition: none; }
  .so-editor.is-wizard .so2-step.so-slide-fwd,
  .so-editor.is-wizard .so2-step.so-slide-bwd { animation: none; }
}
/* Mobile: Positions-Grid stapelt */
@media (max-width: 720px) {
  /* 4 Ebenen-Buttons (Standort/Ort/Kanton/Region) passen nicht in eine
     375px-Zeile — umbrechen statt «Region» abschneiden */
  .so-posmode { flex-wrap: wrap; }
  .so-posmode .view-toggle__btn { flex: 1 1 auto; }
  .so2-pos__row {
    grid-template-columns: minmax(0, 1fr) auto;
    grid-auto-flow: row;
    row-gap: 6px;
  }
  .so2-pos__price { justify-content: flex-start; grid-column: 1 / -1; flex-wrap: wrap; }
  .so2-group > summary { align-items: flex-start; flex-direction: column; gap: 4px; }
  .so2-sub { flex-wrap: wrap; }
}
/* Touch-Floor (Tablet-Bruchzone 768/1024 + coarse pointer). E6-Mobile-Pass:
   44px gilt für BEIDE Dimensionen — 2-Buchstaben-Kantons-Chips rissen die
   Breite (42px), der Back-Link die Höhe (15px), die Standortlisten-summary 40px. */
@media (max-width: 1024px), (pointer: coarse) {
  .so2-chip { min-height: 44px; min-width: 44px; }
  .so2-stepper button { width: 44px; height: 44px; }
  .so2-why { min-height: 44px; }
  .so2-ortsearch { min-height: 44px; }
  .so-back { display: inline-flex; align-items: center; min-height: 44px; }
  .so-loclist summary { min-height: 44px; padding: 12px 0; }
}

/* Mobile ≤720px: einspaltig, Aktionen volle Breite (PWA-Kernnutzung §Owner) */
@media (max-width: 720px) {
  .so-actions { width: 100%; }
  .so-actions .primary-btn, .so-actions .ghost-btn { flex: 1; }
  .so-posmode { margin-left: 0; width: 100%; }
  .so-sums { max-width: none; }
  .so-toolbar .primary-btn { width: 100%; text-align: center; }
}

/* Touch-Floor (Tablet-Bruchzone 768/1024 + coarse pointer) */
@media (max-width: 1024px), (pointer: coarse) {
  /* E6: :not([type="checkbox"]) — der nackte input-Floor streckte die
     Early-Bird-/Partner-Checkboxen (20×20-Basis) auf verzerrte 20×44px;
     deren Tap-Fläche ist das umgebende .so-toggle-Label (min-height 44). */
  .so-fields input:not([type="checkbox"]),
  .so-fields select,
  .so-preset,
  .so-price-input,
  .so-actions .primary-btn,
  .so-actions .ghost-btn {
    min-height: 44px;
  }
  .so-locrow { min-height: 44px; }
  .so-freecell { min-height: 44px; min-width: 44px; }
  /* §16: individuelle Auswahl touch-tauglich */
  .so2-indivadd { min-height: 44px; }
  .so-locrm { min-height: 44px; min-width: 44px; }
  .so2-indivsearch { min-height: 44px; }
}

/* =========================================================================
   Iter 21 Etappe 5 — P&L (/v/pnl, admin-only): Marge-Farben, Break-even-Grid,
   Drilldown-Blöcke (details/summary), Ausgaben-Modal-Checkbox.
   ========================================================================= */
.pnl-neg { color: var(--low); }
.pnl-pos { color: var(--high); }
.pnl-warn { color: var(--medium); }
.pnl-table td[data-label="Marge"] { font-variant-numeric: tabular-nums lining-nums; }
.pnl-breakeven { display: grid; grid-template-columns: minmax(180px, 260px) 1fr 1fr; gap: 14px; align-items: stretch; margin-top: 12px; }
.pnl-breakeven .field input { min-height: 46px; background: var(--surface-inset); border: 1px solid var(--border); border-radius: var(--radius-card); padding: 0 14px; color: var(--text); }
.pnl-block,
.lx-belege__monat { border: 0; border-radius: var(--radius-card); background: var(--surface-inset); }   /* Iter 27: Well ohne Rahmen */
.pnl-block summary,
.lx-belege__monat summary {
  display: flex; justify-content: space-between; align-items: center; gap: 12px;
  padding: 12px 14px; cursor: pointer; min-height: 44px; list-style: none;
}
.pnl-block summary::-webkit-details-marker,
.lx-belege__monat summary::-webkit-details-marker { display: none; }
.pnl-block summary span,
.lx-belege__monat summary .panel-row__val { color: var(--text-secondary); font-variant-numeric: tabular-nums; white-space: nowrap; }
.pnl-block[open] summary,
.lx-belege__monat[open] summary { border-bottom: 1px solid var(--border); }
.pnl-block > :not(summary),
.lx-belege__monat > :not(summary) { margin: 12px 14px; }
.field--check { flex-direction: row; align-items: center; gap: 10px; min-height: 46px; }
.field--check input[type="checkbox"] { width: 22px; height: 22px; accent-color: var(--accent); }
.so-toolbar__actions { display: flex; gap: 10px; flex-wrap: wrap; }
@media (max-width: 720px) {
  .pnl-breakeven { grid-template-columns: 1fr; }
}

/* =========================================================================
   Iter 21 E6 — Touch-Floor-Politur (holistischer Mobile-Pass 2026-07-02).
   Wurzel: bisherige Floors sicherten nur die Höhe; textschmale Elemente
   rissen die Breite der 44px-Tap-Fläche (P&L-Jahrespfeile ‹› 39px breit,
   Dashboard-Segment «7 T» 41px). Muster project_tablet_touch_breakpoint.
   ========================================================================= */
@media (max-width: 1024px), (pointer: coarse) {
  .view-toggle__btn { min-width: 44px; justify-content: center; }
  .seg__btn { min-width: 44px; }
}
/* E6-Politur (alle Breiten): (a) .view-toggle bringt margin-bottom:12px aus
   der Basis mit und sass in der flex-zentrierten .so-toolbar ~6px höher als
   der Aktions-Button daneben; (b) unbrechbare Strings (E-Mail/UID/IBAN) in
   Modal-Cards + gestapelten sl-Tabellen sollen umbrechen statt überlaufen —
   gleiche Fehlerklasse wie objection-* (dort seit Iter 19 gefixt). */
.so-toolbar .view-toggle { margin-bottom: 0; }
.info-card p { overflow-wrap: anywhere; }
/* `break-word` statt `anywhere`: beide brechen einen unbrechbaren String
   (E-Mail/UID/IBAN), aber `anywhere` zieht die Spalte zusätzlich auf ihre
   Buchstabenbreite zusammen — «Swisscom (Schweiz) AG» stand darum als
   «Swissco / m (Schweiz / ) AG» in der Offertenliste. Gebrochen wird jetzt
   erst, wenn das Wort allein nicht passt. */
.sl-table td { overflow-wrap: break-word; }
/* anywhere vererbt in UI-Elemente der Zellen: das «aktiv»-Label der Preis-
   matrix brach buchstabenweise und schrumpfte Label+Checkbox (gemessen 13px
   bei 360/390) — Daten dürfen brechen, UI-Beschriftungen nicht. */
.sl-table td .sp-aktiv { overflow-wrap: normal; }

/* =========================================================================
   Iter 17 Etappe 1 — prefers-reduced-motion (Accessibility-Hardening).
   Respektiert OS/Browser-Einstellung "Bewegung reduzieren" (vestibulaere
   Empfindlichkeit, Konzentrations-Stoerung). Wirkt global auf Hover-Translates
   (firm-card, kanban-card), Modal-Fade, Toast-Out-Fade, Skeleton-Pulse (E2),
   Scroll-Snap. Kein Layout-Eingriff — die Animation laeuft nur kuerzer.
   Block bewusst am Ende, damit er ueber spaeter deklarierten Selektor-spezifischen
   transition-Regeln gewinnt (CSS-Cascade-Order + !important).
   ========================================================================= */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* ============================================================
   Iter 22 F5 — globales «+ Neu» (FAB + Menü, quick-create.js)
   Fixed unten rechts, z-index 90: unter Modals (100) und Toast
   (200), über Inhalt. Touch ≥44px, iOS safe-area.
   ============================================================ */
/* Der Knopf STEHT auf dem Boden, er schwebt nicht irgendwo: 12px Luft über
   allem, was unten fix liegt (Daumenleiste, flächeneigene Leiste, sichere
   Zone) — und über der Tastatur, wenn sie offen ist. Seine eigene Höhe meldet
   er als `--fab-h` weiter unten; erst beides zusammen macht, dass die letzte
   Inhaltszeile über ihm frei ausläuft statt unter ihm zu verschwinden. */
.qc {
  position: fixed; right: 18px; z-index: 90;
  bottom: calc(var(--boden-h) + var(--leiste-h) + var(--vv-unten, 0px) + 12px);
}
.qc__fab {
  width: 56px; height: 56px; border-radius: 50%; border: 0; cursor: pointer;
  background: var(--accent); color: var(--on-accent);
  display: grid; place-items: center;
  box-shadow: 0 10px 28px rgba(2, 6, 8, .5), 0 2px 8px rgba(2, 6, 8, .4);
  transition: background .15s, transform .15s;
}
.qc__fab:hover { background: var(--accent-hover); }
.qc__fab:active { transform: scale(.94); }
.qc__fab svg { width: 26px; height: 26px; transition: transform .18s; }
.qc.open .qc__fab svg { transform: rotate(45deg); }
.qc__menu {
  position: absolute; right: 0; bottom: 68px; min-width: 216px;
  background: var(--surface-2); border: 1px solid var(--border);
  border-radius: var(--radius-card); box-shadow: var(--shadow-md); padding: 6px;
  display: flex; flex-direction: column; gap: 2px;
}
.qc__item {
  display: flex; align-items: center; gap: 10px; width: 100%; min-height: 44px;
  padding: 11px 14px; background: none; border: 0; border-radius: var(--radius-card);
  color: var(--text); font-size: 14px; font-weight: 500; text-align: left;
  cursor: pointer; white-space: nowrap;
}
.qc__item:hover, .qc__item:focus-visible { background: var(--surface-3); }
.qc__item-icon { display: inline-flex; flex: none; }
.qc__item-icon svg { width: 18px; height: 18px; color: var(--accent); }
/* Der Toast weicht dem Knopf aus — beide sitzen fix unten rechts. Er liest
   dafür `--boden-abstand` (Regel bei `.toast-stack`); die frühere feste 88
   galt auch am Rechner, wo es den Knopf gar nicht gibt. */
/* Offenes Menü gewinnt gegen einen noch aktiven Toast (der liegt sonst mit
   z-index 200 genau auf dem untersten Menü-Item — belegt F5-mobil-menu.png) */
.qc.open { z-index: 210; }
/* Die Reserve für die letzte Inhaltszeile trägt jetzt ALLEIN die Schale
   (`.main-shell { padding-bottom: calc(32px + var(--boden-abstand)) }`).
   Vorher hielten #app-view und .main-shell sie doppelt und in drei
   verschiedenen Grössen frei — am Rechner 84px Leere für einen Knopf, den
   die Kaskade dort ausblendet. */

/* ---- Der «+» weicht beim Lesen zurück (W5.6, Klasse 6 · P1) --------------
   OWNER-BEFUND aus dem Video-Audit vom 09.08.: der schwebende Knopf liegt
   beim Scrollen mitten im Inhalt — auf «Erledigt», auf einem Formularfeld.
   Die Boden-Geometrie darüber hält ihn von der LETZTEN Zeile fern; sie kann
   nichts dagegen tun, dass beim Blättern jede Zeile einmal an ihm vorbeikommt.

   Also das Standardverhalten schwebender Knöpfe: nach unten lesen ⇒ er tritt
   zurück, nach oben oder Stillstand ⇒ er ist wieder da. Die Richtung misst
   `utils/viewport.js` und schreibt sie als `lx-abwaerts` an den Körper.

   ZWEI DINGE BEWUSST NICHT:
   · KEIN transform. Der Wächter `scripts/_boden_geometrie_test.mjs` misst die
     Kanten dieses Knopfes gegen Inhalt, Daumenleiste und Toast; ein
     Verschieben oder Skalieren würde genau diese Messung verfälschen, ohne
     dass sich die Geometrie wirklich änderte. Überblenden reicht — dezent ist
     hier auch das Richtige.
   · KEIN Zurücktreten bei offenem Menü (`.qc.open`). Wer gerade wählt,
     scrollt nicht, und die Auswahl darf ihm nicht unter der Hand wegblenden.

   `visibility` schaltet erst am ENDE der Überblendung (Verzögerung in der
   Regel unten) und beim Zurückkommen sofort — sonst erschiene der Knopf hart
   und verschwände hart. `pointer-events: none` macht ihn wirklich klickfrei,
   nicht nur unsichtbar. */
.qc__fab {
  transition: background .15s, transform .15s, opacity .18s ease, visibility 0s;
}
/* ⛔ HIER STAND EIN ZWEITER RÜCKZUG — «der Knopf weicht auch dem GRIFF»
   (`lx-plus-verdeckt`, gebaut und wieder entfernt am 30.08.2026). Er ist
   VERWORFEN, und zwar an der Referenz. Wer die Verdeckung erneut so lösen
   will, liest zuerst das hier:
     BEFUND, der ihn auslöste (echt, bleibt echt): Auf 37 Flächen-Breiten-
     Paaren (390 · 430 · 768 px) lag im Ruhezustand ein Bedienelement unter
     dem Knopf — «+ Termin», «Alle», «Leads hochladen», ein Suchfeld.
     WARUM DER RÜCKZUG TROTZDEM FALSCH WAR — DESIGN.md:139 im Wortlaut:
     «Mobile/Touch: verfeinerte Floating-Aktion BLEIBT (Daumen-Ergonomie,
     52px Quadrat R15) — Listen erhalten Inhalts-Reserve unten, nichts wird
     verdeckt.» Die Antwort der Referenz auf Verdeckung ist die INHALTS-
     RESERVE, nicht ein verschwindender Knopf. Gemessen kostete der Rückzug
     genau das, was der Satz schützt: auf 37 von 120 Flächen-Breiten-Paaren
     fehlte der Knopf im Ruhezustand, auf der Startseite war er noch an
     1 von 24 Rollstellungen sichtbar, und ein normales Aufwärtswischen
     schaltete ihn 3× um (Flackern). Ein Knopf, der bei Bedarf nicht da ist,
     ist kein Daumen-Griff mehr.
     WAS STATTDESSEN GILT: Verdeckung wird nicht mehr als «berührt» gemessen,
     sondern als «UNTIPPBAR» — freie Tippfläche unter 44 × 44 px UND auch am
     Ende der Inhalts-Reserve nicht frei werdend. Der Wächter dafür steht in
     scripts/lib/breiten-mass.mjs (`plusDeckung`). Ein Griff, der nach einem
     Rollstoss frei ist, ist kein Defekt — das ist die Reserve bei der Arbeit.
   Was aus jener Runde BLEIBT, steht direkt unter dieser Regel: die Hülle
   `.qc` fing den Tipp ab, auch wenn der Knopf schon zurückgetreten war. */
body.lx-abwaerts .qc:not(.open) .qc__fab {
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: background .15s, transform .15s, opacity .18s ease, visibility 0s linear .18s;
}
/* ⚠️ DER RÜCKZUG WAR EIN HALBER — DIE HÜLLE FING DEN TIPP WEITER AB.
   GEMESSEN am 30.08.2026, «Heute» auf 390×620, zurückgetretener Knopf:
   `document.elementFromPoint()` in seiner Mitte lieferte `DIV.qc`. Der Knopf
   war unsichtbar und klickfrei — sein Behälter nicht. Ein Finger, der auf den
   Griff darunter zielte, landete also weiterhin im Nichts: 52 × 52 px tote
   Fläche über einem echten Bedienelement.
   Warum das seit W5.6 (09.08.) niemand sah: der Wächter
   `scripts/_boden_geometrie_test.mjs` fragte, ob der Punkt den KNOPF trifft
   («treffer === fab || fab.contains(treffer)») — `.qc` ist beides nicht, also
   meldete er brav «klickfrei». Die Probe ist am selben Tag geschärft worden
   und fragt jetzt nach der ganzen Hülle.
   Diese Korrektur gilt UNABHÄNGIG vom verworfenen Griff-Rückzug darüber: sie
   heilt den Lesevorgang seit W5.6 (09.08.), nicht die Verdeckung.
   Das offene Menü ist ausgenommen: dort MUSS geklickt werden können. */
body.lx-abwaerts .qc:not(.open) { pointer-events: none; }
/* REDUZIERTE BEWEGUNG braucht hier KEINE eigene Regel: der Schlussblock bei
   `@media (prefers-reduced-motion: reduce)` weiter oben drückt jede
   `transition-duration` im Haus mit `!important` auf 0.01ms (style.css, Block
   «Iter 17 Etappe 1»). Der Knopf tritt dort also weiter zurück — nur ohne
   Überblendung, weil das VERHALTEN Bedienbarkeit ist und die Bewegung Schmuck.
   Eine zweite Regel daneben wäre eine zweite Wahrheit über dasselbe.
   Gemessen: `scripts/_boden_geometrie_test.mjs`, Probe «bei reduzierter
   Bewegung tritt er ohne Animation zurück». */

/* =========================================================================
   Iter 25 Welle 2 — Cluster 2/3/4 Reskin: neue View-Klassen zentral (die
   parallelen View-Builder durften style.css nicht anfassen und haben sie als
   css_needed gemeldet). Am Dateiende → nach allen Basis-Regeln, damit die
   Mobile-Overrides gewinnen (css_cascade_mobile-Lehre).
   ========================================================================= */
/* manager-team / manager-goals: Abzeichen der vierten Rolle, die es seit dem 5. Juli nicht mehr gibt (SPRACHE.md, tote Rolle) — kein Profil trifft diesen Selektor noch */
.badge--role-setter { background: rgba(var(--accent-rgb),.16); color: var(--accent-strong); border-color: rgba(var(--accent-rgb),.32); }
/* sales-customers: Warn-Hinweis (Eigenfirma) + kompakter Empty-State im Modal */
.so-hint--warn { color: var(--warn); margin: 0; }
/* ENTFERNT, nicht ersetzt: `.empty-state--compact { padding: 16px }` — sie stand
   hier ZEICHENGLEICH ein zweites Mal, oben im Empty-State-Block des Grundstocks
   (Zeile 1032). Zwei gleiche Regeln sind harmlos, solange nichts dazwischen
   steht — und genau das aendert sich am 22.08.2026: der neue Modifikator
   `.empty-state--spalte` setzt `padding: 0` und stuende bei gleicher
   Spezifitaet VOR dieser Kopie, waere also wirkungslos gewesen (der leere Korb
   des Konfigurators haette in der 210px-Spalte 16px Polsterung bekommen).
   Die Kopie faellt, die Wahrheit bleibt EINMAL stehen. */
/* admin-sources: schmales Sortier-Zahlenfeld (min-width:0 schlägt den .field-Default 150px) */
.field--narrow { max-width: 120px; min-width: 0; }
#source-list .field--check { min-width: 0; }
.team-table tr.is-inactive td { opacity: .55; }
.team-table tr.is-inactive strong { color: var(--text-secondary); font-weight: 600; }
/* admin-intelligence: Zugriffs-Freischaltungs-Zeile (44px Touch-Target + Trenner) */
/* admin-catalog: Editor-Karten (ersetzen ~99 duplizierte Inline-Styles durch echte Klassen) */
.cat-q, .cat-rule, .ba-driver { border: 1px solid var(--border); border-radius: var(--radius-card); padding: 12px; margin-top: 12px; }
.ba-driver { padding: 10px; margin-top: 10px; }
.ba-driver--orphan { border-color: var(--medium); }
.cat-card__head { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.cat-opt { display: flex; gap: 6px; align-items: center; margin-top: 6px; flex-wrap: wrap; }
.cat-cond { display: flex; gap: 8px; align-items: flex-start; flex-wrap: wrap; margin-top: 8px; padding-top: 8px; border-top: 1px dashed var(--border); }
.cat-showwhen { margin-top: 10px; padding-top: 8px; border-top: 1px dashed var(--border); }
/* sales-pricing: Preismatrix-Zelle (3 Kinder: Preis/EB/aktiv) auf Mobile stapeln statt quetschen */
@media (max-width: 720px) {
  .sp-matrix td { flex-direction: column; align-items: flex-start; gap: 6px; }
  .sp-matrix .sp-price { width: 100%; }
}
/* sales-invoices: Toolbar-Button-Paar auf Mobile symmetrisch (beide voll/flex:1) */
@media (max-width: 720px) {
  .si-toolbar-actions { width: 100%; }
  .si-toolbar-actions .primary-btn, .si-toolbar-actions .ghost-btn { flex: 1; }
}
/* manager-activity: Detail-Spalte auf Desktop/Tablet mit Ellipsis (Tablet-Bruchzone 768-1024px) */
@media (min-width: 721px) {
  .activity-item-row__detail { max-width: 220px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
}
@media (min-width: 721px) and (max-width: 1024px) {
  .activity-item-row { grid-template-columns: 56px 140px 140px 1fr minmax(0, 160px); }
}

/* =========================================================================
   Iter 25 Welle 3 — Kommandozentrum «Mein Tag» + einheitlicher Kalender.
   Typ-Farben (Kalender-Quellen): Kundentermine behalten die Status-Klassen
   (.cal-event--planned usw.); neue Quellen bekommen EINEN Farbort je Typ —
   Aufgabe=Amber, Wiedervorlage=Info-Blau, freier Termin=Violett. Farbe nie
   allein: jeder Chip trägt zusätzlich Icon/Label (color-not-only, WCAG).
   ========================================================================= */
:root {
  --cal-task: #f5b83d;      /* Aufgabe (Amber, wie --warn dunkel) */
  --cal-callback: #6989c9;  /* Wiedervorlage (Info-Blau) */
  --cal-frei: #8b5cf6;      /* freier Termin (Violett) */
}

/* Kalender-Chips je Quelle (Muster wie Status-Klassen: border-left + Soft-Bg) */
.cal-event--type-task     { border-left-color: var(--cal-task); background: rgba(var(--warn-rgb), .08); }
.cal-event--type-callback { border-left-color: var(--cal-callback); background: rgba(var(--info-rgb), .08); }
.cal-event--type-frei     { border-left-color: var(--cal-frei); background: rgba(139, 92, 246, .08); }
.cal-event--type-task.is-done { opacity: .55; }
.cal-event--type-task.is-done strong { text-decoration: line-through; }
.cal-month__pill--type-task     { background: var(--cal-task); }
.cal-month__pill--type-callback { background: var(--cal-callback); }
.cal-month__pill--type-frei     { background: var(--cal-frei); }

/* Kanonische Aufgaben-Zeile (Mein Tag + Agenda). Checkbox = echter Button,
   44px Touch-Fläche, sichtbarer Kreis 22px. */
.task-row {
  display: flex; align-items: flex-start; gap: 8px;
  padding: 8px 12px 8px 4px;
  background: var(--surface-inset);
  border: 1px solid var(--border); border-radius: var(--radius-card);
}
.task-row__check {
  flex: 0 0 44px; min-height: 44px;
  display: flex; align-items: center; justify-content: center;
  background: none; border: none; padding: 0; cursor: pointer;
}
.task-row__check .task-row__circle {
  width: 22px; height: 22px; border-radius: 50%;
  border: 2px solid var(--line-strong);
  display: flex; align-items: center; justify-content: center;
  color: transparent;
  transition: border-color .15s ease, background .15s ease, color .15s ease;
}
.task-row__check:hover .task-row__circle { border-color: var(--accent); }
.task-row__check svg { width: 14px; height: 14px; }
.task-row__body { flex: 1; min-width: 0; padding-top: 10px; }
.task-row__title { display: block; font-weight: 600; color: var(--text-primary); overflow-wrap: anywhere; }
.task-row__meta { display: flex; flex-wrap: wrap; gap: 4px 10px; font-size: 12px; color: var(--text-secondary); margin-top: 2px; }
.task-row__meta .is-overdue { color: var(--bad-strong); font-weight: 600; }
.task-row__prio { font-variant-numeric: tabular-nums; }
/* «Ohne Frist» ist ein Zustand, kein Loch: fristlose Aufgaben standen vorher
   ohne jede Zeitangabe da und sahen aus wie halb erfasst. Leiser Ton — sie
   draengt nicht, sie existiert nur. */
.task-row__ohnefrist { color: var(--text-tertiary); }
.task-row.is-done { opacity: .62; }
.task-row.is-done .task-row__circle { background: var(--good-deep); border-color: var(--good-deep); color: #fff; }
.task-row.is-done .task-row__title { text-decoration: line-through; color: var(--text-secondary); font-weight: 400; }

/* Destruktive Sekundär-Aktion (Modal-Footer «Löschen») */
.ghost-btn--danger { color: var(--bad-strong); border-color: rgba(var(--bad-rgb), .35); }
.ghost-btn--danger:hover { background: rgba(var(--bad-rgb), .10); border-color: var(--bad-strong); }

/* Read-only Verknüpfungs-Hinweis im Aufgaben-Modal */
.task-modal__link { font-size: 12px; color: var(--text-secondary); margin: 2px 0 0; }

/* Wrapper der Aufgaben-Zeilen (Mein Tag) */
.task-list { display: flex; flex-direction: column; gap: 8px; }

/* Karte 01.08., Position 6: die Roadmap-Linse der Aufgaben-Fläche (#/m/tasks)
   ist mit ihr entfernt — .roadmap* hatte nach der Löschung von
   public/src/views/manager-tasks.js keinen Verwender mehr in public/src.
   Aufgaben leben im Panel auf «Heute» (.task-list oben) und im
   Kalender-Seitenpanel. */

/* Nicht-draggable Typ-Chips: pointer statt grab (Basis .cal-event hat grab) */
.cal-event--type-task, .cal-event--type-callback, .cal-event--type-frei { cursor: pointer; }

/* Quell-Warnbanner im Kalender (Kritiker-Fix: Totalausfall nie stumm) */
.cal-src-warn {
  margin: 0 0 8px; padding: 8px 12px;
  font-size: 12px; color: var(--warn-strong);
  background: rgba(var(--warn-rgb), .10);
  border: 1px solid rgba(var(--warn-rgb), .35); border-radius: var(--radius-card);
}

/* Namespace-Hooks ohne eigenes Styling (bewusst, Kritiker-Deklaration):
   .slot-menu (Wrapper auf .modal), .cal-agenda__row--appt (Default-Akzent). */

/* — Kalender Agenda-View (Iter 25 W3 E3.3) — */
.cal-agenda { display: flex; flex-direction: column; gap: 18px; padding: 14px; }
.cal-agenda__day { display: flex; flex-direction: column; gap: 6px; }
.cal-agenda__head { margin: 0 0 2px; font-size: 13px; font-weight: 600; color: var(--text-secondary); }
.cal-agenda__head.is-today { color: var(--accent-strong, var(--accent)); }
.cal-agenda__row {
  display: flex; align-items: center; gap: 10px;
  min-height: 44px; width: 100%; padding: 8px 12px;
  background: rgba(var(--tint-rgb), .025); border: 0;
  border-left: 3px solid var(--accent); border-radius: var(--radius-card);
  color: var(--text); font: inherit; text-align: left; cursor: pointer;
}
.cal-agenda__row:hover { background: var(--surface-inset); }
.cal-agenda__time { flex: 0 0 auto; min-width: 40px; font-size: 12px; font-variant-numeric: tabular-nums; color: var(--text-secondary); }
.cal-agenda__ico { flex: 0 0 auto; display: inline-flex; color: var(--text-secondary); }
.cal-agenda__ico svg { width: 16px; height: 16px; }
.cal-agenda__main { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.cal-agenda__main strong { font-size: 13px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cal-agenda__main small { font-size: 11px; color: var(--text-secondary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cal-agenda__row--type-task     { border-left-color: var(--cal-task); }
.cal-agenda__row--type-callback { border-left-color: var(--cal-callback); }
.cal-agenda__row--type-frei     { border-left-color: var(--cal-frei); }
.cal-agenda__row--type-task.is-done { opacity: .55; }
.cal-agenda__row--type-task.is-done strong { text-decoration: line-through; }
.cal-agenda__row--st-won { border-left-color: var(--high, var(--good)); }
.cal-agenda__row--st-lost, .cal-agenda__row--st-cancelled { border-left-color: var(--low, var(--bad-deep)); }
.cal-agenda__row--st-completed { border-left-color: var(--text-secondary); }
.cal-agenda__row--st-no_show { border-left-color: var(--medium); }

/* =========================================================================
   Iter 33 B1 — Mehr-Mitarbeiter-Overlay: Farbe PRO PERSON.
   Eigener Farb-Slot = PUNKT (DESIGN.md:77,82), nicht der schon durch Typ/Status
   belegte linke Balken. Cyan bleibt der Interaktion vorbehalten (nicht in der
   Palette). Farbe nie allein: der Punkt trägt immer Name/Tooltip als Begleiter.
   8 qualitativ getrennte Farbtöne, je Theme abgestimmt.
   ========================================================================= */
:root {
  --cal-person-1: #f2748c;  --cal-person-2: #f0995a;  --cal-person-3: #5fcf8f;  --cal-person-4: #6f9bef;
  --cal-person-5: #b28bf0;  --cal-person-6: #e58ad0;  --cal-person-7: #4fc4b0;  --cal-person-8: #d9c15a;
}
/* Der Farb-Punkt: kleiner Kreis mit dünnem Ring (bleibt auch auf farbigen
   Month-Pills sichtbar). flex-shrink:0 → wird nie zusammengequetscht. */
.cal-owner-dot {
  display: inline-block; flex: 0 0 auto;
  width: 9px; height: 9px; border-radius: 50%;
  background: var(--owner-color, var(--text-tertiary));
  box-shadow: 0 0 0 1.5px var(--surface-2), 0 0 0 2.5px rgba(0,0,0,.18);
  margin-right: 5px; vertical-align: middle;
}

/* Die Haekchenliste «Wessen Kalender» ist am 08.09.2026 aus dem Baum gefallen
   (EINE Wahl in der Kalender-Leiste, views/manager-calendar.js). Ihre Regeln
   (.cal-people, .cal-people-pop*) stehen darum nicht mehr hier — eine Regel
   ohne Griff liest der Naechste als lebendig. Der Farbpunkt am Eintrag
   (.cal-owner-dot, oben) bleibt: er traegt weiter die Person je Eintrag. */

/* — Gratis-Screens im Offerten-Wizard (Owner-Mandat 2026-07-04; Wording eisern).
   Iter 27: ruhige Pill statt dashed-Border-Prototyp-Optik. — */
.so2-gratisbtn {
  flex: 0 0 auto;
  min-height: 32px; padding: 4px 10px;
  font: inherit; font-size: 12px; font-weight: 600;
  color: var(--text-secondary);
  background: var(--surface-2);
  border: 1px solid var(--border); border-radius: var(--radius-badge);
  cursor: pointer;
}
.so2-gratisbtn:hover { border-color: var(--good-deep); color: var(--good-strong); }
.so2-gratisbtn.is-on {
  color: var(--good-strong);
  background: rgba(var(--good-rgb), .12);
  border-color: transparent;
}
.so2-gratisbtn.is-rule { cursor: default; }
.so2-gratis-note { color: var(--good-strong); font-weight: 600; font-size: 12px; margin-left: 4px; }

/* — Slot-Typ-Wahl-Menü (Iter 25 W3 E3.3) — */
.slot-menu__list { display: flex; flex-direction: column; gap: 8px; }
.slot-menu__btn {
  display: flex; align-items: center; gap: 12px;
  min-height: 52px; width: 100%; padding: 10px 14px;
  background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--radius-card);
  color: var(--text); font: inherit; text-align: left; cursor: pointer;
}
.slot-menu__btn:hover, .slot-menu__btn:focus-visible { border-color: var(--accent); background: var(--surface-inset); }
.slot-menu__ico { flex: 0 0 auto; display: inline-flex; color: var(--accent); }
.slot-menu__ico svg { width: 22px; height: 22px; }
.slot-menu__txt { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.slot-menu__txt strong { font-size: 14px; }
.slot-menu__txt small { font-size: 12px; color: var(--text-secondary); }

/* ============================================================
   Iter 27 Welle B — Leads-Cluster (Pool / Pipeline / Caller-Leads)
   firm-card als Zeilen-Hybrid, Prio-Punkt-Badge, kompakte Filter.
   ============================================================ */

/* Prio-Badge: Punkt + Text (ersetzt Unicode-«●» hinter dem Label) */
.badge__dot { width: 7px; height: 7px; border-radius: 50%; background: currentColor; flex: none; opacity: .9; }

/* — firm-card v2 (.firm-card--lead): Name führt, Meta darunter, Kontakt rechts —
   Grid mit auto-Spalte: Titel und Kontakt teilen Zeile 1 ohne Überlappungsrisiko.
   Alt-Klassen (.firm-card__top/__headings) bleiben für manager-lost unangetastet. */
.firm-card--lead {
  position: relative; display: grid; grid-template-columns: minmax(0, 1fr) auto;
  gap: 7px 14px; padding: 12px 16px; align-items: start;
}
/* :not(.firm-card__check): der absolute Checkbox-Label darf KEINE definite
   Grid-Area bekommen — sonst wird die Grid-Area (Titelzeile, beginnt beim
   48px-Gutter) sein Containing-Block und die Box überlappt den Namen. */
.firm-card--lead > :not(.firm-card__check) { grid-column: 1 / -1; min-width: 0; }
.firm-card--lead .firm-card__title {
  grid-column: 1; grid-row: 1;
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap; min-width: 0;
}
.firm-card--lead .firm-card__title h3 {
  margin: 0; font-size: 15px; font-weight: 600; letter-spacing: -.005em;
  color: var(--text-primary); line-height: 1.35;
}
/* Der ORT gehört zum Namen, nicht zu den Abzeichen: «Wer ist das?» ist EINE
   Frage. Die Region beantwortet sie nicht — «Hairwerk Winterthur Nord» trägt
   die Region «Zürich» und liegt in Winterthur.
   Er ist STUMM, solange die Meta-Zeile darunter die volle Adresse zeigt: dort
   stünde der Ort sonst zweimal auf derselben Karte. Sichtbar wird er genau da,
   wo die Adresse fällt — in der Kurzform der Pool-Liste am Handy. */
.firm-card__ort { display: none; font-size: 13px; color: var(--text-secondary); min-width: 0; }
.firm-card__ort::before { content: "· "; color: var(--text-tertiary); }
/* WAS JETZT DRAN IST — dieselbe Bauform wie auf der Offerten-Karte
   (`.vk-karte__schritt`): ein leises Etikett, dahinter die Handlung im
   Klartext. Ein Status-Kürzel sagt, wo man steht; diese Zeile sagt, was man
   tut. */
.firm-card__schritt {
  display: flex; align-items: baseline; gap: 6px;
  margin: 0; font-size: 12.5px; line-height: 1.35; color: var(--text-secondary);
}
/* 9.5px -> 11px am 22.08.2026: der Schrift-Boden aus DESIGN.md §2 («nichts
   rendert unter 11px») gilt gerade hier. Das Wort «NAECHSTER SCHRITT» steht
   ueber der Handlung, die den Kernablauf des Hauses traegt — 805 zugeteilte
   Leads, 4 protokollierte Anrufe. Die Regel stand als BEFUND, nicht als
   Erlaubnis, in scripts/_schrift_boden_test.mjs; sie ist jetzt gehoben und die
   Ausnahme dort gestrichen. */
.firm-card__schritt-wort {
  flex: 0 0 auto;
  font-size: 11px; font-weight: 700; letter-spacing: .07em; text-transform: uppercase;
  color: var(--text-tertiary);
}
.firm-card--lead .firm-card__contact {
  grid-column: 2; grid-row: 1;
  display: flex; flex-wrap: wrap; gap: 6px; justify-content: flex-end;
}
.firm-card--lead .firm-card__meta { margin: 0; font-size: 12.5px; }
.firm-card--lead .firm-card__schmerz { margin-top: 0; padding: 6px 9px; display: flex; gap: 6px; align-items: baseline; }
.firm-card--lead .firm-card__schmerz .eico { flex: none; color: var(--warn-strong); }
.firm-card--lead .firm-card__cb { margin-top: 0; }
.firm-card--lead .firm-card__notes { margin: 0; }
.firm-card--lead .firm-card__bottom { margin-top: 0; }
.firm-card--lead .firm-card__qa { margin-top: 2px; }
/* Checkbox: hover-reveal auf Zeigegeräten (DESIGN.md §4), permanent auf Touch */
.firm-card--lead.firm-card--selectable { padding-left: 48px; }
.firm-card--lead .firm-card__check { top: 2px; left: 2px; }
@media (hover: hover) and (pointer: fine) {
  .firm-card--lead.firm-card--selectable .firm-card__check { opacity: 0; transition: opacity var(--dur-fast) var(--ease); }
  .firm-card--lead.firm-card--selectable:hover .firm-card__check,
  .firm-card--lead.firm-card--selectable:focus-within .firm-card__check,
  .firm-card--lead.firm-card--selectable.is-selected .firm-card__check { opacity: 1; }
}
/* Mobile: eine Spalte (Flex + order) — Kontakt-Pills rutschen unter die Meta-Zeile */
@media (max-width: 720px) {
  .firm-card--lead { display: flex; flex-direction: column; padding: 12px 14px; gap: 7px; }
  .firm-card--lead .firm-card__title { order: 1; }
  .firm-card--lead .firm-card__meta { order: 2; }
  .firm-card--lead .firm-card__contact { justify-content: flex-start; order: 3; }
  .firm-card--lead .firm-card__schmerz { order: 4; }
  .firm-card--lead .firm-card__cb { order: 5; }
  .firm-card--lead .firm-card__notes { order: 6; }
  .firm-card--lead .firm-card__qa { order: 7; }
  .firm-card--lead .firm-card__bottom { order: 8; }
}

/* — Filter-Panels kompakt (Pool / Pipeline / Leads-Liste): Selects 2-spaltig
   auf Mobile statt 4 gestapelter Vollbreite-Felder (ein Screen Filter = Defekt).
   Steht NACH den Basis-@media-Regeln (Cascade: später gewinnt). — */
@media (max-width: 720px) {
  .filters-panel { padding: 8px 10px; }
  .filters-panel .filters-toolbar { gap: 8px; }
  /* 06.08., dritte Owner-Meldung zum Handy: das Zwei-Spalten-Raster stellte
     das Suchfeld ueber ganze Breite und schob den Filter-Knopf in die naechste
     Zeile — 97 px fuer zwei Elemente, die nebeneinander passen. Eine Zeile,
     waagrecht scrollbar: die Suche nimmt den Rest, alles andere behaelt seine
     Groesse. */
  .filters-panel .filters-group {
    display: flex; flex-direction: row; flex-wrap: nowrap; gap: 8px;
    align-items: center; overflow-x: auto; scrollbar-width: none;
  }
  .filters-panel .filters-group::-webkit-scrollbar { display: none; }
  .filters-panel .filters-group > * { flex: 0 0 auto; }
  .filters-panel .filters-group .field { min-width: 0; width: auto; gap: 4px; }
  .filters-panel .filters-group .field--search,
  .filters-panel .filters-group .field--wide { flex: 1 1 0; min-width: 110px; }
  /* Das Label ueber dem Feld ist am Handy eine Zeile fuer ein Wort, das der
     Platzhalter schon sagt. */
  .filters-panel .filters-group .field--search > span { display: none; }
  .filters-panel .filters-actions {
    display: flex; gap: 8px; align-items: center; width: 100%;
    flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none;
  }
  .filters-panel .filters-actions::-webkit-scrollbar { display: none; }
  .filters-panel .filters-actions .ghost-btn,
  .filters-panel .filters-actions .primary-btn { flex: 0 1 auto; white-space: nowrap; }
  .filters-panel .filters-actions .results-pill { flex: 0 0 auto; }
}

/* Zeitraum-Track darf sein Grid-Item nie aufblähen (min-width:auto-Falle):
   sonst schiebt der nowrap-Track das ganze Filter-Panel über den Viewport. */
.filters-toolbar--activity { grid-template-columns: minmax(0, 1fr); }
.time-range-slot { min-width: 0; }

/* ============================================================
   Iter 27 Welle D — Verkauf (Standorte/Offerten/Kunden/Rechnungen/
   P&L/Preisregeln/Offer-Editor): Foundation-Vokabular in den Listen.
   ============================================================ */

/* Stat-Strip-Variante für 3–5 Kennzahlen: EINE Zeile auf Desktop
   (grid-auto-flow verhindert Wrap-Artefakte der Hairlines), 2-spaltig mobil. */
/* Use the shared responsive grid for a variable number of cards. An enforced
   single row made full currency values overflow despite unused page space. */
.stat-strip--auto { grid-template-columns: repeat(auto-fit, minmax(min(100%, 200px), 1fr)); grid-auto-flow: row; grid-auto-columns: auto; }
/* 641px UNTERGRENZE (04.09.2026): diese Regel steht SPAETER in der Datei als
   «DIE EINE ZEILE» und wiegt gleich schwer — ohne Untergrenze haette sie den
   Streifen unter 640 px wieder in zwei Spalten gelegt, ausgerechnet auf den
   Flaechen mit `--auto`. Zwischen 641 und 720 px bleibt alles wie gehabt. */
/* UNTER 640 px GILT «DAS GLEICHE RASTER» AUCH FUER --auto — und diese Zeilen
   muessen HIER stehen, nicht oben im Block: die Grundregel von
   `.stat-strip--auto` steht SPAETER in dieser Datei und wiegt gleich schwer,
   also legte sie den Streifen sonst wieder in EINE Reihe (`grid-auto-flow:
   column`) und die Spaltenangabe von oben waere still ohne Wirkung. GEMESSEN
   05.09. an den Rechnungen: mit `--auto` allein standen drei von vier Kacheln
   im Bild, die vierte ausserhalb.
   Die Fassung vom 04.09. (`grid-auto-columns: minmax(120px, 1fr)`) ist damit
   ERSETZT — sie war die Mindestbreite der Rollreihe, die es nicht mehr gibt. */
@media (max-width: 640px) {
  .stat-strip--auto {
    grid-auto-flow: row;
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  /* Die volle Breite fuer die ungerade letzte Kachel steht oben bei
     `.stat-strip` und gilt hier mit — `--auto` ist dieselbe Kachelreihe. */
}
@media (max-width: 720px) and (min-width: 641px) {
  .stat-strip--auto { grid-auto-flow: row; grid-auto-columns: auto; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  /* ENTFERNT 25.08. (Rueckweg git): die beiden Rest-Strich-Regeln
     `.stat-strip--auto > .stat:nth-child(2n+1|n+3)`. Sie gehoerten zur
     geteilten Haarlinie von 13.08.; die geschlossene Karte trennt sich seit
     heute selbst, und die Regeln haetten ihr die linke Kante ausgeschnitten. */
}

/* Einzel-Stat als Well (P&L Break-even neben dem Preis-Feld) */
.stat--well { background: var(--surface-inset); justify-content: center; }
.stat--well .stat__label { white-space: normal; overflow: visible; }

/* Tabellen-Zahlenspalten: rechtsbündig + tabular + unbrechbar (DESIGN.md §4
   Tabelle) — «CHF 59'481.95» darf nie mitten im Betrag umbrechen. Mobile-
   Stapelmodus (td = flex, Wert rechts) bleibt davon unberührt. */
.sl-table th.num, .sl-table td.num {
  text-align: right; font-variant-numeric: tabular-nums lining-nums;
  white-space: nowrap; overflow-wrap: normal;
}
/* Datums-/ID-Zellen: kompakt halten (die overflow-wrap:anywhere-Datenregel
   oben bricht sonst «09.07.26» mitten im Datum, wenn Nachbarn drücken) */
.sl-table .nw { white-space: nowrap; overflow-wrap: normal; }

/* Listen-Tabellen als EIN Panel (DESIGN.md §1): Panel-Fläche + Scroll-Hint-
   Gradienten in einem Background (die .table-wrap-Gradienten allein liessen
   die Panel-Fläche sonst transparent — .table-wrap gewinnt die Kaskade). */
.table-wrap.panel {
  padding: 2px 0 4px;
  background:
    linear-gradient(to right,  var(--surface), rgba(20,20,20,0)) left  center / 24px 100% no-repeat local,
    linear-gradient(to left,   var(--surface), rgba(20,20,20,0)) right center / 24px 100% no-repeat local,
    radial-gradient(farthest-side at 0% 50%, rgba(var(--tint-rgb), .16), rgba(var(--tint-rgb), 0)) left  center / 14px 100% no-repeat scroll,
    radial-gradient(farthest-side at 100% 50%, rgba(var(--tint-rgb), .16), rgba(var(--tint-rgb), 0)) right center / 14px 100% no-repeat scroll,
    var(--surface);
}
.table-wrap.panel .team-table th { padding-top: 13px; }
@media (max-width: 720px) {
  .table-wrap.panel { padding: 4px 0; }
}

/* ============================================================
   Iter 27 Welle E — Team/Analyse/Admin/Profil
   Notizen, Dirty-Flag, Modal-KPI-Strip, iCal-Hilfe.
   ============================================================ */

/* Hinweis-Note: erhabene Fläche + Inset-Akzent-Bar (ersetzt border-left-Streifen
   und Roh-rgba-Inline-Blöcke; DESIGN.md Kill-Liste). */
.note {
  padding: 10px 14px; border-radius: var(--radius-card);
  font-size: 13px; line-height: 1.55; color: var(--text-secondary);
  background: var(--surface-2);
  box-shadow: inset 2.5px 0 0 var(--accent);
}
.note strong { color: var(--text-primary); }
.note .eico { color: var(--warn-strong); }
.note--warn { box-shadow: inset 2.5px 0 0 var(--warn-deep); background: rgba(var(--warn-rgb), .07); }
.note--warn strong { color: var(--warn-strong); }

/* Katalog-Editor: «ungespeicherte Änderungen» — CSS-Punkt statt Unicode-«●» */
.dirty-flag { display: inline-flex; align-items: center; gap: 7px; color: var(--medium); font-size: 13px; font-weight: 600; }
.dirty-flag:not(:empty)::before { content: ''; width: 7px; height: 7px; border-radius: 50%; background: currentColor; flex: none; }

/* User-Detail-Modal: KPI-Minis als Strip (4-spaltig, Hairlines; ersetzt
   die Icon-losen kpi-card--mini-Boxen-in-Boxen) */
.kpi-strip--modal { grid-template-columns: repeat(4, minmax(0, 1fr)); padding: 0; }
.kpi-strip--modal .kpi-pill { padding: 8px 14px; }
.kpi-strip--modal .kpi-pill strong { font-size: 18px; }
.kpi-strip--modal .kpi-pill:nth-child(4n+1) { border-left: 0; }
.kpi-strip--modal .kpi-pill:nth-child(n+5) { border-top: 1px solid var(--border); }
@media (max-width: 640px) {
  .kpi-strip--modal { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .kpi-strip--modal .kpi-pill:nth-child(2n+1) { border-left: 0; }
  .kpi-strip--modal .kpi-pill:nth-child(n+3) { border-top: 1px solid var(--border); }
}

/* 21.08.2026 entfernt: `.ics-help` (drei Regeln) — die Anleitung «So fuegst du
   das Abo ein» auf #/profil. Das Abo fuer fremde Kalender-Programme ist vom
   Owner abgelehnt (OWNER-WUENSCHE Punkt 27); die Flaeche dazu ist weg, also
   auch ihr Stil. Rueckweg: ~/.claude-lager/loopx13/kalender-abo-2026-08-21/ */

/* Nicht-klickbare firm-card-Zeile (manager-lost: Aktion ist der Button, nicht
   die Karte) — neutralisiert Cursor + Hover-Lift der klickbaren Basis. */
.firm-card--static { cursor: default; }
.firm-card--static:hover {
  transform: none; box-shadow: none; border-color: var(--border);
  background: var(--surface);
}

/* ============================================================
   Iter 27 Welle F — geteilte Komponenten/Modals
   (Toast-Stack + Empty-State-Ring leben in ihren Foundation-
   Sektionen; hier nur die neuen Selektions-/Detail-Muster.)
   ============================================================ */

/* Assign-Modal: gewählte Person = Tint + Inset-Bar (Selektions-Idiom,
   keine Vollborder). :has ist im Codebestand etabliert (.oc-status__option). */
.user-checkbox:has(input:checked) {
  background: linear-gradient(180deg, rgba(var(--accent-rgb), .07), rgba(var(--accent-rgb), .04)), var(--surface-2);
  box-shadow: inset 2.5px 0 0 var(--accent);
}
/* Personen-Namen sind Daten, keine Micro-Labels — die .field-span-Kaskade
   (uppercase 10.5px) darf sie nicht erfassen. */
.user-checkbox .user-checkbox__body {
  text-transform: none; letter-spacing: normal; font-size: 13.5px;
}
.user-checkbox__body strong { color: var(--text-primary); }

/* Fieldset ohne native Rahmen-Chrome (assign-modal «Wer bekommt Leads?» /
   «Priorität») — Legende als Micro-Label wie .field span, kein Wireframe. */
.modal fieldset.field { border: 0; padding: 0; margin: 0; min-width: 0; }
.modal fieldset.field legend {
  padding: 0; margin-bottom: 2px;
  color: var(--text-tertiary); font-size: 11px; text-transform: uppercase;
  letter-spacing: .07em; font-weight: 600;
}

/* .note mit Fliesstext-Absatz (firm-modal Cross-Reference) */
.note p { margin: 4px 0 0; color: var(--text-secondary); }

/* Outcome-Modal: Firmenname in der Sub-Zeile führt (Titel stellt die Frage) */
.modal__header-sub strong { color: var(--text-primary); font-weight: 600; }


/* =========================================================================
   Iter 27 — Motion + Command-Palette (aus iter27.css gemerged: eine Wahrheit)
   ========================================================================= */

/* =========================================================================
   Iter 27 — Motion + Command-Palette (DESIGN.md §5/§6).
   View-Enter, ⌘K-Palette, Sidebar-Suche; FAB nur noch Touch/Mobile.
   ========================================================================= */
/* View-Enter: Fade + 4px-Rise — Zustand, keine Ladeshow */
@keyframes view-enter { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } }
#app-view.view-enter { animation: view-enter var(--dur) var(--ease); }

/* Listen-Stagger: nur die ersten 8 Karten, 16ms Versatz, einmal pro Render */
.firms-list > .firm-card { animation: view-enter var(--dur) var(--ease) backwards; }
.firms-list > .firm-card:nth-child(1) { animation-delay: 0ms; }
.firms-list > .firm-card:nth-child(2) { animation-delay: 16ms; }
.firms-list > .firm-card:nth-child(3) { animation-delay: 32ms; }
.firms-list > .firm-card:nth-child(4) { animation-delay: 48ms; }
.firms-list > .firm-card:nth-child(5) { animation-delay: 64ms; }
.firms-list > .firm-card:nth-child(6) { animation-delay: 80ms; }
.firms-list > .firm-card:nth-child(7) { animation-delay: 96ms; }
.firms-list > .firm-card:nth-child(8) { animation-delay: 112ms; }

/* Sidebar-Suche (öffnet die Palette) — Input-Optik, aber ein Button */
.sidebar__search {
  display: flex; align-items: center; gap: 9px; width: 100%; min-height: 34px;
  margin: 0 0 10px; padding: 7px 10px;
  background: var(--surface-inset); border: 1px solid var(--border); border-radius: var(--radius-button);
  color: var(--text-tertiary); cursor: pointer; font: 500 13px/1 inherit; text-align: left;
  transition: border-color var(--transition), background var(--transition), color var(--transition);
}
.sidebar__search:hover { border-color: var(--line-strong); color: var(--text-secondary); background: var(--surface-hover); }
.sidebar__search-ic { display: inline-flex; flex: none; width: 15px; height: 15px; }
.sidebar__search-ic svg { width: 15px; height: 15px; }
.sidebar__search-label { flex: 1; overflow: hidden; text-overflow: ellipsis; }
@media (min-width: 901px) {
  body.sidebar-collapsed .sidebar__search { justify-content: center; padding: 7px; }
  body.sidebar-collapsed .sidebar__search-label { display: none; }
}
@media (max-width: 1024px), (pointer: coarse) { .sidebar__search { min-height: 44px; } }

/* Command-Palette */
.cp { position: fixed; inset: 0; z-index: 400; }
.cp__backdrop { position: absolute; inset: 0; background: rgba(4, 8, 12, .55); backdrop-filter: blur(6px); animation: backdrop-in var(--dur) var(--ease); }
.cp__panel {
  position: relative; margin: min(14vh, 120px) auto 0; width: min(600px, calc(100vw - 28px));
  background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--radius-card);
  box-shadow: var(--shadow-lg); overflow: hidden;
  animation: modal-in var(--dur) var(--ease);
}
.cp__inputrow { display: flex; align-items: center; gap: 10px; padding: 6px 14px; border-bottom: 1px solid var(--border); }
.cp__searchicon { display: inline-flex; width: 17px; height: 17px; color: var(--text-tertiary); flex: none; }
.cp__searchicon svg { width: 17px; height: 17px; }
.cp__input {
  flex: 1; min-width: 0; min-height: 46px; border: 0; outline: none; background: transparent;
  color: var(--text-primary); font-size: 15px;
}
.cp__input::placeholder { color: var(--text-tertiary); }
.cp__kbd { font: 500 10.5px/1 inherit; color: var(--text-tertiary); border: 1px solid var(--border); border-radius: var(--radius-card); padding: 3px 5px; text-transform: uppercase; }
.cp__list { max-height: min(52vh, 420px); overflow-y: auto; padding: 6px; }
.cp__group { padding: 8px 10px 4px; color: var(--text-tertiary); font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: .07em; }
.cp__item {
  display: flex; align-items: center; gap: 11px; width: 100%;
  padding: 9px 10px; min-height: 40px; border: 0; border-radius: var(--radius-card);
  background: transparent; color: var(--text); font: 500 13.5px/1.3 inherit; text-align: left; cursor: pointer;
}
.cp__item.is-active { background: rgba(var(--accent-rgb), .12); color: var(--text-primary); }
.cp__item.is-active .cp__item-ic { color: var(--accent); }
.cp__item-ic { display: inline-flex; flex: none; width: 17px; height: 17px; color: var(--text-tertiary); }
.cp__item-ic svg { width: 17px; height: 17px; }
/* 04.09.2026 — DER TREFFER SAGT, WER DAS IST: Name gross, darunter Ort und
   Nummer, rechts sein Zustand. Anatomie aus der Referenz Portaluikomplett
   (13_25_27.png, Reihen «Letzte Aktivitaeten»/«Aktive Agenten»). Die Spalte
   traegt `min-width: 0`, sonst waechst ein Grid-/Flex-Kind ueber seinen
   Elternkasten hinaus und schneidet ohne Scrollbalken ab. */
.cp__item-text { display: flex; flex: 1; min-width: 0; flex-direction: column; gap: 2px; }
.cp__item-label { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cp__item-sub {
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  color: var(--text-tertiary); font-size: 11.5px; line-height: 1.3; font-weight: 400;
}
/* Die getroffenen Ziffern. Kein neuer Farbwert — dieselbe Toenung, mit der
   diese Flaeche schon «hier stehe ich» sagt (`.cp__item.is-active`), nur
   dichter. `mark` bringt vom Browser Gelb auf Schwarz mit; das wird hier
   vollstaendig ersetzt. */
.cp__treffer {
  background: rgba(var(--accent-rgb), .22); color: var(--text-primary);
  border-radius: 3px; padding: 0 2px; font-weight: 600;
}
.cp__item-meta {
  color: var(--text-tertiary); font-size: 11.5px; flex: none;
  max-width: 46%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.cp__item-go { display: inline-flex; color: var(--text-tertiary); opacity: 0; transition: opacity var(--transition); }
.cp__item.is-active .cp__item-go { opacity: 1; }
.cp__empty { padding: 22px 14px; text-align: center; color: var(--text-tertiary); font-size: 13px; }
body.cp-open { overflow: hidden; }
@media (max-width: 720px) {
  .cp__panel { margin-top: max(16px, var(--sat)); }
  .cp__list { max-height: min(62vh, 480px); }
  .cp__item { min-height: 44px; }
}
/* Der Griff-Boden haengt am FINGER, nicht an der Fensterbreite: ein Tablet in
   Querlage ist breiter als 720 px und wird trotzdem getippt. */
@media (pointer: coarse) { .cp__item { min-height: 44px; } }

/* FAB: am Desktop ersetzt durch Sidebar-Suche/⌘K + Kontext-Buttons; auf Touch
   bleibt er (Daumen-Ergonomie), aber als präzises Werkzeug statt Material-Blob.
   Der türkise 40px-Radius darunter WAR der Material-Blob, den dieser Kommentar
   ausschliesst — 03.08. entfernt. Der schwarze Schatten bleibt: er trägt die
   Schwebe (der FAB liegt wirklich über der Seite), nicht Farbe. */
@media (min-width: 901px) { .qc { display: none; } }
.qc__fab {
  width: 52px; height: 52px; border-radius: var(--radius-card);
  box-shadow: 0 6px 16px rgba(2,8,9,.45);
}
.qc__fab:active { transform: scale(.94); }

/* Reduced Motion: alle Iter-27-Animationen neutralisieren */
@media (prefers-reduced-motion: reduce) {
  #app-view.view-enter, .firms-list > .firm-card, .cp__backdrop, .cp__panel, .modal, .modal-backdrop, .toast { animation: none !important; }
}

/* Login-Politur (Iter 27): Untertitel, Passwort-Toggle, Karten-Entrance */
.login-card { animation: modal-in var(--dur-slow) var(--ease); }
.login-sub { margin: -14px 0 18px; color: var(--text-tertiary); font-size: 13px; }
.pw-wrap { position: relative; display: block; }
.pw-wrap input { width: 100%; padding-right: 50px; }
/* Handy-Rundgang 03.08.: der Knopf mass 34×34 und war damit das EINZIGE
   Bedienelement des Hauses unter 44 px — ausgerechnet auf der Fläche, die
   jeder Mitarbeiter täglich sieht. Vergrössert wird die TREFFERFLÄCHE, nicht
   das Auge: das SVG bleibt bei 17 px, sonst würde der Knopf das Feld
   optisch erschlagen. `right: 2px` + 50 px Textabstand halten den Text frei. */
.pw-toggle {
  position: absolute; right: 2px; top: 50%; transform: translateY(-50%);
  width: 44px; height: 44px; display: grid; place-items: center;
  border: 0; background: transparent; color: var(--text-tertiary); border-radius: var(--radius-card); cursor: pointer;
}
.pw-toggle:hover { color: var(--text-secondary); background: rgba(var(--tint-rgb), .06); }
.pw-toggle svg { width: 17px; height: 17px; }

/* FAB verdeckt keine Inhalte — der Knopf MELDET seinen Platzbedarf, statt dass
   ihn drei Flächen-Regeln in drei Grössen raten (112 · 140 · 84 px).
   64px = 12px Luft über dem Boden + 52px Knopf (`.qc__fab` oben).
   Nur am Handy: ab 901px blendet `.qc` sich aus (Regel darüber), dort bleibt
   die Reserve 0 — der Rechner ändert sich um kein Pixel. */
@media (max-width: 900px) {
  body.has-quick-create { --fab-h: 64px; }
}

/* DER PLUS WANDERT IN DIE LEISTE (05.09.2026)
   ---------------------------------------------------------------------------
   ANLASS, an den Live-Bildern des Eigentuemers gemessen (390 px, Chromium und
   WebKit, gleiches Bild): der schwebende Knopf deckte auf der Zentrale die
   Verlaufszeile «vor 23 Stunden» zu, auf der Lead-Akte die Kachel «Termine»
   und im Kanban den Satz «CHF 0 erwartet aus 6 offenen Terminen». Die
   INHALTS-RESERVE (`--fab-h`, oben) haelt ihn von der LETZTEN Zeile fern; sie
   kann nichts dagegen tun, dass er mitten auf der Flaeche liegt.

   DIE REFERENZ ENTSCHEIDET, nicht der Geschmack: das iPhone in
   docs/design/referenzen/Portaluikomplett/«ChatGPT Image 29. Juli 2026,
   13_25_27.png» hat KEINEN schwebenden Knopf — es hat die Leiste am Daumen mit
   festen Zielen. Genau dorthin geht «Neu» (components/app-chrome.js,
   `unterleisteMarkup`): gleiche Bauart wie die anderen Ziele, in der Mitte,
   und es ruft dasselbe Menue (quick-create.js, `schnellwahlUmschalten`).

   NUR DA, WO DIE LEISTE WIRKLICH STEHT (`body:has(.lx-unten)`): eine Rolle mit
   weniger als zwei Tueren (partner) bekommt keine Leiste — dort bleibt der
   Knopf ihr einziger Weg und alles wie bisher. Am Schreibtisch (ab 901 px) ist
   `.qc` ohnehin aus.

   Die Reserve faellt im selben Zug weg: wer den Knopf ausblendet, gibt seinen
   Platz frei (dieselbe Regel wie bei `so-editor-open` und `lx-werkflaeche`).
   Die HUELLE `.qc` bleibt — in ihr wohnt das Menue. Sie spannt sich am Telefon
   ueber die Breite und legt das Menue direkt ueber die Leiste, statt es 68 px
   ueber einem Knopf schweben zu lassen, den es dort nicht mehr gibt. */
@media (max-width: 900px) {
  body:has(.lx-unten) .qc__fab { display: none; }
  body:has(.lx-unten).has-quick-create { --fab-h: 0px; }
  body:has(.lx-unten) .qc {
    left: 12px; right: 12px;
    bottom: calc(var(--boden-h) + var(--leiste-h) + var(--vv-unten, 0px) + 10px);
  }
  /* Im Fluss der Huelle statt ueber ihr: ohne Knopf haette `bottom: 68px` das
     Menue eine Knopfhoehe zu hoch aufgehaengt. */
  body:has(.lx-unten) .qc__menu { position: static; min-width: 0; }
  /* EIN KNOPF HAT EINEN ORT (Owner-Gesetz 03.09.: «gleiche Beschriftung
     zweimal auf einer Flaeche = Fehler»). Steht «Neu» am Daumen, verschwindet
     der gleichlautende Griff aus dem Seitenkopf: die Offerten trugen ihn als
     «+ Neue Offerte», die Kunden als «+ Neuer Kunde» — auf 390 px las man auf
     EINER Flaeche zweimal «NEU» und musste raten, ob die beiden dasselbe tun.
     Sie tun dasselbe: der Griff im Kopf fuehrt auf `#/v/offer/new` bzw. ins
     Kundenformular, und genau diese zwei Zeilen stehen im Menue des
     Leisten-Ziels. Am Schreibtisch (ab 901 px, keine Leiste) bleibt der Griff
     im Kopf, wo er seit dem 08.08. steht — dort ist er der einzige. */
  body:has(.lx-unten) [data-neu-handgriff] { display: none; }
}

/* ============================================================================
   Iter 30 I2 — Sichtbarkeit (v78): Wizard-Annotation, Lösungs-Cards,
   Belegungs-Heatmap, Verzugs-/Renewal-Ampel, Guthaben, Konflikt-Queue.
   Kanon: Mobile-@media NACH der Basis (project_css_cascade_mobile),
   Touch-Floor via (max-width:1024px),(pointer:coarse).
   ========================================================================== */

/* ---- Live-Verfügbarkeit — Wizard-Annotation Schritt 2 (§2K) ---- */
.so-avail-head { margin: 12px 0 2px; }
.so-avail-head b { color: var(--text-primary); font-weight: 600; }
.so-avail-sub { margin: 0 0 4px; font-size: 11.5px; }
.so-avail-badge {
  margin-left: auto;
  flex-shrink: 0;
  padding: 3px 9px;
  border-radius: var(--radius-badge);
  font-size: 11.5px;
  font-weight: 600;
  white-space: nowrap;
  color: var(--text-secondary);
  background: var(--surface-inset);
}
.so-avail-badge--warn { background: rgba(var(--warn-rgb), .13); color: var(--warn-strong); }

/* ---- Annahme-Dialog — Lösungs-Cards (§2K/G11) ---- */
.aod-status { margin: 2px 0 0; }
.aod-cards {
  margin: 8px 0 2px;
  border-radius: var(--radius-card);
  background: var(--surface-inset);
  overflow: hidden;
}
.aod-card {
  display: block;
  width: 100%;
  text-align: left;
  padding: 10px 14px;
  background: none;
  border: 0;
  cursor: pointer;
  color: var(--text-primary);
  font: inherit;
}
.aod-card + .aod-card { border-top: 1px solid var(--border); }
.aod-card:hover:not(:disabled):not(.is-on) { background: rgba(var(--tint-rgb), .04); }
.aod-card.is-on {
  background: var(--accent-soft);
  box-shadow: inset 2.5px 0 0 var(--accent); /* Selektions-Idiom, keine Vollborder */
}
.aod-card:disabled { opacity: .55; cursor: not-allowed; }
.aod-card__title { display: block; font-size: 13.5px; font-weight: 600; }
.aod-card__sub { display: block; margin-top: 2px; font-size: 12px; color: var(--text-secondary); }
.aod-card__rows { display: flex; flex-direction: column; gap: 2px; margin-top: 6px; font-size: 12px; color: var(--text-secondary); }
.aod-editor-cta { margin: 8px 0 0; display: flex; justify-content: flex-end; }

/* ---- Belegungs-Heatmap (§2K, components/availability-heatmap.js) ---- */
.avh { display: grid; gap: 10px; }
.avh__head { display: flex; align-items: center; justify-content: center; gap: 8px; }
.avh__month { font-size: 14px; font-weight: 600; min-width: 140px; text-align: center; font-variant-numeric: tabular-nums; }
.avh__nav--prev svg { transform: scaleX(-1); }
.avh__weekdays, .avh__grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 4px; }
.avh__wd { text-align: center; font-size: 11px; color: var(--text-secondary); }
.avh__day { appearance: none; border: 0; background: transparent; border-radius: var(--radius-card); padding: 6px 2px 5px; display: grid; gap: 3px; justify-items: center; align-content: center; color: var(--text); font: inherit; min-height: 46px; }
.avh__day:not(:disabled) { cursor: pointer; }
.avh__day:not(:disabled):hover { box-shadow: inset 0 0 0 1px var(--border); }
.avh__num { font-size: 11px; line-height: 1; color: var(--text-secondary); }
.avh__free { font-size: 12.5px; font-weight: 600; line-height: 1; font-variant-numeric: tabular-nums; }
.avh__cap { color: var(--text-secondary); font-weight: 500; }
.avh__day.is-load-1 { background: rgba(var(--tint-rgb), .05); }
.avh__day.is-load-2 { background: rgba(var(--tint-rgb), .10); }
.avh__day.is-load-3 { background: rgba(var(--tint-rgb), .16); }
.avh__day.is-load-4 { background: rgba(var(--tint-rgb), .24); }
.avh__day.is-closed, .avh__day.is-nocap { opacity: .45; }
.avh__day.is-past { opacity: .55; }
.avh__day.is-under .avh__free { color: var(--bad-strong); }
.avh__day.is-today, .avh__day.is-today:not(:disabled):hover { box-shadow: inset 0 0 0 1px var(--accent); }
.avh-rows { display: grid; }
.avh-row { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; padding: 8px 0; border-top: 1px solid var(--border); flex-wrap: wrap; }
.avh-row:first-child { border-top: 0; padding-top: 0; }
.avh-row.is-expired { opacity: .5; }
.avh-row__main { display: grid; gap: 2px; min-width: 0; }
.avh-row__meta { font-size: 12px; color: var(--text-secondary); }
.avh-form { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; margin-top: 4px; }
.avh-form .field--wide, .avh-form .modal-actions, .avh-form .avh-error { grid-column: 1 / -1; }
.avh-error { margin: 0; font-size: 12.5px; color: var(--bad-strong); }

/* ---- Verzugs-Ampel (§7C), Renewal (§2N-2), Guthaben (§7D) ----
   Stufe 1/3 nutzen bestehende sl-badge--pipeline/--storniert; nur Stufe 2
   (orange) ist neu (Alpha-Fläche + Strong-Text). */
.verzug-badge--2 { background: rgba(249, 115, 22, .16); color: var(--warn-strong); }
.credit-row--applied { opacity: .55; }
.credit-form { display:grid; grid-template-columns:minmax(140px,200px) minmax(0,1fr); gap:12px; align-items:start; margin-top:14px; }
.credit-form .field { min-width:0; }
.credit-form>.lx-lesung__summe { grid-column:1/-1; margin:0; min-width:0; }
.credit-form button[type="submit"] { grid-column:1/-1; justify-self:var(--credit-submit-align,start); }
.credit-apply { display: flex; gap: 8px; align-items: flex-end; flex-wrap: wrap; margin-top: 6px; }
.credit-apply .field { flex: 1 1 180px; }

/* ---- Inventar Konflikt-Queue (§2E/§7G — admin-only View) ---- */
.conflict-bookings { margin-top: 6px; font-size: 12.5px; color: var(--text-secondary); }
.conflict-bookings span { display: block; }
.conflict-credit { padding-top: 12px; border-top: 1px solid var(--border); }

/* ---- I2 Mobile NACH der Basis ---- */
@media (max-width: 720px) {
  .aod-card { padding: 12px; }
  .avh__weekdays, .avh__grid { gap: 2px; }
  .avh__day { padding: 5px 1px 4px; min-height: 42px; }
  .avh__free { font-size: 11.5px; }
  .avh-form { grid-template-columns: 1fr; }
  .credit-form { grid-template-columns:minmax(0,1fr); --credit-submit-align:stretch; }
  .credit-apply { flex-direction:column; align-items:stretch; }
  .credit-form .field, .credit-apply .field { flex:0 0 auto; min-width:0; width:100%; }
  .credit-apply>* { flex:0 0 auto; }
}
@media (max-width: 400px) {
  .avh__cap { display: none; } /* «frei/cap» → nur «frei» auf sehr schmal */
}
/* ---- I2 Touch-Floor ---- */
@media (max-width: 1024px), (pointer: coarse) {
  .aod-card { min-height: 44px; }
  .avh__day:not(:disabled) { min-height: 44px; }
  .avh__nav { min-width: 44px; min-height: 44px; }
  .credit-form button, .credit-apply button { min-height: 44px; }
}

/* Iter 31 M4 — Fällig-Zähler auf der «Mein Tag»-Tür (updateTaskBadge, main.js).
   DESIGN.md: kleine Pill, kein Border, Warn-Ton für Dringlichkeit; ans
   Dateiende (nach allen Basis-/@media-Regeln — Cascade-Kanon). */
.nav-tab { position: relative; }
.nav-tab__badge {
  margin-left: auto;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-card);
  background: var(--bad);
  color: #fff;
  font-size: 11px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  line-height: 1;
  flex: 0 0 auto;
}
/* Eingeklappte Sidebar: Label ausgeblendet → Zähler als Punkt oben rechts am Icon. */
.sidebar-collapsed .nav-tab__badge {
  position: absolute;
  top: 4px;
  right: 4px;
  margin: 0;
  min-width: 16px;
  height: 16px;
  padding: 0 4px;
}

/* Entity-Link (Iter 32 «Verzahnung»): jede Kunden-/Partner-Erwähnung im Modul ist
   navigierbar, aber dezent — liest sich als Text mit feiner Hairline-Unterstreichung,
   Cyan (= Interaktion, DESIGN.md §3) nur bei Hover/Fokus. Kein Farb-Rauschen. */
/* `min-width` seit 28.08.2026: ein Link, der nur eine ZIFFER traegt, mass auf
   /v/material 9.1 px breit («2 aktive Spots»). Die Hoehe hielt der Touch-Block
   weiter unten laengst — die Breite hat nie jemand gemessen, weil die Flaeche
   in keiner Messliste stand. `position: relative` traegt die Fangflaeche der
   naechsten Regel. Die Mindestbreite steht bewusst NICHT hier: diese Regel
   steht in der Datei NACH dem Touch-Block, haette dessen 44 px also still
   geschlagen — der Kaskaden-Fallstrick, den dieses Haus schon zweimal bezahlt
   hat (Memory project_css_cascade_mobile). Sie sitzt im Kaestchen. */
.entity-link {
  position: relative;
  color: inherit;
  text-decoration: underline;
  text-decoration-color: var(--hairline-strong, var(--hairline));
  text-underline-offset: 2px;
  text-decoration-thickness: 1px;
  border-radius: 3px;
  transition: color var(--dur-fast, .12s) var(--ease, ease), text-decoration-color var(--dur-fast, .12s) var(--ease, ease);
}
.entity-link:hover,
.entity-link:focus-visible {
  color: var(--accent);
  text-decoration-color: var(--accent);
}
.entity-link:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* Iter 30 N1 — Werbematerial-Panel (Kunden-Detail + Freigabe-Queue).
   Ans Ende gesetzt, damit keine frühere @media-Regel überschreibt
   (project_css_cascade_mobile). Nutzt Precision-Ink-Tokens. */
.material-panel {
  border: 1px solid var(--hairline);
  border-radius: var(--radius-card);
  padding: 12px 14px;
  background: var(--panel-2);
}
.material-panel__head {
  display: flex;
  gap: 10px;
  align-items: baseline;
  flex-wrap: wrap;
}
.material-panel__hint {
  font-size: 12px;
  color: var(--text-tertiary);
}
.material-panel__note {
  margin: 8px 0 0;
  font-size: 12.5px;
  color: var(--warn-strong);
}
.material-panel__files {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin: 10px 0;
}
.material-file {
  display: flex;
  align-items: center;
  gap: 8px;
  border: 1px solid var(--hairline);
  border-radius: var(--radius-card);
  padding: 6px 10px;
}
.material-file__open {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 1px;
  background: none;
  border: none;
  cursor: pointer;
  text-align: left;
  color: var(--text);
  padding: 0;
}
.material-file__open strong {
  font-size: 13px;
  font-weight: 500;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 100%;
}
.material-file__open span {
  font-size: 11.5px;
  color: var(--text-tertiary);
}
.material-file__open:hover strong {
  color: var(--accent);
}
.material-file__del {
  flex: none;
  font-size: 13px;
  line-height: 1;
}
.material-panel__actions {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  align-items: center;
}
.material-panel__upload {
  cursor: pointer;
}
.material-row > td {
  padding: 0 12px 12px;
  background: var(--panel-2);
}

/* §7f — Blick-Führung für breite Tabellen (Owner-Wunsch «smooth & smart»).
   Auf grossen Screens (2560/3440) nutzen Tabellen die volle Breite (Owner-Entscheid
   style.css:190) → langer Augen-Weg Name→Zahl. NICHT mit Content-Cap bekämpft
   (v73-Regression), sondern GEFÜHRT: (1) subtile Zebra = statische Schiene je Zeile,
   (2) smoother Hover mit Accent-Anker links (Lead-Row-Muster) trägt den Blick von
   links nach rechts. Precision Ink: sehr dezent, Chrome verschwindet, Daten Held.
   Ans Ende gesetzt (Cascade-Regel project_css_cascade_mobile). */
.sl-table tbody tr { transition: background var(--dur-fast, 120ms) ease; }
.sl-table tbody tr:nth-child(even) > td { background: rgba(var(--tint-rgb), .032); }
.sl-table tbody tr[data-id]:hover > td,
.sl-table tbody tr[data-ort]:hover > td,
.sl-table tbody tr[data-month]:hover > td,
.sl-table tbody tr[data-expense]:hover > td {
  background: rgba(var(--accent-rgb), .07);
}
.sl-table tbody tr[data-id]:hover > td:first-child,
.sl-table tbody tr[data-ort]:hover > td:first-child,
.sl-table tbody tr[data-month]:hover > td:first-child,
.sl-table tbody tr[data-expense]:hover > td:first-child {
  box-shadow: inset 2px 0 0 var(--accent-hover);
}

/* ---- Kalkulator (#/v/calc, Iter 29 E7) — Gewinn/Verlust-Balken (dataviz:
   eine Serie, Polarität good/bad, aktueller Preis volle Deckkraft) ---- */
.calc-chart {
  display: flex; gap: 10px; align-items: stretch; margin-top: 12px;
  overflow-x: auto; padding-bottom: 4px;
}
.calc-col { flex: 1 1 0; min-width: 44px; text-align: center; }
.calc-col__top, .calc-col__bot { height: 76px; display: flex; justify-content: center; }
.calc-col__top { align-items: flex-end; }
.calc-col__bot { align-items: flex-start; }
.calc-col__base { height: 1px; background: var(--hairline); }
.calc-bar { width: 60%; max-width: 34px; opacity: .45; }
.calc-bar--pos { background: var(--good); border-radius: var(--radius-card) var(--radius-card) 0 0; }
.calc-bar--neg { background: var(--bad); border-radius: 0 0 var(--radius-card) var(--radius-card); }
.calc-bar.is-cur { opacity: 1; }
.calc-col__label {
  margin-top: 6px; font-size: 11.5px; color: var(--text-tertiary);
  font-variant-numeric: tabular-nums;
}
.calc-col__label.is-cur { color: var(--text-primary); font-weight: 650; }

/* ---- Signage-Board (#/v/signage, Iter 34 S1) ---- */
.sig-loop {
  display: flex; gap: 3px; margin-top: 8px; flex-wrap: wrap;
}
.sig-slot {
  width: 22px; height: 8px; border-radius: 3px; flex: 0 0 auto;
}
.sig-slot.is-used { background: var(--accent); }
.sig-slot.is-free { background: rgba(var(--tint-rgb), .16); }
.sig-tag {
  font-size: 11px; padding: 1px 7px; border-radius: var(--radius-badge);
  background: rgba(var(--tint-rgb), .14); color: var(--text-secondary);
  font-variant-numeric: tabular-nums;
}
.sig-screen:first-of-type { border-top: none !important; }

/* ---- Regel-Zentrum (#/a/rules, Iter 46 S3.1) ----
   Regeln sind Sätze, Werte stehen im Satzfluss (Oberflächen-Reinheit).
   Regelwerk-Index = EIN Panel mit Hairline-Rows (DESIGN.md §1). */
.rules-panel { margin-bottom: 16px; }
.rules-actions { display: inline-flex; gap: 8px; }

/* Rechen-Grundlagen (E4/F4): zwei Modellwerte unter EINEM Namen. Die beiden
   inneren Blöcke tragen weiter ihre eigene Überschrift — sie sind
   Unterabschnitte, nicht eigene Kästen; deshalb rücken sie ein und trennen
   sich mit einer Haarlinie statt mit einem zweiten Rahmen. */
.rules-grundlagen__satz {
  margin: 6px 0 10px; max-width: 62ch;
  font-size: 13px; line-height: 1.5; color: var(--text-secondary);
}
.rules-grundlagen__satz em { font-style: italic; color: var(--text-primary); }
.rules-grundlagen > [data-slot] { border-top: 1px solid var(--hairline); padding-top: 4px; }
.rules-grundlagen > [data-slot] .panel__header { padding-left: 0; }
.rules-grundlagen > [data-slot] h3 { font-size: 14px; }
.rules-history__row {
  display: flex; justify-content: space-between; gap: 12px; flex-wrap: wrap;
  padding: 9px 0; font-size: 12.5px; color: var(--text-secondary);
  border-bottom: 1px solid var(--hairline); font-variant-numeric: tabular-nums;
}
.rules-history__row.is-current { color: var(--text-primary); }
.rules-index { display: flex; flex-direction: column; }
.rules-index__row {
  display: flex; align-items: center; gap: 12px; min-height: 56px;
  padding: 8px 2px; text-decoration: none; color: inherit;
  border-bottom: 1px solid var(--hairline);
}
.rules-index__row:last-child { border-bottom: none; }
.rules-index__row:hover { background: var(--surface-3); }
.rules-index__text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.rules-index__text strong { font-size: 14px; font-weight: 600; }
.rules-index__text small { font-size: 12px; color: var(--text-tertiary); }
.rules-index__chevron { display: inline-flex; color: var(--text-tertiary); flex: 0 0 auto; }

/* ---- Vertriebs-Konfigurator (#/p/vertriebe, Iter 47 S4.1) ----
   Liste = EIN Panel mit Hairline-Rows; Vereinbarung als Satz mit Werten
   im Satzfluss (gleiches Idiom wie das Regel-Zentrum). */
.vt-row { padding: 10px 2px; border-bottom: 1px solid var(--hairline); }
.vt-row:last-child { border-bottom: none; }
.vt-row.is-inactive { opacity: .55; }
.vt-row__main {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  min-height: 48px; justify-content: space-between;
}
.vt-row__text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.vt-row__text strong { font-size: 14px; font-weight: 600; }
/* S4.3: KEIN tabular-nums auf dieser Zeile — sie ist Fliesstext («Vertriebs-
   Berater · rita@… · Erhält 9 % · seit 01.03.2026») und richtet sich an nichts
   aus. Inter gibt dem Bindestrich unter tabular-nums die volle Ziffernbreite,
   was «Vertriebs - Berater» aussehen liess. Tabellenziffern bleiben dort, wo
   Spalten untereinander stehen (Beträge in .vt-row__actions). */
.vt-row__text small { font-size: 12px; color: var(--text-tertiary); }
.vt-row__actions { display: inline-flex; align-items: center; gap: 8px; flex: 0 0 auto; flex-wrap: wrap; min-width: 0; max-width: 100%; }
.vt-row__actions .sl-badge { max-width: 100%; white-space: normal; overflow-wrap: anywhere; }
/* .field bringt min-width:150px mit — für den nackten Aktiv-Schalter in der
   Row ist das Überlauf-Ursache @390px (gemessen: right=557). */
.vt-row__actions .field--check { min-width: 0; width: auto; }
.vt-agree {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 10px 0 4px; font-size: 14px; line-height: 1.6;
}
.vt-agree[hidden] { display: none; }
.vt-agree__sentence { display: inline-flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.vt-agree input[data-f="von"] { min-height: 44px; }
.vt-agree input[data-f="pct"] { width: 88px; min-height: 44px; text-align: center; font-variant-numeric: tabular-nums; }
.vt-history { padding: 6px 0 2px; }
/* S4.2b Vertriebs-Portal: Klartext-Satz über dem Provisions-Stand. */
.vt-portal__satz { margin: 0 0 14px; font-size: 14px; color: var(--text-secondary); }
/* S4.3: erklärender Satz im Anlege-Formular; Zugangs-Schalter mit Beschriftung
   (ein nackter Kasten sagt nicht, was er tut). */
.vt-portal__hint { flex-basis: 100%; margin: 4px 0 0; font-size: 13px; color: var(--text-tertiary); line-height: 1.5; }
.vt-row__switch { display: inline-flex; align-items: center; gap: 6px; }
.vt-row__switch span { font-size: 12px; color: var(--text-tertiary); }

/* ---- Zwei-Schritt-Anmeldung (#/enroll-2fa + #/verify-2fa, Iter 49) ----
   09.08.2026 (Video-Audit B34): Der QR-Code war der EINZIGE sichtbare Weg,
   der Schlüssel lag zugeklappt in einem <details> ohne Kopierknopf. Wer sich
   am Handy anmeldet, kann den eigenen Bildschirm nicht abscannen — der Owner
   musste den Code von einem zweiten Bildschirm abfilmen. Seither trägt die
   Fläche zwei gleichwertige Wege nebeneinander; welcher oben steht, entscheidet
   views/mfa.js am echten DOM (nicht per `order:` — sonst läuft das
   Vorleseprogramm die andere Reihenfolge als das Auge). */
.mfa-wege { display: flex; flex-direction: column; gap: 20px; margin: 14px 0 18px; }
.mfa-weg { display: flex; flex-direction: column; gap: 10px; }
.mfa-weg__titel {
  margin: 0; font-size: 11px; font-weight: 600; letter-spacing: .08em;
  text-transform: uppercase; color: var(--text-tertiary);
}
.mfa-weg__satz { margin: 0; font-size: 13px; line-height: 1.55; color: var(--text-secondary); }
.mfa-weg__oeffnen { width: 100%; }
.mfa-qr { display: flex; justify-content: center; margin: 0; }
.mfa-qr svg, .mfa-qr img {
  width: 196px; height: 196px; border-radius: var(--radius-card); background: #fff; padding: 8px;
}
.mfa-schluessel { display: flex; flex-direction: column; gap: 8px; }
/* Der Schlüssel steht in Vierergruppen und darf umbrechen — `break-all` riss
   die Gruppen mitten entzwei und machte das Abtippen wieder zur Zumutung. */
.mfa-schluessel code {
  display: block; padding: 12px; border-radius: var(--radius-card); background: var(--surface-inset);
  font-family: var(--font-mono, monospace); font-size: 15px; letter-spacing: .1em;
  line-height: 1.6; text-align: center; color: var(--text);
  overflow-wrap: break-word; user-select: all; -webkit-user-select: all;
}
.mfa-schluessel .ghost-btn { width: 100%; min-height: 44px; }
/* Am Handy ist der QR der ZWEITE Weg — in voller Grösse schob er das
   Bestätigungsfeld unter den Bildschirmrand. 156px reichen jeder Kamera
   (ein QR dieser Länge hat ~29 Module, also gut 5px je Modul). */
@media (max-width: 720px), (pointer: coarse) {
  .mfa-qr svg, .mfa-qr img { width: 156px; height: 156px; }
}

/* =========================================================================
   Kundenportal (Iter 54 / S5.3) — die Aussenwelt-Sicht.
   Reihenfolge eisern (Memory project_css_cascade_mobile): Basis zuerst, der
   Touch-/Mobile-Block DANACH — sonst greift der Override für eine später
   definierte Komponente nicht.
   ========================================================================= */
.kp-count { color: var(--text-tertiary); font-size: 12px; font-variant-numeric: tabular-nums; }

.kp-search { flex: 1 1 220px; min-width: 0; }
.kp-kanton { flex: 0 0 auto; width: auto; min-width: 140px; }

/* Liste = EIN Panel mit Hairline-Zeilen, nicht N gerahmte Karten (DESIGN §1).
   Deckel + Innen-Scroll, damit 199 Standorte die Seite nicht zur Endlosrolle
   machen (DESIGN §7: >12'000px iPhone ist ein Defekt). */
.kp-liste { max-height: min(56vh, 520px); overflow-y: auto; margin: 0 -4px; }
.kp-row {
  display: grid; align-items: center; gap: 4px 12px; cursor: pointer;
  grid-template-columns: 20px minmax(0, 1.4fr) minmax(0, 1fr) auto auto;
  padding: 10px 12px; border-bottom: 1px solid var(--hairline);
  border-radius: var(--radius-button); transition: background var(--dur);
}
.kp-row:last-child { border-bottom: 0; }
.kp-row:hover { background: var(--surface-3); }
/* Selektion = Inset-Balken + Tint, nie Vollborder (DESIGN Verbote). */
.kp-row.is-on { background: var(--accent-soft); box-shadow: inset 2.5px 0 0 var(--accent); }
.kp-row input[type="checkbox"] { width: 18px; height: 18px; accent-color: var(--accent); margin: 0; }
.kp-row__name { font-weight: 600; font-size: 14px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.kp-row__ort { color: var(--text-secondary); font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.kp-row__screens { color: var(--text-tertiary); font-size: 12px; font-variant-numeric: tabular-nums; white-space: nowrap; }
.kp-row__grenze {
  font-size: 11px; font-weight: 600; white-space: nowrap;
  color: var(--warn-strong);
}

.kp-seg { flex-wrap: wrap; }
.kp-hint { color: var(--text-tertiary); font-size: 11px; line-height: 1.45; }

.kp-abschluss { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 16px; }
.kp-pruefen { margin-top: 16px; padding-top: 16px; border-top: 1px solid var(--hairline); }
.kp-pruefen__satz { font-size: 15px; font-weight: 600; line-height: 1.5; margin: 0; }
.kp-ok__text { color: var(--text-secondary); font-size: 14px; line-height: 1.5; margin: 4px 0 16px; }

.kp-buchung + .kp-buchung { margin-top: 16px; }
.kp-orte { margin-top: 16px; }
.kp-orte__row {
  display: grid; align-items: center; gap: 4px 12px;
  grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr) auto;
  padding: 9px 0; border-bottom: 1px solid var(--hairline);
}
.kp-orte__row:last-child { border-bottom: 0; }
.kp-orte__zeit { font-size: 13px; color: var(--text-secondary); font-variant-numeric: tabular-nums; white-space: nowrap; }

.kp-rechnung { margin-top: 16px; padding-top: 12px; border-top: 1px solid var(--hairline-strong); }
.kp-rechnung__kopf { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
/* Zahlungsangaben: der Einzahlungsschein des Kunden — Referenz und IBAN
   müssen abtippbar sein, also Mono + selektierbar. */
.kp-zahl { display: grid; grid-template-columns: auto 1fr; gap: 4px 16px; margin: 10px 0 0; }
.kp-zahl dt { color: var(--text-tertiary); font-size: 11px; font-weight: 600;
  text-transform: uppercase; letter-spacing: .06em; align-self: center; }
.kp-zahl dd { margin: 0; font-size: 13px; }
.kp-zahl__mono { font-family: var(--font-mono, monospace); letter-spacing: .04em;
  user-select: all; word-break: break-all; }

/* Touch-Floor (Memory project_tablet_touch_breakpoint): auch die Tablet-
   Bruchzone 768/1024 trifft, nicht nur 720. */
@media (max-width: 1024px), (pointer: coarse) {
  .kp-row { min-height: 52px; padding: 12px; grid-template-columns: 44px minmax(0, 1.4fr) minmax(0, 1fr) auto auto; }
  /* Das Kästchen bleibt 22 px gross — der DAUMEN bekommt 44 (E1d-Kleinteil,
     Rundgang 08.08.: «Pool-Checkboxen am Touch 22px»). Die Tapfläche kommt
     aus einem Pseudo-Element des Kästchens selbst: Treffer darauf zählen für
     das Kästchen, und weil die Spalte hier 44 px breit ist, greift sie nie
     in den Namen daneben. Die Marke (`::after`) bleibt unberührt. */
  .kp-row input[type="checkbox"] { width: 22px; height: 22px; position: relative; justify-self: center; }
  .kp-row input[type="checkbox"]::before {
    content: ''; position: absolute; left: 50%; top: 50%;
    width: 44px; height: 44px; transform: translate(-50%, -50%);
  }
  .kp-seg .seg__btn { min-height: 44px; }
  .kp-abschluss .primary-btn, .kp-abschluss .ghost-btn { min-height: 44px; }
}
/* 390px: die Zeile bricht in zwei Ebenen statt fünf Spalten zu quetschen —
   Name oben, Ort + Zahlen darunter (sonst fällt Text unter den 11px-Floor). */
@media (max-width: 720px) {
  .kp-row {
    grid-template-columns: 44px minmax(0, 1fr);
    grid-template-areas: "cb name" ". meta";
  }
  .kp-row input[type="checkbox"] { grid-area: cb; }
  .kp-row__name { grid-area: name; white-space: normal; }
  .kp-row__ort { grid-area: meta; }
  .kp-row__screens, .kp-row__grenze { grid-column: 2; }
  .kp-liste { max-height: none; }
  .kp-orte__row { grid-template-columns: minmax(0, 1fr); }
  .kp-zahl { grid-template-columns: minmax(0, 1fr); gap: 2px; }
  .kp-zahl dd { margin-bottom: 8px; }
}

/* B-02 — gerätegebundener App-Lock. Die laufende Arbeitsfläche bleibt unter
   einer echten modalen Sperre im DOM, damit nach Unlock exakt derselbe View-
   Zustand weiterlebt. */
.app-is-locked { overflow: hidden !important; }
.app-lock {
  position: fixed; inset: 0; z-index: 100000;
  display: grid; place-items: center; padding: 24px;
  background:
    radial-gradient(circle at 50% 22%, rgba(var(--accent-rgb), .15), transparent 38%),
    rgba(5, 9, 12, .96);
  backdrop-filter: blur(18px);
}
.app-lock[hidden] { display: none; }
.app-lock__card {
  width: min(100%, 430px); display: grid; gap: 18px;
  padding: 30px; border: 1px solid var(--hairline-strong);
  border-radius: var(--radius-card); background: var(--surface-1);
  box-shadow: 0 28px 90px rgba(0, 0, 0, .46);
}
.app-lock__mark {
  width: 38px; height: 38px; border: 3px solid var(--accent);
  border-radius: 50%; position: relative;
}
.app-lock__mark::after {
  content: ''; position: absolute; width: 8px; height: 8px;
  inset: 50% auto auto 50%; border-radius: 50%; background: var(--accent);
  transform: translate(-50%, -50%);
}
.app-lock__eyebrow {
  margin: 0 0 5px; color: var(--accent); font-size: 11px;
  font-weight: 700; letter-spacing: .1em; text-transform: uppercase;
}
.app-lock h1 { margin: 0; font-size: 28px; }
.app-lock h1 + p { margin: 8px 0 0; color: var(--text-secondary); line-height: 1.55; }
.app-lock__draft, .app-lock__error {
  margin: 0; padding: 10px 12px; border-radius: var(--radius-card);
  color: var(--bad-strong); background: var(--bad-soft);
  font-size: 13px; line-height: 1.45;
}
.app-lock__card > button { width: 100%; min-height: 44px; }

@media (max-width: 520px) {
  .app-lock { padding: 14px; align-items: end; }
  .app-lock__card { padding: 24px 20px; border-radius: var(--radius-card) var(--radius-card) var(--radius-card) var(--radius-card); }
}

/* ---------------------------------------------------------------------------
   G-01 · «Was ansteht» — Benachrichtigungen und Eskalationen
   Kein Glocken-Symbol und kein roter Punkt: das Werkzeug schreit nicht, es
   sagt, was faellig ist. Der Zaehler erscheint nur, wenn wirklich etwas offen
   ist (Projektregel «Werkzeug erklaert sich nicht, es zeigt Funktion»).
--------------------------------------------------------------------------- */
/* 44px Tapflaeche — der geerbte Suchleisten-Stil brachte nur 37px
   (Projektregel feedback_mobile_pwa_mandatory, im UI-Test gemessen). */
.sidebar__bell { position: relative; min-height: 44px; }
.lx-bell__count {
  margin-left: auto;
  min-width: 20px;
  padding: 1px 6px;
  border-radius: 999px;
  background: var(--accent);
  color: var(--on-accent);
  font-size: 11px;
  font-weight: 700;
  text-align: center;
  line-height: 18px;
}
/* 10px -> 11px am 22.08.2026, Schrift-Boden (DESIGN.md §2). Die Zwillingsregel
   `.lx-top .lx-bell__count` steht seit dem 21.08. auf 11px — zwei Groessen fuer
   dieselbe Zahl waeren zwei Wahrheiten. Geometrie bleibt: 16px Zeilenhoehe
   traegt 11px Text, und die Pille sitzt weiter am selben Punkt ueber dem
   Zeichen. */
.sidebar.is-collapsed .lx-bell__count {
  position: absolute; top: 4px; right: 4px; margin: 0; min-width: 16px;
  padding: 0 4px; font-size: 11px; line-height: 16px;
}
.lx-bell-panel {
  position: fixed;
  z-index: 60;
  width: min(360px, calc(100vw - 24px));
  max-height: min(60vh, 520px);
  overflow-y: auto;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  box-shadow: 0 18px 50px -20px rgba(0, 0, 0, 0.8);
  padding: 6px;
}
.lx-bell-panel__head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px; padding: 8px 10px 10px;
}
.lx-bell-panel__all {
  background: none; border: 0; color: var(--muted);
  font-size: 12px; cursor: pointer; padding: 4px 6px; border-radius: var(--radius-card);
}
.lx-bell-panel__all:hover { color: var(--text); background: var(--hover); }
.lx-bell-panel__leer { color: var(--muted); font-size: 13px; padding: 6px 10px 12px; margin: 0; }
.lx-bell-row {
  display: flex; align-items: flex-start; gap: 10px; width: 100%;
  /* 44px Tapflaeche — Projektregel feedback_mobile_pwa_mandatory */
  min-height: 44px;
  padding: 9px 10px; border: 0; border-radius: var(--radius-card);
  background: none; color: inherit; text-align: left; cursor: pointer;
}
.lx-bell-row:hover { background: var(--hover); }
.lx-bell-row__mark {
  flex: 0 0 auto; width: 6px; height: 6px; margin-top: 7px; border-radius: 50%;
  background: var(--accent);
}
.lx-bell-row.is-read .lx-bell-row__mark { background: var(--line); }
.lx-bell-row__body { flex: 1 1 auto; min-width: 0; }
.lx-bell-row__title { display: block; font-size: 13.5px; font-weight: 600; }
.lx-bell-row.is-read .lx-bell-row__title { font-weight: 400; color: var(--muted); }
.lx-bell-row__meta { display: block; font-size: 12px; color: var(--muted); margin-top: 1px; }
.lx-bell-row__age { flex: 0 0 auto; font-size: 11px; color: var(--muted); margin-top: 2px; }
/* 25.08. — die Wand wird gebündelt (Klasse C, Muster patch-eskalationen.css):
   gleiche Regeln ab drei als EINE Sammelzeile, Einzelzeilen aufklappbar.
   Dieselbe Zeilen-Bauart, nur als <summary>. */
.lx-bell-buendel > summary { list-style: none; }
.lx-bell-buendel > summary::-webkit-details-marker { display: none; }
.lx-bell-row--buendel .lx-bell-row__title::before {
  content: '▸ '; color: var(--muted); font-size: 11px;
}
.lx-bell-buendel[open] .lx-bell-row--buendel .lx-bell-row__title::before {
  content: '▾ ';
}
.lx-bell-row--innen { padding-left: 26px; }

/* ---------------------------------------------------------------------------
   G-01 · Freigabe-Streifen. Erscheint NUR, wenn eine Offerte eine vom Owner
   gesetzte Schwelle reisst — sonst ist er nicht im Weg.
--------------------------------------------------------------------------- */
.lx-approval {
  display: flex; align-items: center; justify-content: space-between;
  gap: 16px; flex-wrap: wrap;
  margin: 0 0 14px; padding: 12px 14px;
  border-radius: var(--radius-card);
  border: 1px solid var(--border);
  background: var(--panel);
}
.lx-approval.is-wait { border-color: var(--warn); }
.lx-approval.is-ok   { border-color: var(--good); }
.lx-approval.is-no   { border-color: var(--bad); }
.lx-approval__body { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.lx-approval__body strong { font-size: 14px; }
.lx-approval__body span { font-size: 12.5px; color: var(--muted); }
.lx-approval__meta { font-size: 11.5px; }
.lx-approval__act { display: flex; gap: 8px; flex-wrap: wrap; }
.lx-approval__act button { min-height: 44px; }

/* ---------------------------------------------------------------------------
   G-01 · Die REGEL-Seite derselben Sache: wann braucht es ueberhaupt eine
   Freigabe. Sitzt im Regel-Bildschirm, nicht an der Offerte.
   Precision Ink: EIN Panel mit Zeilen und Hairline dazwischen — keine N
   gerahmten Karten (DESIGN.md §1).
--------------------------------------------------------------------------- */
.lx-approval-rules { display: flex; flex-direction: column; }
.lx-approval-rules__leer { color: var(--muted); font-size: 13px; margin: 4px 0 0; }

/* ---------------------------------------------------------------------------
   E4/R17 · Versionsliste (components/versionen.js) — EIN Baustein für das
   Regel-Zentrum und den Gesprächsleitfaden. Vorher zeichnete jede Fläche ihre
   eigene Liste mit eigenen Abständen; hier steht sie einmal.
   Precision Ink: Zeilen mit Haarlinie, kein Kartenstapel (DESIGN.md §1).
--------------------------------------------------------------------------- */
.lx-versionen { display: flex; flex-direction: column; margin-top: 8px; }
.lx-versionen__row {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; flex-wrap: wrap;
  padding: 10px 0; border-top: 1px solid var(--border);
}
.lx-versionen__wort { display: flex; align-items: center; flex-wrap: wrap; gap: 4px 8px; min-width: 0; }
.lx-versionen__wort small {
  flex: 1 1 100%; color: var(--text-secondary); font-size: 12px;
  font-variant-numeric: tabular-nums;
}
.lx-versionen__hinweis { color: var(--text-secondary); font-size: 12px; }
.lx-versionen__verlauf { margin-top: 12px; display: grid; gap: 6px; }
.lx-versionen__verlauf small { color: var(--text-secondary); }

/* E4/R17 · Der Satz unter der Standard-Frist: welche Zahl wirklich gilt.
   Er steht bewusst unter dem Feld und nicht daneben — er ist eine Folge der
   Eingabe, keine zweite Beschriftung. */
.lx-frist-heimat {
  margin: 6px 0 14px; max-width: 460px;
  font-size: 12.5px; line-height: 1.5; color: var(--text-secondary);
}
.lx-frist-heimat a { margin-left: 6px; white-space: nowrap; }

.lx-approval-rules__row {
  display: flex; align-items: center; justify-content: space-between;
  gap: 16px; flex-wrap: wrap;
  padding: 14px 0;
}
.lx-approval-rules__row + .lx-approval-rules__row {
  border-top: 1px solid var(--border);
}

.lx-approval-rules__an {
  display: flex; align-items: center; gap: 12px;
  flex: 1 1 260px; min-width: 0; cursor: pointer;
}
.lx-approval-rules__an input { flex: 0 0 auto; width: 18px; height: 18px; cursor: pointer; }
.lx-approval-rules__an > span { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.lx-approval-rules__an strong { font-size: 14px; font-weight: 600; }
.lx-approval-rules__an small { font-size: 12px; color: var(--muted); }
.lx-approval-rules__an input:disabled { cursor: default; }
.lx-approval-rules__an:has(input:disabled) { cursor: default; }

.lx-approval-rules__wert { display: flex; align-items: center; gap: 8px; flex: 0 0 auto; }
.lx-approval-rules__wert input {
  width: 104px; min-height: 36px; padding: 6px 10px;
  border-radius: var(--radius-card);
  border: 1px solid var(--border);
  background: var(--surface-inset);
  color: inherit; font-size: 14px;
  font-variant-numeric: tabular-nums; text-align: right;
}
.lx-approval-rules__wert input:focus-visible {
  outline: 2px solid var(--accent); outline-offset: 1px;
}
.lx-approval-rules__wert input:disabled { opacity: .6; }
.lx-approval-rules__wert > span {
  font-size: 12px; color: var(--muted); min-width: 26px;
}

/* Touch-Boden: gilt auch in der Tablet-Bruchzone (Iter-15-E3-Lehre). */
@media (max-width: 1024px), (pointer: coarse) {
  .lx-approval-rules__wert input,
  .lx-approval-rules__wert button { min-height: 44px; }
  .lx-approval-rules__an input { width: 22px; height: 22px; }
}
@media (max-width: 560px) {
  .lx-approval-rules__row { align-items: flex-start; }
  .lx-approval-rules__wert { flex: 1 1 100%; }
  .lx-approval-rules__wert input { flex: 1 1 auto; width: auto; }
}

/* ---------------------------------------------------------------------------
   G-01 · Schaltbare Regeln (Hinweise · Freigaben · Statuswechsel · Auswertungen)
   Ein Ort, eine Zeile je Regel, Klartext statt Schlüssel. Alles AUS
   ausgeliefert — eine Regel wirkt erst, wenn sie hier eingeschaltet wird.
--------------------------------------------------------------------------- */
.lx-policy__stand { color: var(--muted); font-size: 13px; margin: 0 0 16px; }
.lx-policy__gruppe { margin-bottom: 22px; }
.lx-policy__gruppe h3 { margin: 0 0 2px; font-size: 14.5px; }
.lx-policy__erklaerung { color: var(--muted); font-size: 12.5px; margin: 0 0 10px; }
.lx-policy__row {
  display: flex; align-items: center; justify-content: space-between;
  gap: 14px; padding: 10px 0;
  border-top: 1px solid var(--line);
}
.lx-policy__body { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.lx-policy__titel { font-size: 13.5px; }
.lx-policy__detail { font-size: 12px; color: var(--muted); }
.lx-policy__switch, .lx-policy__ro {
  flex: 0 0 auto; min-width: 74px; min-height: 44px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: var(--radius-card); font-size: 13px; font-weight: 600;
  border: 1px solid var(--line);
  background: none; color: var(--muted); cursor: pointer;
}
.lx-policy__ro { cursor: default; }
.lx-policy__row.is-on .lx-policy__switch,
.lx-policy__row.is-on .lx-policy__ro {
  border-color: var(--accent-line); color: var(--accent-strong);
}
.lx-policy__switch:disabled { opacity: 0.5; cursor: wait; }
.lx-policy__wert { display: inline-flex; align-items: center; gap: 6px; flex: 0 0 auto; }
.lx-policy__num {
  width: 78px; min-height: 44px; padding: 0 8px; text-align: right;
  border-radius: var(--radius-card); border: 1px solid var(--line);
  background: var(--bg); color: inherit; font-size: 13.5px;
}
.lx-policy__save {
  min-height: 44px; padding: 0 12px; border-radius: var(--radius-card); font-size: 13px;
  border: 1px solid var(--line); background: none;
  color: var(--muted); cursor: pointer;
}
.lx-policy__save:disabled { opacity: 0.5; cursor: wait; }
/* Eskalationsfrist (04.08.): ausgewaehlt statt getippt — gleiche Hoehe und
   Kante wie das Zahlenfeld daneben, nur breiter (der Text steht drin). */
/* Die Eskalationsfrist ist am 11.08. in den Abschnitt «Wenn etwas liegen
   bleibt» ausgezogen (W11.6) — mit ihr die Regeln .lx-policy__esk und
   .lx-policy__save-esk. Die neue Form steht bei .lx-eskal am Dateiende. */

/* Regelwerkstatt: «+ Neue Regel» je Bereich, eigene Regeln löschbar. */
.lx-policy__gruppe h3 { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.lx-policy__add, .lx-policy__del {
  min-height: 44px; padding: 0 12px; border-radius: var(--radius-card); font-size: 13px; font-weight: 600;
  border: 1px solid var(--line); background: none;
  color: var(--muted); cursor: pointer; flex: 0 0 auto;
}
.lx-policy__add:hover, .lx-policy__del:hover { color: var(--text); }
.lx-policy__neu {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 12px; margin: 6px 0 14px; padding: 14px;
  border: 1px solid var(--line); border-radius: var(--radius-card);
}
.lx-policy__neu label { display: flex; flex-direction: column; gap: 4px; font-size: 12.5px; color: var(--muted); }
.lx-policy__neu input, .lx-policy__neu select {
  min-height: 44px; padding: 0 10px; border-radius: var(--radius-card); font-size: 13.5px;
  border: 1px solid var(--line); background: var(--bg); color: var(--text);
}
.lx-policy__neu fieldset {
  border: 1px solid var(--line); border-radius: var(--radius-card); padding: 8px 10px;
  display: flex; flex-wrap: wrap; gap: 10px;
}
.lx-policy__neu legend { font-size: 12px; color: var(--muted); padding: 0 4px; }
.lx-policy__chk { flex-direction: row !important; align-items: center; gap: 6px; min-height: 44px; }
.lx-policy__neu-act { grid-column: 1 / -1; display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.lx-policy__neu-act button { min-height: 44px; }
.lx-policy__neu-fehler { color: var(--bad-strong); font-size: 12.5px; }

/* E-02 · Textbausteine der Dokumente im Regel-Bildschirm. Ein Textfeld statt
   einer Zahl; die Zeile bricht um, damit lange Klauseln lesbar bleiben.
   Eigener @media-Block NACH den Basisregeln — ein frueherer Block wuerde die
   spaeter definierte Komponente nicht erreichen (Iter-15-Lehre). */
.lx-policy__text { display: flex; flex-direction: column; gap: 6px; flex: 1 1 100%; min-width: 0; }
.lx-policy__ta {
  width: 100%; min-height: 64px; resize: vertical;
  font: inherit; line-height: 1.45; padding: 8px 10px;
  border: 1px solid var(--line); border-radius: var(--radius-card);
  background: var(--panel-2); color: inherit;
}
.lx-policy__save-text { align-self: flex-start; }
@media (max-width: 1024px), (pointer: coarse) {
  .lx-policy__ta { min-height: 96px; }
  .lx-policy__save-text { min-height: 44px; }
}

/* E-03 · Was ich schulde. Kennzahlen oben, dann die Liste — überfällig zuerst.
   Eigener @media-Block NACH den Basisregeln (Iter-15-Lehre).
   Fundament 29.07.: dieselbe Kennzahl-Kachel wie .stat — es gibt EINE
   Kennzahlsprache, nicht eine je Bereich. Der Balken links wich der Kante. */
.lx-stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
  gap: 14px; margin: 16px 0 18px; }
.lx-stat { display: flex; flex-direction: column; gap: 3px; padding: 18px;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-card); }
.lx-stat.is-late { border-color: rgba(var(--bad-rgb), .45); }
.lx-stat__v { font-size: 26px; font-weight: 650; letter-spacing: -.5px; line-height: 1.12;
  color: var(--text-primary); font-variant-numeric: tabular-nums; }
.lx-stat__k { font-size: 12.5px; color: var(--text-secondary); opacity: 1; }

/* Panel-Zeile: die Liste ist EIN Panel mit Hairline-Zeilen (DESIGN §1).
   Die Bausteine .panel-row__* gab es seit Block E-03, die BASIS fehlte —
   119 Zeilen in Buchhaltung, Schulden, Raten, Belegen und Abschluss
   rutschten darum als nackte <div> ohne Abstand und ohne Trenner
   ineinander. Eine Regel statt 119 Fundstellen. */
.panel-row {
  display: flex; align-items: center; gap: 8px 16px; flex-wrap: wrap;
  padding: 14px 0; border-bottom: 1px solid var(--border);
}
.panel-row:last-child { border-bottom: 0; }
.panel-row.is-void { opacity: .55; }
.panel-row__main { display: flex; flex-direction: column; gap: 1px; min-width: 0; flex: 1 1 260px; }
/* RANGFOLGE 25.08.: der Zeilentitel erbte 14px aus dem Rumpf — er war damit
   GROESSER als die Ueberschrift, die ihn ueberschreibt (`.panel h3`, 13px),
   bei gleicher Farbe und gleichem Gewicht. 14px ist ausserdem gar keiner der
   vier Grade aus EINHEIT §1.5; er stand nur da, weil nie einer gesetzt wurde.
   Jetzt der Grad «Kachel-Label» (12.5px) — dieselbe Groesse wie die Unterzeile
   darunter, aber 600 statt 400 und primaer statt sekundaer. Rangfolge ueber
   Gewicht und Farbe, nicht ueber einen fuenften Grad. */
.panel-row__main > b { font-size: 12.5px; font-weight: 600; color: var(--text-primary); }
.panel-row__sub { font-size: 12.5px; color: var(--text-secondary); opacity: 1; }
/* Owner-Wunsch 16a: die Vorgeschichte eines wiederverteilten Leads. Sie steht
   ruhiger als die Anschrift darüber — sie ist Kontext, keine Anweisung, und
   soll den Namen der Firma nicht überstimmen. Erscheint nur, wenn wirklich
   schon telefoniert wurde. */
.va-schon { display: block; color: var(--text-tertiary); font-size: 12px; margin-top: 2px; }
.panel-row__meta { font-size: 12.5px; color: var(--text-tertiary); opacity: 1; font-variant-numeric: tabular-nums;
  white-space: nowrap; }
.panel-row__val { font-variant-numeric: tabular-nums; font-weight: 600; white-space: nowrap;
  color: var(--text-primary); margin-left: auto; }
.panel-row__tag { font-size: 11.5px; color: var(--text-tertiary); opacity: 1; }
.panel-row.is-late .panel-row__tag { color: var(--danger); opacity: 1; }
.panel-row.is-hold .panel-row__tag,
.panel-row.is-part .panel-row__tag { color: var(--warn); opacity: 1; }

.lx-pay-form, .lx-neu-form { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 10px;
  padding: 12px 14px; margin: 0 0 6px; border: 1px solid var(--border); }
.lx-pay-form label, .lx-neu-form label { display: flex; flex-direction: column; gap: 4px;
  font-size: .82rem; opacity: .8; }
.lx-pay-form input, .lx-neu-form input { font: inherit; padding: 7px 9px;
  border: 1px solid var(--line); border-radius: var(--radius-card);
  background: var(--panel-2); color: inherit; }
.lx-pay-form__fehler, .lx-neu-form__fehler { color: var(--danger); font-size: .82rem;
  flex: 1 1 100%; }

/* E-05 Belege: dieselbe eingerueckte Sprache wie die Zahlungsform — was zu
   einer Zeile gehoert, sieht auch so aus. Die Datei-Auswahl ist ein Label um
   einen versteckten Input: der Owner klickt einen Knopf, kein Systemfeld. */
.lx-beleg-box { padding: 6px 14px 12px; margin: 0 0 6px;
  border: 1px solid var(--border); }
.lx-beleg-liste { display: flex; flex-direction: column; gap: 2px; }
.lx-beleg-neu { display: inline-flex; margin-top: 6px; cursor: pointer; }
.lx-beleg-neu span { pointer-events: none; }
/* B1 (24.08.): der Satz, der VOR dem Klick gilt. Er kommt woertlich vom Server
   (`expense_belege_stand`/`vertrag_beleg_stand`) und steht darum unter der
   Liste, nicht als Titel an einem Knopf — er ist oft zwei Zeilen lang. */
.lx-beleg-hinweis { margin: 8px 0 0; font-size: .82rem; line-height: 1.45;
  color: var(--text-secondary); max-width: 62ch; }

@media (max-width: 1024px), (pointer: coarse) {
  .lx-pay-form label, .lx-neu-form label { flex: 1 1 100%; }
  .lx-pay-form input, .lx-neu-form input,
  .lx-pay-form button, .lx-neu-form button { min-height: 44px; }
  .lx-beleg-neu span, .lx-beleg-box .ghost-btn { min-height: 44px;
    display: inline-flex; align-items: center; }
  .panel-row__meta { white-space: normal; }
}

/* ---------- JETZT: ein Vorgang, eine Aktion ----------------------------------
   Owner 2026-07-28: «geklebte Scheisse, kein Flow, nichts hat.» Der Tag begann
   mit fünf Listen — jede für sich richtig, zusammen keine Antwort auf die
   einzige Frage, die morgens zählt: was jetzt?

   Darum steht dieser Block ganz oben und ist der einzige mit Akzentkante: er
   ist keine weitere Liste, sondern die Anweisung. Kein Rahmen um ein Bild —
   die Zeile rechnet (nächster Termin, überfällige Wiedervorlage, ältester
   unberührter Lead) und handelt (ein Knopf, ein Ziel). */
/* DER FRAGE-KOPF (v397, 03.09.) — EIN Bauteil für «Was jetzt» (Heute,
   Vertriebsportal) und «Nächster Schritt» (Lead-Akte), in der Anatomie des
   Blatt-Kopfs des Offerten-Rechners (`.kf-blattkopf`, Referenz Bild 02): oben
   das Etikett in gesperrten Versalien, darunter die EINE Frage — gross und
   dünn, kein fetter Titel —, rechts die Hauptaktion als eishelles Feld. Grund
   = gemessener Verlauf der Referenz, Kante = Haarlinie. Der Seitenstreifen
   (3 px Akzent links) ist weg — DESIGN.md: Side-Stripe ist Deko. Die Masse
   laufen mit der Breite (clamp), darum kein Geräte-Block. Owner 02.09.: «man
   spürt: jetzt bin ich hier». */
.panel.frage-kopf {
  border: 1px solid var(--border);
  background: var(--work-heading-background);   /* gemessen Bild 02 */
  /* am Handy 12 px: der Provisions-Satz im Vertriebsportal muss bei 390×620
     im Bild bleiben (_beraterweg_test E12c, Bild 34 — 6 px fehlten) */
  padding: clamp(12px, 2vw, 18px) clamp(16px, 2.5vw, 22px);
}
.frage-kopf__wort {
  font-size: 12px; font-weight: 650; letter-spacing: .16em; text-transform: uppercase;
  color: #7691aa;   /* wie `.kf-blattkopf > .kf-kopf` */
}
.frage-kopf__frage {
  font-size: clamp(20px, 2.6vw, 26px); font-weight: 400; letter-spacing: -.01em;
  line-height: 1.2; color: var(--text-primary); text-wrap: balance;
}
.jetzt { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 18px; }
/* DER SACHVERHALT — eine Zeile, die sagt, was mit einer Zahl los ist (Referenz
   Bild 14: «Berechnet …», «Noch zu prüfen …», «Separater Umfang …»): Zeichen im
   Quadrat, Leitwort, ein Satz. Gerahmt mit der Haarlinie, damit er neben Tabellen
   und Kacheln als eigene Sache steht — kein Erklärtext unter einem Kasten. Drei
   Töne, die trennen: ok (grün), prüfen (bernstein), abseits (neutral).
   Bauteil: components/sachverhalt.js. */
.sachverhalt {
  display: grid; grid-template-columns: 26px minmax(0, 1fr); gap: 10px; align-items: start;
  margin: 10px 0 0; padding: 10px 12px; border: 1px solid var(--border); border-radius: var(--radius-card);
  font-size: 12.5px; line-height: 1.5; color: var(--text-secondary);
}
.sachverhalt + .sachverhalt { margin-top: 6px; }
.sachverhalt > .gz-ic { --gz-ic-gr: 26px; }
.sachverhalt b { color: var(--text-primary); font-weight: 650; }
.sachverhalt a { color: var(--accent); }
.sachverhalt--ok > .gz-ic { --gz-feld: var(--good-rgb); }
.sachverhalt--pruefen > .gz-ic { --gz-feld: var(--warn-rgb); }
.sachverhalt--pruefen { border-color: rgba(var(--warn-rgb), .35); }
.jetzt__wozu { flex: 0 0 100%; }
.jetzt__was { flex: 1 1 260px; }
/* 44px Tapfläche — dieselbe Grenze, die der Realtest an jedem Knopf prüft. */
.jetzt__tun { flex: 0 0 auto; min-height: 44px; display: inline-flex; align-items: center; }
@media (max-width: 720px) {
  .jetzt__was { flex-basis: 100%; }
  .jetzt__tun { width: 100%; justify-content: center; }
}


/* ---------------------------------------------------------------------------
   KONTAKT-ZULAESSIGKEIT (COS 0.3, 01.09.2026)
   ---------------------------------------------------------------------------
   Drei Staende, die ein Mensch AUSEINANDERHALTEN muss — und zwar auch dann,
   wenn er Farben nicht unterscheidet. Darum trennt jeder Stand sich dreifach:
   durch sein eigenes Wort (im Markup), durch die Kante und durch die Farbe.
   Die Kante allein oder die Farbe allein waere keine Trennung.

     --stopp   rote Kante + kraeftige Schrift   → haelt den Blick an
     --offen   neutrale Kante, gedaempfter Ton  → «ich weiss es nicht»
     --ok      KEINE Kante, nur Text            → eine Randnotiz, kein Orden

   Warum «erlaubt» am leisesten ist: waere es gruen und breit, gewoehnte sich
   das Auge daran — und uebersaehe die Sperre daneben. Was auffaellt, ist
   genau das, was den Berater aufhalten muss.

   Ein <span>, kein <p>: die Zeile steht IN der Kennzeile, und die ist selbst
   ein <p> — ein Absatz im Absatz waere kaputtes Markup.

   Sie bekommt bewusst KEIN erzwungenes Umbrechen. Die Kennzeile ist ein
   umbrechender Fluss; ist Platz da (gemessen ab 1024 px), setzt sich die
   Auskunft hinter die Nummer und kostet keine Zeile. Wird es eng, rutscht sie
   von selbst darunter. Das ist der Unterschied zwischen «passt sich an» und
   «nimmt sich immer eine Zeile». */
.kz { display: flex; flex-wrap: wrap; gap: 5px 14px; }
.kz__teil {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 12.5px; line-height: 1.5;
  padding: 3px 9px 3px 8px; border-radius: var(--radius-card);
}
.kz__teil .ico { width: 14px; height: 14px; flex: 0 0 auto; opacity: .85; }
.kz__teil--stopp {
  color: var(--bad-strong); font-weight: 600;
  background: rgba(var(--bad-rgb), .09);
  box-shadow: inset 2.5px 0 0 var(--bad);
}
/* GEMESSEN, NICHT GERATEN (01.09.): der erste Entwurf setzte hier --text-2
   und --text-3 — beide gibt es in diesem Haus NICHT (0 Definitionen in
   grund.css und allen patch-Blaettern). Eine unbekannte Variable ist in CSS
   stumm: die Farbe fiel auf den geerbten Wert, und «ungeprüft» sah Pixel fuer
   Pixel aus wie «erlaubt» — genau die Trennung, die der Auftrag verlangt, war
   weg. Dieselbe Klasse, die dieser Datei oben schon einmal 40 tote
   Deklarationen beschert hat. Jetzt zwei Toene, die es wirklich gibt und die
   beide ihren Kontrast tragen.
   (Bestandsbefund am Rande, nicht mein Auftrag: .pitch-herkunft und
    .pitch-befund__liste span setzen dasselbe tote --text-3.) */
.kz__teil--offen {
  color: var(--text-secondary); background: var(--surface-2);
  box-shadow: inset 2.5px 0 0 var(--line, var(--text-tertiary));
}
.kz__teil--ok { color: var(--text-tertiary); padding-left: 0; background: none; }
/* KEIN Geraete-Block. Hier stand einer («auf schmalen Geraeten untereinander»)
   — er definierte `.kz` und `.kz__teil` ein ZWEITES Mal, und genau das haelt
   `_stil_einmalig_test.mjs` an: 1044 eingefrorene Doppelungen, die nicht mehr
   wachsen duerfen. Zwei Definitionen eines Selektors heissen, dass die
   Kaskade entscheidet und nicht der Autor; dieses Haus hat dafuer schon
   bezahlt (die patch-Blaetter schlagen den Griff-Boden aus grund.css still).
   Nachgemessen statt geglaubt: `flex-wrap: wrap` legt die zwei Stuecke
   ohnehin untereinander, sobald sie nicht nebeneinander passen — das
   `width: 100%` erzwang den Umbruch nur zusaetzlich. Ohne den Block auf allen
   neun Breiten: nichts sprengt seinen Elternkasten, keine Seite laeuft quer,
   und auf 390 px stehen beide Stuecke weiterhin untereinander. Der
   Zeilenabstand von 5 px, den der Block mitbrachte, steht jetzt in der einen
   Regel oben (`gap: 5px 14px` — 5 zwischen den Zeilen, 14 zwischen den
   Stuecken, wenn sie nebeneinander Platz haben). */

/* ---------- COS-Etappe 2.4 (02.09.2026): die eigene Rangfolge ---------- */
/* WARUM DIESE KARTE HIER STEHT. Dieselbe Bauform wie `.firm-card__schritt`
   (leises Etikett, dahinter der Satz): ein Zustand sagt, wo man steht, der
   Schritt sagt, was man tut, der Grund sagt, warum jetzt diese. Kein Rang
   ohne Satz — die Zeile ist der Satz. */
.firm-card__grund {
  display: flex; align-items: baseline; gap: 6px; flex-wrap: wrap;
  margin: 0; font-size: 12.5px; line-height: 1.35; color: var(--text-secondary);
}
.firm-card__grund-wort {
  flex: 0 0 auto;
  font-size: 11px; font-weight: 700; letter-spacing: .07em; text-transform: uppercase;
  color: var(--text-tertiary);
}
/* Die vier Zulaessigkeits-Angaben, einzeln — dieselben Chips wie in der Akte
   (`.kz__teil`), damit «ungeprueft» hier genauso aussieht wie dort. */
.firm-card__angaben { display: flex; flex-wrap: wrap; gap: 5px 12px; margin: 0; font-size: 12px; }
/* Auf schmalen Breiten rutschen Grund und Angaben ans Ende der Karte. Der
   Abstand (margin 0) steht EINMAL, oben bei `.firm-card__grund` und
   `.firm-card__angaben` — nicht hier ein zweites Mal (Stil-Einmalig, 02.09.). */
@media (max-width: 720px) {
  .firm-card--lead :is(.firm-card__grund, .firm-card__angaben) { order: 6; }
}
/* Der Umschalter «Eigene Reihenfolge | Laut Lieferung» im Kopf des
   Abschnitts — dieselbe Bauform wie der Ansicht-Umschalter oben.
   Die 36 px gelten nur an der Maus: der Griff-Boden von 44 px (oben im
   Touch-Block, `.view-toggle__btn { min-height: 44px }`) stand VOR dieser
   Zeile und verlor — auf 390–1024 px mass der Knopf 36 px (jede-breite,
   8 Befunde, 02.09.2026). Ein unbewachtes min-height nach dem Boden
   schlägt ihn still; darum steht es hier hinter derselben Grenze. */
.rangfolge-schalter { margin-left: auto; }
@media (min-width: 1025px) and (pointer: fine) {
  .rangfolge-schalter .view-toggle__btn { min-height: 36px; font-size: 12.5px; }
}

/* v399 — «Diesen Kunden gibt es womöglich schon»: Bernstein heisst im Haus
   «hier fehlt/stimmt etwas noch nicht», darum trägt der Kasten diese Linie.
   Jede Zeile: wer, warum, und EIN Griff. */
/* DIE FUGE HAENGT AM KASTEN, NICHT AM NACHBARN — dieselbe Rechnung wie bei
   `.panel` oben (nachgemessen 25.08.), hier nachgezogen am 04.09.2026.
   GEMESSEN in der Kundenakte UND auf dem Wegweiser: `ku-gleiche` -> `panel
   kpi-strip` = 0 px. Zwei gerahmte Kaesten stiessen ohne Luft aneinander und
   lasen sich als ein Kasten mit einer Linie mittendrin; die Referenz
   (Portaluikomplett 13_25_56 (1)) laesst kein gerahmtes Panel ein anderes
   beruehren. Der Wert ist NICHT neu gewaehlt: es ist die Fuge, die jede
   Panel-Karte im Haus traegt. Der Dubletten-Kasten ist der einzige gerahmte
   Kasten der Akte, der sie nicht hatte. */
.ku-gleiche { border: 1px solid var(--warn); padding: 10px 12px; display: grid; gap: 8px; margin-bottom: 16px; }
.ku-gleiche__satz {
  margin: 0; font-size: 12px; font-weight: 650; letter-spacing: .08em;
  text-transform: uppercase; color: var(--warn);
}
.ku-gleiche__liste { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }
.ku-gleiche__zeile,
/* Die GRIFF-Zeile des Kastens (Rückweg der Zusammenführung, 05.09.). Dieselbe
   Form wie eine Listenzeile, aber ein anderes Ding: `__zeile` ist EIN
   namensgleicher Kunde, `__griffzeile` ist der Weg zurück. Zwei Namen, weil
   die Prüfstände die Dubletten-Zeilen zählen (`_kunde_archiv_test.mjs` B26) —
   ein zweckentfremdeter Name macht dort aus einem Griff eine Dublette. */
.ku-gleiche__griffzeile { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; }
.ku-gleiche__wer { display: grid; gap: 2px; font-size: 13px; }
.ku-gleiche__warum { font-size: 12px; color: var(--text-secondary); }

/* Team callbacks remain searchable and paged before the following work. */
.mt-work-filters { display:grid;grid-template-columns:repeat(auto-fit,minmax(min(220px,100%),1fr));gap:12px;padding:16px clamp(12px,2vw,18px);border-bottom:1px solid var(--border); }
.mt-work-filters label { display:grid;gap:6px;min-width:0;font-size:12px;color:var(--muted); }
.mt-work-filters input,.mt-work-filters select { width:100%;min-width:0;min-height:44px; }
.mt-work-pages { display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:12px 16px;padding:14px clamp(12px,2vw,18px);border-top:1px solid var(--border); }
.mt-work-pages p { flex:1 1 200px;margin:0;color:var(--muted);font-size:12px;font-variant-numeric:tabular-nums; }
.mt-work-pages > div { display:flex;flex:1 1 200px;gap:8px; }
.mt-work-pages button { min-height:44px;flex:1; }
.mt-work-empty { padding:18px;margin:0; }
/* ============================================================
   Patch-Integration — Namensraum kk-; Quelle: docs/design/patch-kundenzentrale.css
   Der Block wird bei Integration als GANZES ersetzt, nie editiert. Steht NACH .kp-* (Kaskade).
   ============================================================ */
/* ===========================================================================
   Kunden-Kommandozentrale (#/k) — Patch zu public/style.css
   Welle «Exakt nach Referenz, Runde 1», Team A · 2026-07-29
   Referenz: docs/design/ZIELBILD-2026-07-28.md §LoopScreens «Willkommen zurück»

   EINBAU: diesen Block unverändert ans Ende von `public/style.css` hängen —
   nach dem `.kp-*`-Block (heute style.css:5011-5095), damit die Mobile-Regeln
   NACH ihren Basisregeln stehen (Memory project_css_cascade_mobile).
   Es wird keine bestehende Regel geändert und keine überschrieben; alle
   Selektoren tragen den neuen Präfix `kk-`.

   Alles, was es schon gab, wird benutzt statt nachgebaut:
   .panel · .panel__header · .panel__title · .stat-strip--auto · .stat ·
   .panel-row/__main/__sub/__tag · .sl-badge* · .conv-pill__bar/__fill ·
   .primary-btn · .ghost-btn · .kp-count. Neu sind nur: die Herkunftszeile
   unter einer Kachel, die Wege-Karte, der Übernahme-Hinweis.
   =========================================================================== */

/* Die eine Zeile unter «Willkommen zurück» — Stand, nicht Werbung. */
.kk-versprechen {
  margin: -4px 0 18px;
  font-size: 15px;
  line-height: 1.5;
  color: var(--text-secondary);
}

/* Kachelzeile: identisch zur bestehenden .stat, plus das Symbol-Quadrat der
   Referenz (FINISH-STANDARD 1) und eine dritte Zeile, die sagt, WOHER die Zahl
   kommt. Ohne sie wäre «4» nur eine Behauptung.
   Das Soft-Feld trägt den Akzent statt einer Bereichsfarbe: die Kundenwelt ist
   EIN Bereich, und die Referenz zeigt alle vier Felder in Türkis. `--gz-feld`
   ist die Variable des bestehenden Bauteils (.gz-ic, style.css:6938) — hier
   wird sie gesetzt, nicht das Bauteil kopiert. */
.kk-kacheln { --gz-feld: var(--accent-rgb); }
/* Farbe und Feld mit zwei Klassen: ältere Regeln wie `.kk-karte > span` färben
   jedes span ihrer Karte ein — ohne diese Zeile stünde das Zeichen grau,
   solange der Vorgängerblock noch in style.css liegt. */
.kk-kacheln .gz-ic, .kk-panel .gz-ic {
  color: rgb(var(--gz-feld));
  background: rgba(var(--gz-feld), .13);
}
.kk-stat { align-content: start; }
/* Zeichen OBEN, nicht neben dem Label: auf 390px stehen zwei Kacheln
   nebeneinander, und daneben bliebe für «Geplante Ausstrahlungstage» kein
   Platz (dieselbe Entscheidung wie .gz-kachel, docs/design/patch-zentrale.css). */
.kk-stat .gz-ic { margin-bottom: 10px; }
.kk-stat__sub {
  margin-top: 2px;
  font-size: 11.5px;
  line-height: 1.35;
  color: var(--text-tertiary);
  font-variant-numeric: tabular-nums;
}
/* Der Balken misst denselben Planfortschritt wie die Zusatzzeile darüber —
   er steht unten in der Kachel, damit alle vier Kacheln gleich hoch bleiben. */
.kk-stat .stat__bar { margin-top: auto; }

.kk-panel + .kk-panel,
.kk-raster + .kk-panel,
.kk-panel + .kk-raster,
.kk-raster + .kk-raster { margin-top: 16px; }

/* Das Raster der Referenz (EINHEIT 4.15): breites Panel neben schmalem.
   Dieselben Proportionen wie die Zentrale innen (.gz-raster, style.css:7020) —
   eine Aussenwelt, die anders proportioniert ist als die Innenwelt, ist genau
   die Uneinheitlichkeit, gegen die EINHEIT.md geschrieben wurde. */
.kk-raster {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(280px, 360px);
  gap: 16px;
  align-items: start;
}
.kk-raster--halb { grid-template-columns: repeat(2, minmax(0, 1fr)); }

/* Panel-Kopf rechts: Zähler und «Alle anzeigen →» auf einer Höhe. */
.kk-kopf__rechts { display: inline-flex; align-items: center; gap: 12px; flex: 0 0 auto; }
.kk-alle {
  display: inline-flex; align-items: center; gap: 4px;
  color: var(--accent); font-size: 12.5px; font-weight: 600; text-decoration: none;
  white-space: nowrap;
}
.kk-alle svg { width: 14px; height: 14px; }
.kk-alle:hover { text-decoration: underline; }
.kk-alle:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: var(--radius-card); }

/* Kampagnen-Zeile: eine .panel-row mit Chip, Balken und genau EINER Aktion.
   `align-items: flex-start`, weil die Zeile mehrzeilig ist — zentriert
   schwömme der Chip neben dem Fortschrittsbalken. */
.kk-kampagne { align-items: flex-start; gap: 10px 14px; }
.kk-kampagne .panel-row__main { gap: 3px; }
/* Zustandsblock und Aktion stehen rechts auf EINER Höhe. Ohne das trennt sie
   die Zeilenhöhe des mehrzeiligen Textblocks: der Chip klebte oben, der Knopf
   sass in der Mitte — im Bild zwei Elemente, die nicht zusammengehören. */
.kk-kampagne .kk-zustand { flex: 0 0 auto; margin-left: auto; align-self: center; }
/* Der neutrale Zustand (Geplant, Beendet) trägt in style.css keine Fläche und
   stand darum als nackter Text neben zwei echten Chips. Hier bekommt er die
   ruhige Variante des Vokabulars — bewusst nur in der Zentrale, damit keine
   fremde Fläche mitkippt. */
.kk-kampagne .sl-badge:not([class*="sl-badge--"]) {
  background: rgba(var(--tint-rgb), .07);
  color: var(--text-secondary);
}
/* Der Balken gehört zur Zeile, nicht zur Seite: begrenzt, damit er auf 1400px
   nicht als Vollbreiten-Band den Blick vom Namen wegzieht. */
.kk-bar { max-width: 360px; }
.kk-tun { flex: 0 0 auto; align-self: center; }
a.kk-tun { display: inline-flex; align-items: center; justify-content: center; }

/* Zustand + Restlaufzeit stehen als EIN Block rechts (Referenz: Status-Chip
   und «Noch 6 Tage» direkt untereinander). */
.kk-zustand {
  display: inline-flex; flex-direction: column; align-items: flex-end; gap: 4px;
  flex: 0 0 auto; margin-left: auto; align-self: center;
}
.kk-rest {
  font-size: 11.5px; color: var(--text-tertiary);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
/* Der Bildschirm-Stand der Zeile — eine Stufe leiser als der Plantext, weil er
   den Zustand ergänzt und nicht die Kampagne benennt. */
.kk-lage { font-size: 12px; line-height: 1.4; color: var(--text-secondary); margin-top: 2px; }
/* Worauf sich dieser Stand bezieht — einmal je Panel, nur wenn ein Bildschirm
   wirklich fehlt (PROTOTYP-ANALYSE B2: nie «jetzt offline»). */
.kk-stand {
  margin: 12px 0 0; font-size: 11.5px; line-height: 1.45;
  color: var(--text-tertiary);
}

/* «Benötigte Inhalte» und «Letzte Rechnungen»: dieselbe .panel-row wie die
   Kampagnenzeile, nur ohne Aktion — beide sagen einen Zustand, sie öffnen
   nichts (der Weg dorthin steht im Panel-Kopf). */
.kk-inhalt, .kk-rechnung { align-items: center; gap: 8px 14px; }
.kk-inhalt .sl-badge, .kk-rechnung .sl-badge { flex: 0 0 auto; align-self: center; }
.kk-rechnung .sl-badge { margin-left: 0; }
.kk-betrag {
  flex: 0 0 auto; margin-left: auto;
  font-size: 14px; font-weight: 600; font-variant-numeric: tabular-nums;
  color: var(--text-primary); white-space: nowrap;
}
.kk-inhalt .sl-badge { margin-left: auto; }

/* Leerfall: ein Satz und der Weg — nie nur grauer Text. */
/* ENTFERNT, nicht ersetzt: .kk-leer · .kk-leer__satz
   GEFALLEN 21.08.2026 — die Leer-Zeile des Hauses ist EINE Form:
   `.empty-state.empty-state--zeile` + `.empty-state__weg` in docs/design/grund.css.
   Sie war die einzige der vierzehn, die einen KNOPF statt eines Links trug —
   darum kann die Haus-Zeile das jetzt auch (`:has(.primary-btn)`). */

/* «Schnellaktionen» — Karten, die alle wirklich etwas öffnen. Im schmalen Panel
   der Referenz stehen sie untereinander, Zeichen links, Text rechts. */
.kk-wege {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: 12px;
  margin-top: 12px;
  --gz-feld: var(--accent-rgb);
}
.kk-schnell .kk-wege { grid-template-columns: minmax(0, 1fr); }
.kk-karte {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  grid-template-areas: "ic kopf" "ic satz";
  align-items: center;
  gap: 2px 12px;
  padding: 14px 16px;
  text-align: left;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  color: inherit;
  font: inherit;
  cursor: pointer;
  text-decoration: none;
  transition: background var(--transition), border-color var(--transition);
}
.kk-karte .gz-ic { grid-area: ic; }
/* Eine einzelne Karte streckt sich sonst über 1400px und sieht aus wie ein
   leeres Panel mit zwei Zeilen Text. */
.kk-karte:only-child { max-width: 420px; }
.kk-schnell .kk-karte:only-child { max-width: none; }
.kk-karte:hover { background: var(--surface-3); border-color: var(--accent-line); }
.kk-karte:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.kk-karte > b { grid-area: kopf; font-size: 14px; font-weight: 600; color: var(--text-primary); align-self: end; }
.kk-karte > span:not(.gz-ic) { grid-area: satz; font-size: 12.5px; line-height: 1.45; color: var(--text-secondary); align-self: start; }

/* Buchungsstrecke: der Rückweg steht über allem, damit die Zentrale nie zur
   Sackgasse wird. */
.kk-zurueck { margin-bottom: 12px; }

/* Was «Erneut buchen» übernommen hat — und was nicht mehr buchbar ist.
   Akzentkante wie .jetzt-panel: dieser Block ist eine Ansage, keine Liste. */
.kk-uebernahme { margin-bottom: 16px; border-color: var(--accent-line); }
.kk-uebernahme__satz { margin: 0; font-size: 14px; line-height: 1.5; color: var(--text-primary); }
.kk-uebernahme__fehlt { margin: 8px 0 0; font-size: 13px; line-height: 1.5; color: var(--warn-strong); }

/* Der per «Details» aufgeschlagene Beleg im Tab «Meine Buchungen». */
.kk-hervor { box-shadow: inset 3px 0 0 var(--accent); }

/* --- Touch + Handy (390px) -------------------------------------------------
   Ein eigener Block NACH den Basisregeln (Memory project_css_cascade_mobile),
   und der Touch-Boden greift auch auf Tablets (Memory
   project_tablet_touch_breakpoint) — 720px allein deckt sie nicht ab. */
@media (max-width: 1024px), (pointer: coarse) {
  /* .kk-leer .primary-btn ist hier raus: der Touch-Boden fuer .primary-btn
     steht laengst im Grundstock (grund.css, `@media …(pointer: coarse)`) —
     die Zeile hier hat ihn doppelt gesagt. */
  .kk-tun, .kk-zurueck .ghost-btn { min-height: 44px; }
  .kk-karte { min-height: 44px; }
  .kk-alle { min-height: 44px; }
}

/* Zwischenbreite: der Zweispalter wird zum Einspalter, bevor das schmale Panel
   unter 280px fällt und die Kampagnenzeile ihre Aktion verliert. */
@media (max-width: 1080px) {
  .kk-raster, .kk-raster--halb { grid-template-columns: minmax(0, 1fr); }
  .kk-schnell .kk-wege { grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); }
}

@media (max-width: 720px) {
  /* Auf 390px steht der Zustand über der Zeile — dort ist rechts kein Platz
     mehr für Chip und Restlaufzeit nebeneinander. */
  .kk-zustand { flex-direction: row; align-items: center; gap: 8px; }
  .kk-inhalt .sl-badge, .kk-rechnung .sl-badge, .kk-betrag { margin-left: 0; }
  .kk-inhalt, .kk-rechnung { flex-wrap: wrap; }
  .kk-inhalt .panel-row__main, .kk-rechnung .panel-row__main { flex: 1 1 100%; }
  .kk-versprechen { font-size: 14px; margin-bottom: 14px; }
  /* Auf 390px passen zwei Kacheln nebeneinander — «Geplante Ausstrahlungstage»
     wurde dort zu «Geplante Ausstrahlungs…». Ein abgeschnittenes Label ist
     eine Kachel ohne Bedeutung; sie darf lieber zweizeilig sein. Präzedenz:
     .stat--well .stat__label (docs/design/grund.css). */
  .kk-stat .stat__label { white-space: normal; overflow: visible; }
  /* Auf 390px steht die Aktion unter der Zeile, nicht daneben: nebeneinander
     bliebe für den Namen keine lesbare Breite. */
  .kk-kampagne { flex-wrap: wrap; }
  .kk-kampagne .panel-row__main { flex: 1 1 100%; order: 2; }
  /* Auf 390px steht der Zustand ÜBER dem Namen: er ist die erste Frage
     («läuft es?»), und rechts wäre für ihn kein Platz mehr. Der Chip bleibt
     dabei vor der Restlaufzeit — `order: 0` steht hier, weil der
     Vorgängerblock in style.css den Chip nach hinten schob, als er noch
     direktes Kind der Zeile war. */
  .kk-kampagne .kk-zustand { order: 1; margin-left: 0; align-items: center; }
  .kk-kampagne .kk-zustand .sl-badge { order: 0; }
  .kk-tun { order: 3; flex: 1 1 auto; }
  .kk-bar { max-width: none; }
  .kk-wege { grid-template-columns: minmax(0, 1fr); }
  /* ENTFERNT: .kk-leer + .kk-leer .primary-btn — dieselbe Regel steht jetzt
     am Haus-Bauteil (grund.css, `@media (max-width: 720px)`) und gilt fuer
     jede Leer-Zeile mit Knopf, nicht nur fuer diese eine. */
}

/* ---------------------------------------------------------------------------
   DIE KUNDENWELT LIEST ÜBERSCHRIFTEN, KEINE ETIKETTEN (03.09.2026).
   Mit der Farbwelt der Referenz sind `.panel__title` im Haus gesperrte
   Versalien (12 px, Etikett über einer Zone). In der Kundenwelt trägt derselbe
   Titel Sätze an Kundinnen und Kunden («Das bekommst du», «Was jetzt
   passiert», «Passt es so nicht?») — ein Satz in Versalien liest sich wie ein
   Formularfeld. Hier bleibt darum die Überschrift: gemischt, 13 px, wie bis
   zum 03.09. im ganzen Haus (Probe A3 in `_kunde_annahme_ui_test.mjs`).
   Farben, Rahmen, Knöpfe, Chips der Farbwelt gelten auch hier — nur die
   Schreibung des Titels nicht. */
.lx-kundenportal .panel__title {
  text-transform: none; letter-spacing: -.01em; font-size: 13px; font-weight: 600;
  color: var(--text-primary);
}

/* ============================================================
   Patch-Integration — Namensraum gz-; Quelle: docs/design/patch-zentrale.css
   Der Block wird bei Integration als GANZES ersetzt, nie editiert. Steht VOR pl-/pd2-/ar- (die .gz-ic-Variablen umsetzen).
   ============================================================ */
/* =========================================================================
   Zentrale — #/zentrale, die Kommandozentrale des GANZEN Geschäfts.
   Owner 29.07.: «Es wird immer noch behandelt, als wäre es ein CRM: Leads
   offen etc. Das ist EIN Bereich.» Referenz: docs/design/ZIELBILD-2026-07-28.md
   («Agent OS»: Kennzahl-Kacheln, Bereichs-Portfolio mit Fortschritt, laufende
   Arbeit, Systemlage · gross, ruhig, teuer — nicht gedrängt).

   FINISH-STANDARD (Owner 29.07.: «Design/UX ist nicht wie die Referenz»,
   ZIELBILD-2026-07-28.md:111-137). Die Struktur stand, der Reichtum fehlte.
   Was diese Fassung dazu baut:
     1. farbiges Symbol-Quadrat an JEDER Kachel und JEDER Bereichs-Karte
     2. je Bereich ein eigener, ruhiger Soft-Ton (gz--Tokens weiter unten) —
        Türkis bleibt frei für Aktion, aktiven Zustand und Positivwert
     3. Verlaufskurve, wo eine ECHTE Reihe existiert (kpi_trend); sonst Balken
     4. Menschen als Initialen-Avatare statt als blosser Text
     5. Fusszeilen-Statusleiste aus ausschliesslich gemessenen Zuständen
     6. Dichte der Referenz: Zahl 26px/650/-.5px, Label 12.5px, Luft — aber
        keine leeren Riesenkarten (.gz-karte--knapp) und einzeilige Leerfälle

   Anatomie in Regeln:
     1. Kopfzeile: Titel links, gemessene Systemlage als Fusszeile
     2. EINE Kachelzeile mit den Kernzahlen des Geschäfts (Anzahl variiert mit
        den Rechten — deshalb Spalten-Autofluss statt fester Sechserreihe)
     3. Raster: links das Bereichs-Portfolio, rechts Missionen + Aktivitäten
     4. Handy: Kacheln 2 je Reihe, Portfolio einspaltig, alles ≥ 44px

   Bausteine aus style.css werden benutzt, nicht ersetzt: .panel, .stat,
   .stat__bar, .badge (Pillen-Chip), .ghost-btn, .sparkline. Der Orchestrator
   hängt diese Datei an style.css an — sie steht darum NACH allen Basisregeln
   und darf sie mit gleicher Spezifität stechen (Memory
   project_css_cascade_mobile). Präfix gz- für alles Neue.
   ========================================================================= */

/* --- 0. Bereichs-Farbcode ----------------------------------------------- */
/* Sieben Bereiche, sieben ruhige Töne. Sie tragen NUR Soft-Felder (Icon-
   Quadrat, Kurve) — nie Text, nie Fläche, nie einen Knopf: Türkis bleibt der
   EINE Akzent für Aktion und Positivwert (ZIELBILD «EIN Akzent»), und die
   Semantikfarben (--warn Bernstein, --bad Rot) bleiben der Warnung.
   Als Kanal (r, g, b), damit dieselbe Zahl das Feld (α .13) und die Linie
   (voll) speist — genau das Muster von --accent-rgb/--good-rgb im Fundament.

   DIE TOENE STEHEN SEIT 25.08.2026 IM FUNDAMENT (docs/design/grund.css,
   `:root`), nicht mehr hier. Grund, gemessen: solange sie an `.gz` hingen,
   galten sie NUR in der Zentrale — 36 Flaechen-Dateien geben `gz-ic`- oder
   `data-bereich`-Traeger aus, aber nur 19 davon liegen in einem `.gz`. Der
   Rest zeichnete sein Symbol in der Rueckfallfarbe. Was hier bleibt, ist der
   Rueckfall dieser Flaeche und die Zuordnung Ton → Traeger. */
.gz {
  --gz-feld: var(--tint-rgb);        /* Rückfall: nie eine tote var()           */
}
/* EINE Zeile je Bereich für beide Wege: das Quadrat trägt seinen Ton selbst,
   und ein Träger mit data-bereich vererbt ihn an alles darin (die Kurve).
   OHNE `.gz`-Vorsatz seit 25.08.: die Zuordnung gilt im ganzen Haus. Ein
   Traeger, der die Farbe NICHT will, sagt es weiterhin selbst
   (`gz-ic--neutral`) — sie draengt sich nirgends auf, sie steht nur endlich
   dort zur Verfuegung, wo die Flaechen sie schon anfordern. */
.gz-ic--verkauf,     [data-bereich="verkauf"]     { --gz-feld: var(--gz-verkauf); }
.gz-ic--leads,       [data-bereich="leads"]       { --gz-feld: var(--gz-leads); }
.gz-ic--buchhaltung, [data-bereich="buchhaltung"] { --gz-feld: var(--gz-buchhaltung); }
.gz-ic--partner,     [data-bereich="partner"]     { --gz-feld: var(--gz-partner); }
.gz-ic--screens,     [data-bereich="screens"]     { --gz-feld: var(--gz-screens); }
.gz-ic--kunden,      [data-bereich="kunden"]      { --gz-feld: var(--gz-kunden); }
.gz-ic--missionen,   [data-bereich="missionen"]   { --gz-feld: var(--gz-missionen); }
/* Panel-Köpfe tragen KEINE Bereichsfarbe: «Bereiche» ist kein Bereich, und ein
   eingefärbter Kopf würde den Code verwässern, der darunter etwas bedeutet. */
.gz-ic--neutral { --gz-feld: var(--tint-rgb); }

/* Das Symbol-Quadrat der Referenz: Zeichen im Soft-Farbfeld, gerundet. */
.gz-ic {
  display: grid; place-items: center; flex: 0 0 auto;
  width: var(--gz-ic-gr, 32px); height: var(--gz-ic-gr, 32px);
  border-radius: var(--radius-card); /* 03.09.2026: die Ecken des Hauses, nicht 30 % */
  /* Rueckfall (Schlichtung 10.08., Pruefblick W9 Q2): `--gz-feld` setzt nur,
     wer eine Traegerklasse mitgibt — ohne sie fiel das Feld ersatzlos weg
     (unsichtbares Zeichen statt sichtbarem Fehler). Akzent ist der Boden. */
  background: rgba(var(--gz-feld, var(--accent-rgb)), .13);
  color: rgb(var(--gz-feld, var(--accent-rgb)));
}
.gz-ic svg { width: calc(var(--gz-ic-gr, 32px) * .56); height: calc(var(--gz-ic-gr, 32px) * .56); }
/* 1:1-Huelle (gemessen 13_25_27): die Icon-Quadrate der KARTEN sind SATTE
   Farbfelder (Projekt-Quadrat #7f4cf0 voll, nicht getoent) — die KPI-Kacheln
   dagegen bleiben getoent (gemessen #134e56-Mittel). Dunkles Zeichen auf dem
   satten Pastellfeld haelt die Kontrastpflicht, die die Referenz mit ihren
   dunkleren Feldern via Weiss erfuellt. */
.gz-karte .gz-ic, .kk-karte .gz-ic {
  background: rgb(var(--gz-feld));
  color: #081018;
}

/* Menschen als Initialen (FINISH-STANDARD 4). Bewusst EIN neutraler Ton: eine
   Farbe je Person würde in einer Fläche, in der jede Farbe einen Bereich
   meint, eine Bedeutung vortäuschen, die sie nicht hat. */
.gz-avatar {
  display: grid; place-items: center; flex: 0 0 auto;
  width: 26px; height: 26px; border-radius: 50%;
  background: rgba(var(--tint-rgb), .09); border: 1px solid var(--border);
  color: var(--text-secondary); font-size: 11px; font-weight: 650; letter-spacing: .02em;
}

/* Verlaufskurve — nur dort, wo die View eine echte Reihe hat. Die Farbe kommt
   vom Bereich (currentColor), die Fläche darunter ist dieselbe Farbe mit
   Soft-Alpha, damit die Kurve wie in der Referenz «sitzt» statt zu schweben. */
.gz-spark { display: grid; gap: 3px; min-width: 0; color: rgb(var(--gz-feld)); }
.gz-spark .sparkline { height: 34px; }
.gz-spark svg polygon { opacity: .14; }
.gz-spark i {
  font-style: normal; font-size: 11.5px; color: var(--text-tertiary);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* --- 1. Kopf + Fusszeile ------------------------------------------------ */
.gz-kopf { margin-bottom: 20px; }
.gz-kopf h1 {
  margin: 0; font-size: 26px; font-weight: 650; letter-spacing: -.02em;
  color: var(--text-primary);
}
/* Panel-Kopf mit Zeichen — dieselbe Sprache wie die Kacheln, eine Stufe kleiner. */
.gz-panel__titel { display: flex; align-items: center; gap: 10px; min-width: 0; }
.gz-panel__titel .gz-ic { --gz-ic-gr: 26px; }
/* «Alle anzeigen →» im Panel-Kopf, wie in der Referenz («Alle Projekte
   anzeigen →», «Alle Metriken →»). Der Pfeil sitzt am Wort, nicht daneben. */
.gz-mehr { gap: 6px; }
.gz-mehr svg { width: 13px; height: 13px; }

/* Die Systemlage-Fusszeile (.gz-lage) ist seit 03.09. weg — Owner am Bild:
   «das muss ein separater Bereich sein, nicht auf der Zentrale». Ihr Ort
   ist #/v/systemlage (Einstellen). */

/* --- 2. Kachelzeile ----------------------------------------------------- */
/* Spalten-Autofluss: vier oder sechs Kacheln füllen dieselbe eine Reihe. Wer
   ein Recht nicht hat, sieht die Kachel gar nicht (Migration 099) — eine feste
   Sechserreihe hinterliesse dort eine Lücke. */
/* EINE KACHEL-BAUART (25.08.): die Basisbauform `.stat` (docs/design/grund.css)
   traegt seit heute wieder Flaeche, Haarlinie und Radius 14 — die Fuge kommt
   damit zurueck, sonst stuenden die Karten kantenbuendig aneinander. */
.gz-kacheln {
  display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr);
  gap: 14px; margin-bottom: 20px;
}
/* Zeichen oben, Label darunter, dann die Zahl — nicht Zeichen NEBEN Label:
   in der 2er-Reihe am Handy bleiben so keine 110px für «Offene Rechnungen»,
   und ein abgeschnittenes Label ist genau das Billige, das hier weg soll. */
.gz-kachel { justify-content: flex-start; padding: 18px; gap: 3px; }
.gz-kachel .gz-ic { margin-bottom: 10px; }
/* Die Zahl bleibt bei 26px/650/-.5 aus dem Fundament (.stat__value) — die
   Referenz-Dichte, kein eigener Sondergrad. */
/* Rot steht an der Zahl, die warnt (die Zusatzzeile) — nicht an der grossen
   daneben. ZIELBILD: «Warnung Bernstein, Fehler Rot, sparsam». */
.gz-kachel .stat__sub.is-warn { color: var(--warn-strong); }
.gz-kachel .stat__bar { margin-top: auto; }
/* Ein Balken, der einen Rückstand misst, trägt die Warnfarbe; ein Balken, der
   Fortschritt misst, den Akzent. Die Farbe folgt der Bedeutung, nicht dem Ort. */
.stat__bar.is-warn > i { background: var(--warn); }

/* --- 3. Raster ---------------------------------------------------------- */
.gz-panel { margin-bottom: 0; }

/* --- Bereichs-Portfolio ------------------------------------------------- */
/* 290px statt 215px: erst ab dieser Breite trägt die Kopfzeile Zeichen, vollen
   Titel UND den Zustands-Chip nebeneinander — genau die Anatomie der
   Referenz-Projektkarte (13_25_27). Bei 215px waren es vier Spalten, in denen
   der Chip in eine zweite Kopfzeile brach; darum stand er früher unten. */
/* FLACH STATT KASTEN (Owner «Widget», 2026-08-13): aus vier losen Karten wird
   ein Raster mit inneren Trennlinien — genau die Struktur, die der Fussbereich
   dieser Flaeche seit dem 31.07. schon hat («EIN Kasten, innen Trennlinien —
   nicht drei lose Boxen»), nur ohne den Kasten aussen herum.
   Feste zwei Spalten statt `auto-fill`: eine Linie zwischen den Spalten setzt
   voraus, dass die Spaltenzahl bekannt ist. Gemessen (Buehne 13.08., 1680px):
   `auto-fill minmax(290px,1fr)` ergab in dieser Spalte ohnehin genau 2 — die
   Regel schreibt also fest, was schon gerendert wurde. */
.gz-portfolio {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px;
  align-items: stretch;
}
/* 25.08.: die Karte traegt ihre Kante wieder selbst — die Spaltenlinie ist
   damit eine doppelte und wird zur Null gesetzt (der Selektor bleibt stehen,
   er ist der Ort, an dem die Frage «Linie oder Fuge» beantwortet ist). */
.gz-portfolio > .gz-karte:nth-child(2n) { border-left: 1px solid var(--border); }
@media (max-width: 720px) {
  .gz-portfolio { grid-template-columns: minmax(0, 1fr); }
  .gz-portfolio > .gz-karte:nth-child(2n) { border-left: 1px solid var(--border); }
}
/* Vier feste Zeilen: Kopf · Zahlen · Kurve/Fortschritt/Zustand · Tür. Die
   dritte dehnt sich — dadurch stehen alle Türen einer Reihe auf einer Linie,
   auch wenn eine Karte weniger zu sagen hat. */
/* DIE BEREICHSKARTE IST WIEDER EINE KARTE (25.08.). Vom 13.08. bis heute war
   sie eine Rasterzelle ohne Kante mit einer Haarlinie unten — auf dem Bild
   nicht von der Zeile darueber zu unterscheiden. Die Referenz
   (docs/design/referenzen/Portaluikomplett/«… 13_25_27.png», Block «PROJEKT
   OVERVIEW») zeigt jede Bereichskarte als 2×2-Karte mit eigener Flaeche,
   Kante und Radius. EINE Stufe (`--surface`), kein Schatten, kein Schweben. */
.gz-karte {
  display: grid; grid-template-rows: auto auto 1fr auto; gap: 14px;
  padding: 18px 20px; min-height: 168px;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-card); color: inherit; text-decoration: none;
  transition: background var(--transition), border-color var(--transition);
}
.gz-karte:hover { background: var(--surface-hover); border-color: var(--line-strong); }
.gz-karte:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* Ein Bereich ohne Lesequelle bekommt KEINE leere Riesenkarte (FINISH-
   STANDARD 6): er wächst nicht auf die Höhe der Nachbarn, sondern bleibt so
   kurz, wie er zu sagen hat. */
.gz-karte--knapp { align-self: start; min-height: 0; grid-template-rows: repeat(4, auto); }
/* Kopfzeile wie in der Referenz: Zeichen · Titel · Zustands-Chip ganz rechts.
   Der Titel darf NIE abgeschnitten werden — «Standortbetreiber» als
   «Standortb…» ist genau das Billige, das hier verschwinden soll. Deshalb
   `nowrap` am Träger (der Chip rutscht nie in eine zweite Zeile) und
   `flex: 0 0 auto` am Chip: die Breite geht dem Titel zu, nicht dem Chip. */
.gz-karte__kopf { display: flex; align-items: center; gap: 10px; min-width: 0; flex-wrap: nowrap; }
.gz-karte__kopf .gz-ic { --gz-ic-gr: 28px; }
.gz-karte__kopf .gz-chip { flex: 0 0 auto; margin-left: auto; }
.gz-karte__titel {
  flex: 0 1 auto; min-width: 0; font-size: 15px; font-weight: 600;
  color: var(--text-primary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* EINE grosse Zahl, daneben die Nebenwerte klein — die Hierarchie hält die
   Karte auch in einer 240px-Spalte ruhig und umbruchfest. */
/* Referenz-Dichte, identisch mit der Kachelzeile: 26px/650/-.5px. */
/* Chip-Reihe: gemessene Nebentatsachen als Wort-Chips (Referenz «Status als
   Wort-Chips»). Sie tragen die Karte dort, wo es keine Reihe für eine Kurve
   gibt — statt einer Leerfläche steht eine Tatsache. */
/* Balken und sein Prozentwert in EINER Zeile — der Wert rechtsbündig am Ende
   des Balkens, wie an jeder Projektkarte der Referenz. Tabellenziffern, damit
   er beim Auffrischen nicht wandert. */
.gz-karte__balken { display: flex; align-items: center; gap: 10px; min-width: 0; }
.gz-karte__balken .stat__bar { flex: 1 1 auto; min-width: 0; }
.gz-karte__pct {
  flex: 0 0 auto; font-size: 12.5px; font-weight: 600; color: var(--text-secondary);
  font-variant-numeric: tabular-nums lining-nums;
}
.gz-karte__zustand { font-size: 12px; color: var(--text-secondary); min-width: 0; }

/* Zustands-Chip: Wort in Pillenform, gleiche Semantik wie app-weit. */
.gz-chip--gut { background: rgba(var(--good-rgb), .13); color: var(--good-strong); }
.gz-chip--warn { background: rgba(var(--warn-rgb), .13); color: var(--warn-strong); }
.gz-chip--schlecht { background: rgba(var(--bad-rgb), .13); color: var(--bad-strong); }
.gz-chip--still { background: rgba(var(--tint-rgb), .07); color: var(--text-secondary); }
/* 1:1-Huelle: der Chip im KARTEN-Kopf ist in der Referenz ein SATTES Feld
   (PRIORITAET-Chip gemessen #268187), kein Toenungsfeld. Nur im Karten-Kopf —
   Chips in Listenzeilen bleiben ruhig getoent. Dunkle Schrift = Kontrast. */
.gz-karte__kopf .gz-chip--gut { background: var(--accent-deep); color: #04211f; }
.gz-karte__kopf .gz-chip--warn { background: var(--warn); color: #241503; }
.gz-karte__kopf .gz-chip--schlecht { background: var(--bad); color: #2a0b08; }

/* --- Missionen (rechte Spalte) ------------------------------------------ */
/* Referenz-Aktivitätsspalte: wer (Initialen) · woran · Zustand, darunter der
   nächste Schritt links und die Frist rechts. */
.gz-mission {
  display: grid; gap: 6px; padding: 12px 14px; margin-bottom: 8px;
  background: var(--surface-2); border-radius: var(--radius-card);
  color: inherit; text-decoration: none;
  transition: background var(--transition);
}
.gz-mission:last-of-type { margin-bottom: 0; }
.gz-mission:hover { background: var(--surface-3); }
.gz-mission:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.gz-mission__kopf { display: flex; align-items: center; gap: 9px; min-width: 0; }
.gz-mission__titel {
  flex: 1 1 auto; min-width: 0; font-size: 13.5px; font-weight: 600; color: var(--text-primary);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.gz-mission__zeile { display: flex; align-items: baseline; gap: 10px; min-width: 0; }
.gz-mission__schritt {
  flex: 1 1 auto; min-width: 0; font-size: 12.5px; color: var(--accent-strong);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.gz-mission__fuss {
  flex: 0 0 auto; font-size: 11.5px; color: var(--text-tertiary);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.gz-mission__fuss.is-spaet { color: var(--bad-strong); }

/* --- Aktivitäten: mehrspaltiger Streifen über die volle Breite ----------- */
/* Unten quer statt in der schmalen Spalte: dort liess er die linke Seite
   leerlaufen, hier trägt er die Fläche zu Ende (Referenz-Cockpit).
   Zeilenaufbau der Referenz: Initialen links, Sache in der Mitte, Zeit rechts. */
/* 380px je Spalte, nicht 280: mit Initialen links und Zeit rechts blieben für
   «Rita Beispiel (Berater) · Coiffure Beispiel 1 AG» sonst 200px, und der
   Eintrag endete auf «Coiffu…». Ein abgeschnittener Name ist keine Aktivität. */
.gz-akt { display: grid; grid-template-columns: repeat(auto-fill, minmax(380px, 1fr)); gap: 8px; }
/* Die Leer-Zeile im Aktivitaeten-Raster nimmt die ganze Breite. Der Name ist
   jetzt der des Hauses (`gz-leer` gefallen 21.08.) — die PLATZIERUNG bleibt
   hier, denn sie gehoert dem Raster, nicht der Form. */
.gz-akt > .empty-state--zeile { grid-column: 1 / -1; }
.gz-akt__item {
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center; gap: 10px; min-width: 0;
  padding: 10px 12px; background: var(--surface-2); border-radius: var(--radius-card);
}
.gz-akt__leib { display: grid; gap: 2px; min-width: 0; }
.gz-akt__titel { font-size: 13px; font-weight: 600; color: var(--text-primary); }
.gz-akt__sub {
  font-size: 12.5px; color: var(--text-secondary);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.gz-akt__zeit {
  font-size: 11.5px; color: var(--text-tertiary);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}

/* --- Leerfall ----------------------------------------------------------- */
/* ENTFERNT, nicht ersetzt: .gz-leer · .gz-leer__weg (+ :hover, :focus-visible)
   GEFALLEN 21.08.2026 — die Leer-Zeile des Hauses ist EINE Form:
   `.empty-state.empty-state--zeile` + `.empty-state__weg` in docs/design/grund.css.
   Ihr Helfer in views/zentrale.js stand zeichengleich auch in
   views/manager-today.js unter dem Namen `ck-leer` — zwei Namen, EIN Satz. */

/* --- Tablet: das Raster faltet, die Kacheln rücken zusammen -------------- */
@media (max-width: 1240px) {
  .gz-kacheln { grid-auto-flow: row; grid-template-columns: repeat(3, minmax(0, 1fr)); }
  /* ENTFERNT 25.08. (Rueckweg git): die beiden Rest-Strich-Regeln
     `.gz-kacheln > .gz-kachel:nth-child(3n + 1 | n + 4)`. Die geschlossene
     Karte trennt sich mit ihrer Fuge selbst; die Regeln haetten ihr beim
     Umbruch die linke Kante ausgeschnitten. */
}
@media (max-width: 1040px) {
  .gz-portfolio { grid-template-columns: repeat(auto-fill, minmax(290px, 1fr)); }
}

/* --- Handy: Kacheln 2 je Reihe, Portfolio einspaltig -------------------- */
@media (max-width: 640px) {
  .gz-kopf h1 { font-size: 22px; }
  .gz-kacheln { grid-auto-flow: row; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
  /* KEINE HALB LEERE REIHE (05.09.2026) — dieselbe Regel wie beim
     Kennzahlen-Streifen des Hauses (docs/design/grund.css, «DAS GLEICHE
     RASTER»). Gemessen am Live-Bild der Zentrale (390 px): drei Kacheln
     standen als 2+1, und die dritte hielt nur die halbe Breite; daneben lag
     Leere. Das iPhone der Referenz (Portaluikomplett/«… 13_25_27.png») zeigt
     ein gleichmaessiges Raster ohne Waise. */
  .gz-kacheln > *:last-child:nth-child(odd) { grid-column: 1 / -1; }
  .gz-kachel { padding: 14px 15px; }
  /* ENTFERNT 25.08. (Rueckweg git): die drei Haarlinien-Regeln
     `.gz-kacheln > .gz-kachel` / `:nth-child(2n + 1)` / `:nth-child(n + 3)`. */
  .gz-kachel .gz-ic { --gz-ic-gr: 28px; margin-bottom: 8px; }
  .gz-portfolio { grid-template-columns: minmax(0, 1fr); }
  .gz-karte { min-height: 0; }
  .gz-akt { grid-template-columns: minmax(0, 1fr); }
  /* Am Handy bleiben neben Initialen und Zeit rund 220px — zu wenig für
     «Rita Beispiel (Berater) · Coiffure Beispiel 1 AG». Statt den Firmennamen
     abzuschneiden, bricht die Zeile um: Mobile ist keine Restgrösse
     (ZIELBILD «Handy- und Desktop-Fassung gleichwertig»). */
  .gz-akt__item { align-items: start; }
  .gz-akt__sub { white-space: normal; overflow: visible; }
  .gz-akt__zeit { padding-top: 1px; }
}
/* Der Tapflächen-Boden gilt auf jedem Touch-Gerät, nicht nur unter 640px
   (Memory project_tablet_touch_breakpoint: 768/1024px sind die Bruchzone). */
@media (max-width: 1024px), (pointer: coarse) {
  .gz-kachel, .gz-karte, .gz-mission { min-height: 44px; }
  /* ENTFERNT: .gz-leer__weg — der Touch-Boden steht jetzt am Haus-Weg
     (`.empty-state__weg`, grund.css) und gilt damit ueberall. */
}

/* ============================================================
   AUFBAU nach der Owner-Referenz 13_25_27.png (31.07.)
   Befehlszeile oben · Chat in der Mitte · Kommandozentrale rechts.
   Massstab der Referenz: RUHE. Eine grosse Zahl je Kachel, ein Label,
   ein farbiges Zeichenfeld — sonst nichts.
   ============================================================ */

/* Zwei Spalten wie in der Referenz: Kommandozentrale breiter, Chat schmaler.

   W6.4 / SB1 (10.08.) — DIE SPALTEN SIND GETAUSCHT, die Breiten nicht.
   Owner (B8, 2×): «der kann ganz am Schluss kommen.» Die schmale Spalte trug
   den Assistenten und stand LINKS: am Desktop das Erste im Blick, und unter
   1180px — wo das Raster auf eine Spalte fällt — die erste ganze Karte des
   Hauses. Jetzt trägt die erste Spalte die Kommandozentrale (1fr) und die
   zweite den Assistenten (360px). Das Raster bleibt zweispaltig, die Breiten
   bleiben, die Reihenfolge im DOM ist dieselbe wie im Bild (views/zentrale.js)
   — kein `order`, damit Tastatur und Vorleseprogramm dieselbe Folge hören,
   die das Auge sieht. */
.gz-buehne { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 360px); gap: 18px; align-items: start; }
.gz-chat { display: flex; flex-direction: column; gap: 14px; }
.gz-chat__lauf { display: flex; flex-direction: column; gap: 12px; }
.gz-chat__missionen { border-top: 1px solid var(--border); padding-top: 12px; }
.gz-chat__mtitel {
  display: block; font-size: 11.5px; font-weight: 600; letter-spacing: .04em;
  text-transform: uppercase; color: var(--text-secondary); margin-bottom: 8px;
}

.gz-kz { display: flex; flex-direction: column; gap: 18px; }
.gz-kz__titel { margin: 0; font-size: 20px; font-weight: 650; letter-spacing: -.01em; }
/* DIE DREI ABSCHNITTE DER KOMMANDOZENTRALE SIND KARTEN (25.08.2026).
   «Mein Tag», «Was wartet» und «Bereiche» waren bis heute drei Stapel ohne
   Kante untereinander — genau das, was der Owner an diesem Tag beschrieben
   hat: «Alles ist einfach auf dunkle Flaeche geschrieben.» Dieselbe Karte wie
   `.panel`, damit die Zentrale nicht eine eigene Bauart fuer «Abschnitt»
   fuehrt. Die Referenz zeigt es so
   (docs/design/referenzen/Portaluikomplett/«… 13_25_27.png»: «Aktive Agenten»,
   «System Performance», «Letzte Aktivitaeten» als drei Karten nebeneinander,
   «PROJEKT OVERVIEW» als Karte darueber). */
.gz-kz__block, .gz-kz__spalte {
  display: flex; flex-direction: column; gap: 10px;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-card); padding: 18px 20px;
}
.gz-kz__kopf { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
/* EINHEIT §1.5: der Abschnitts-Titel ist 13px in gemischter Schreibung, mit
   Laufweite und in Textfarbe — genau wie `.panel h3`. Gesperrte Versalien
   tragen im ganzen Haus GENAU EINE Aufgabe: den Tabellenkopf. Hier standen
   sie fuer «MEIN TAG», «WAS WARTET», «BEREICHE» — drei Ueberschriften, die
   dadurch leiser waren als die Zeilen darunter. */
.gz-kz__label {
  font-size: 13px; font-weight: 600; letter-spacing: .02em;
  text-transform: none; color: var(--text-primary);
}

/* Die Kacheln der Referenz: vier in einer Reihe, jede EINE Aussage. */
/* Drei je Reihe statt sechs: bei sechs blieben je ~160px und der Zusatz brach
   zweizeilig um — genau der Eindruck «billig». Mit drei je Reihe hat jede
   Kachel Luft, und keine Zahl geht verloren. */
.gz-buehne .gz-kacheln {
  /* grid-auto-flow der Grundregel steht auf `column` — das ordnet ALLE Kacheln
     in EINE Reihe und ueberstimmt jede Spaltenangabe. In der Buehne fliesst es
     darum zeilenweise: drei je Reihe, jede mit Luft. */
  grid-auto-flow: row;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 12px;
}
.gz-buehne .gz-kachel { padding: 14px 16px; gap: 6px; }
.gz-buehne .gz-kachel .stat__bar { display: none; }   /* Ruhe: kein Balken in der Kopfzeile */

@media (max-width: 1180px) {
  .gz-buehne { grid-template-columns: minmax(0, 1fr); }
  .gz-buehne .gz-kacheln { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 720px) {
  .gz-buehne .gz-kacheln { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* Fussbereich der Kommandozentrale: zwei Spalten wie in der Referenz
   («System Performance» neben «Letzte Aktivitäten»). */
/* KAESTEN IN EINER REIHE TEILEN IHRE UNTERKANTE (Hausregel 06.09.2026).
   Hier stand `align-items: start`; damit war jeder Kasten nur so hoch wie sein
   Inhalt und die Unterkanten flatterten. Anlass ist die Betreiber-Akte
   («so viele Bereiche versetzt und nicht schoen geordnet», 06.09.), aber der
   Fehler steckte in vier Blaettern zugleich — er wird darum an jeder Quelle
   entfernt, nicht an einer Stelle ueberschrieben. `stretch` ist die Vorgabe
   von Grid; die Zeile faellt ersatzlos weg. Waechter:
   `npm run test:kastenkanten`. */
/* Hier wiegt sie doppelt: zwischen den beiden Spalten laeuft eine Haarlinie
   (`.gz-kz__spalte + .gz-kz__spalte { border-left: … }`, weiter unten). Mit
   `start` reichte diese Linie nur so weit wie die KUERZERE Spalte und endete
   mitten in der Luft. */
.gz-kz__fuss { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 18px; }
.gz-verlauf__zeile { display: flex; flex-direction: column; gap: 4px; }
.gz-verlauf__kopf { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
.gz-verlauf__wort { font-size: 12.5px; color: var(--text-primary); }
.gz-verlauf__zeit { font-size: 11.5px; }

/* Meta-Zeile der Bereichs-Karte: hoechstens drei Angaben, mit Trennpunkt. */
.gz-karte__meta { display: flex; flex-wrap: wrap; gap: 4px 10px; font-size: 12px; }
.gz-karte__meta > span + span::before { content: '· '; color: var(--text-secondary); }

@media (max-width: 900px) {
  .gz-kz__fuss { grid-template-columns: minmax(0, 1fr); }
}

/* Die Begruessung des Agenten — Referenz: eine Sprechblase mit Absender,
   zwei kurzen Saetzen und einer Frage. Ruhig, nicht bunt. */
.gz-chat__block { display: flex; flex-direction: column; gap: 6px; }
.gz-chat__wer { display: flex; align-items: center; gap: 8px; font-size: 12.5px; }
.gz-chat__wer b { font-weight: 600; }
.gz-chat__satz { margin: 0; font-size: 13.5px; line-height: 1.5; color: var(--text-primary); }
.gz-chat__frage { color: var(--text-secondary); }

/* Kommandozentrale — Anatomie 1:1 aus 13_25_27.png */

.gz-agenten { display: flex; flex-direction: column; gap: 10px; }
.gz-agent { display: flex; align-items: center; gap: 10px; }
.gz-agent__wer { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.gz-agent__wer b { font-size: 12.5px; font-weight: 600; }
.gz-agent__stand { white-space: nowrap; font-size: 11.5px; }

/* Karte 01.08., Position 7: die dritte Spalte «System-Leistung» ist entfallen —
   ohne Messwerte schrieb sie denselben Nicht-Satz «Noch keine Messwerte», der
   schon im Seitenstreifen jeder Flaeche und auf der Systemlage stand. Mit ihr
   sind `.gz-leistung*` weg (kein Verwender mehr in public/src); der Fussbereich
   traegt zwei gleich breite Spalten statt drei. */
.gz-kz__fuss { grid-template-columns: repeat(2, minmax(0, 1fr)); }
@media (max-width: 900px) { .gz-kz__fuss { grid-template-columns: minmax(0, 1fr); } }

/* In der schmalen Spalte der Kommandozentrale ist die Aktivitaetszeile eng.
   Die Referenz stapelt dort: fette Zeile, graue Zeile darunter, Zeit rechts —
   nichts wird abgeschnitten. */
.gz-kz__fuss .gz-akt__item { grid-template-columns: auto minmax(0, 1fr); row-gap: 2px; }
.gz-kz__fuss .gz-akt__sub { white-space: normal; overflow: visible; }
/* Die Zeit bleibt RECHTS (Referenz-Anatomie) — nur der Untertitel darf
   umbrechen, statt abgeschnitten zu werden. */
.gz-kz__fuss .gz-akt__item { grid-template-columns: auto minmax(0, 1fr) auto; }
.gz-kz__fuss .gz-akt__zeit { font-size: 11.5px; white-space: nowrap; }

/* ===== DICHTE-PASS 31.07. — Nebeneinander-Beleg gegen `13_25_27.png` =====
   Die Referenz ist DICHT: kompakte Kacheln, enge Abstände, sichtbare feine
   Kanten, kleine Schrift. Unser Stand war auf allen Achsen ~1.5× so gross —
   das ist der «aufgeblasen/billig»-Eindruck. Hier wird der Massstab der
   Referenz übernommen; jede Regel unten SENKT bewusst eine Grösse. */

/* Kacheln: Referenz-Anatomie (Zeichen · grosse Zahl · CAPS-Label · Subzeile),
   kompakt, EINE Reihe die trägt. */
.gz-buehne .gz-kacheln {
  /* VIER Kacheln in EINER Reihe wie die Referenz — auto-fit auf gleiche
     Anteile: bei vieren je ~230px, bei dreien (Manager) breiter. Nie eine
     Waise in einer zweiten Reihe. */
  grid-auto-flow: row;
  grid-template-columns: repeat(auto-fit, minmax(0, 1fr));
  /* EINE KACHEL-BAUART (25.08.): die Karte traegt ihre Kante selbst, die Fuge
     kommt zurueck. */
  gap: 14px;
}
.gz-buehne .gz-kachel { padding: 18px; gap: 6px; }
/* ENTFERNT 25.08. (Rueckweg git): die Trennlinie
   `.gz-buehne .gz-kacheln > .gz-kachel + .gz-kachel { border-left }` — sie war
   der Ersatz fuer die fehlende Karte und ist jetzt eine doppelte Kante. */
.gz-buehne .gz-kachel .stat__value { font-size: 26px; line-height: 1.12; }
/* EINHEIT §1.5: Kachel-Label 12.5px, gemischte Schreibung. Gesperrte Versalien
   tragen genau EINE Aufgabe — den Tabellenkopf. Die Zentrale war die einzige
   Flaeche, die sie auch fuer ihre Kachel-Label benutzte (11px/.08em/CAPS). */
.gz-buehne .gz-kachel .stat__label {
  font-size: 12.5px; letter-spacing: 0; text-transform: none;
  color: var(--text-secondary);
}
.gz-buehne .gz-kachel .stat__sub { font-size: 11.5px; }
.gz-buehne .gz-kachel .gz-ic { width: 26px; height: 26px; }

/* Bereichs-Karten: 2×2 wie die Referenz, kompakt, Balken als Held. */
.gz-portfolio, .gz-buehne [data-slot="bereiche"] {
  /* 25.08.: 14px — dieselbe Fuge wie zwischen zwei Kacheln und zwischen zwei
     Abschnitten. Bei 10px standen zwei Karten-Kanten enger als der
     Innenabstand der Karte selbst. */
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px;
}
.gz-karte { padding: 16px 18px; gap: 8px; border: 1px solid var(--border); border-radius: var(--radius-card); }
.gz-karte__titel { font-size: 13px; }
.gz-karte__sub { display: flex; gap: 8px; font-size: 11.5px; }
.gz-karte__balken { display: flex; align-items: center; gap: 10px; }
.gz-karte__balken .stat__bar { flex: 1; }
.gz-karte__pct { font-size: 11.5px; }
.gz-karte__meta { font-size: 11px; gap: 3px 8px; }
.gz-karte--mehr {
  /* Kompakte Zeile über die volle Breite — als vierte Zelle im 2×2 stand sie
     als riesiger leerer Kasten neben den Karten (Nebeneinander-Beleg). */
  grid-column: 1 / -1;
  display: flex; align-items: center; justify-content: center; gap: 8px;
  padding: 9px 14px; font-size: 12px; color: var(--text-secondary);
  text-decoration: none;
}
.gz-karte--mehr:hover { color: var(--text-primary); }

/* Chat: Missionszeilen ruhig + Eingabefeld unten wie die Referenz. */
.gz-mission { padding: 9px 10px; gap: 5px; }
.gz-mission__titel { font-size: 12.5px; }
.gz-mission__zeile { display: flex; justify-content: space-between; gap: 10px; font-size: 11.5px; }
.gz-mission__balken { height: 3px; }
.gz-mission__fuss { font-size: 11.5px; color: var(--text-secondary); white-space: nowrap; }
.gz-mission__fuss.is-spaet { color: var(--bad); }
.gz-chat__eingabe {
  display: flex; gap: 8px; margin-top: 12px; padding-top: 12px;
  border-top: 1px solid var(--border);
}
.gz-chat__eingabe input {
  flex: 1; min-width: 0; background: var(--surface-inset);
  border: 1px solid var(--border); border-radius: var(--radius-card);
  padding: 9px 12px; font-size: 12.5px; color: var(--text-primary);
}
.gz-chat__eingabe input:focus { outline: none; border-color: var(--accent); }
.gz-chat__senden { padding: 8px 12px; border-radius: var(--radius-card); }

/* Kommandozentrale gesamt: engere Vertikale. */
.gz-kz { gap: 16px; }
.gz-kz__titel { font-size: 15px; }
.gz-kz__label { font-size: 13px; letter-spacing: .02em; }
.gz-kz__fuss { gap: 14px; }
.gz-akt__item { padding: 8px 10px; }
.gz-akt__titel { font-size: 12px; }
.gz-akt__sub { font-size: 11px; }
@media (max-width: 900px) {
  .gz-portfolio, .gz-buehne [data-slot="bereiche"] { grid-template-columns: minmax(0, 1fr); }
}

/* Handy: zwei Kacheln je Reihe — auto-fit wuerde alle vier in eine Reihe
   quetschen (und collabierte 0px-Spuren erzeugen). */
@media (max-width: 720px) {
  .gz-buehne .gz-kacheln { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  /* Und keine Waise in der letzten Reihe: die Kommandozentrale zeigt der
     Leitung DREI Kacheln (offene Rechnungen · offene Offerten · heute im
     Team) — die dritte stand am Telefon halb breit neben einer leeren
     Haelfte (Live-Bild 390 px, 05.09.). Dieselbe Regel wie im Haus
     (docs/design/grund.css, «DAS GLEICHE RASTER»). */
  .gz-buehne .gz-kacheln > *:last-child:nth-child(odd) { grid-column: 1 / -1; }
  /* ENTFERNT 25.08. (Rueckweg git): die beiden Rest-Strich-Regeln
     `.gz-buehne .gz-kacheln > .gz-kachel:nth-child(2n + 1 | n + 3)`. Der
     Strich, der im Nichts anfaengt, kann gar nicht mehr entstehen — die
     Kachel ist rundum geschlossen und die Fuge trennt in beide Richtungen. */
}

/* ===== RAHMEN-UND-FARBE-PASS 31.07. — zweiter Nebeneinander-Beleg =====
   Owner: «Die Struktur, die Farbe … der untere rechte Bereich ist einfach
   irgendwo neben aussen.» Exakt: in der Referenz ist JEDER Abschnitt ein
   umrandetes Panel auf gehobener Fläche mit türkis getönter Kante, und die
   drei unteren Spalten sind EIN Kasten mit inneren Trennlinien. Bei uns
   schwamm alles rahmenlos auf flachem Schwarz — darum wirkte die
   Aktivitäten-Liste «draussen». Dieser Pass baut die Referenz-Struktur. */

/* Türkis getönte Kante — die Farbwahrheit der Referenz. */
.gz-buehne { --gz-kante: rgba(var(--accent-rgb), .16); }

/* FLACH STATT KASTEN (Owner «Widget», 2026-08-13) — DER RAHMEN-PASS VOM 31.07.
   WIRD ZURUeCKGENOMMEN, SEINE STRUKTUR BLEIBT.
   Damals war der Befund richtig («der untere rechte Bereich ist einfach
   irgendwo neben aussen») und die Antwort war: jedem Abschnitt einen Rahmen.
   Der Owner hat am 13.08. das Gegenteil verlangt — «wie ein Wizard oder
   Widget» ist genau die Anmutung, die diese Rahmen erzeugen. Was BLEIBT, ist
   der wertvolle Teil des Passes: «EIN Kasten, innen Trennlinien — nicht drei
   lose Boxen». Die inneren Trennlinien tragen die Gliederung jetzt allein;
   der Kasten aussen faellt. */
.gz-buehne .gz-chat {
  background: transparent;
  border: 0;
  border-top: 1px solid var(--border);
  border-radius: 0;
  padding: 17px 0 0;
}
.gz-kz__fuss {
  background: transparent;
  border: 0;
  /* 25.08.: die beiden Spalten sind seit heute je eine Karte — der Streifen
     darum braucht weder Kante noch Trennlinie, nur die Fuge. */
  border-top: 0;
  border-radius: 0;
  padding: 0;
  gap: 14px;
}
.gz-kz__spalte { min-width: 0; }
.gz-kz__spalte:first-child { padding-left: 20px; }
.gz-kz__spalte + .gz-kz__spalte { border-left: 1px solid var(--border); }
.gz-kz__fuss .gz-akt__item { background: transparent; padding: 7px 0; }
/* ENTFERNT, nicht ersetzt: `.gz-kz__fuss .empty-state { font-size: 12px }`.
   Dieselbe Sorte namenlose Zweitbauart wie `.gz .empty-state` weiter unten,
   nur kleiner: der Haus-Leerzustand sah in DIESEM Fussstreifen anders aus als
   ueberall sonst. Eine Bauart heisst EIN Mass — die Haus-Zeile bringt 13px
   mit, und das ist hier gemessen genug Platz. */

/* 25.08.: Kacheln und Karten tragen wieder die Flaeche der Referenz
   (docs/design/referenzen/Portaluikomplett/«… 13_25_27.png» — jede KPI-Kachel
   und jede Projekt-Karte eine eigene Karte). Es ist EINE Stufe, kein Schweben:
   kein Schatten, keine zweite Erhoehung. Die tuerkis getoente Kante
   `--gz-kante` bleibt fuer die Bedienelemente dieser Flaeche in Gebrauch
   (Chat-Eingabe, unten in diesem Block). */
.gz-buehne .gz-kachel,
.gz-buehne .gz-karte {
  background: var(--surface);
}


/* HIER STANDEN ZWEI HÖFE (`0 0 9px` türkis und bernstein), bis zum 03.08.
   Sie kamen aus dem Wort «leuchtet» in der Passbeschreibung, nie aus dem Bild.
   Nachgemessen an docs/design/referenzen/Portaluikomplett/…13_25_27.png,
   senkrechter Schnitt bei x=1050 durch den 78 %-Balken der Projektkarte:
     Grund darüber   13,21,27
     eine Zeile über dem Balken   14,10,18   ← DUNKLER
     Balkenkern      18,217,211
     zwei Zeilen darunter          3, 1, 9   ← DUNKLER
     Grund darunter  10,20,27
   Das Bild setzt den Balken mit einer dunklen Naht gegen seinen Grund, nicht
   mit einem Leuchtradius. Die Aussage trägt die FÜLLUNG: türkis, wo es läuft
   (`.gz .stat__bar > i`), Bernstein im Rückstand (`.gz .stat__bar.is-warn > i`)
   — beides steht weiter unten in diesem Block und bleibt unangetastet.
   Wächter gegen die Rückkehr: _stil_integration_test.mjs, Prüfung «Kein
   farbiger Leucht-Hof» — sie liest jede box-shadow-Ebene dieses Blattes. */

/* Chat-Eingabe: Kante ebenfalls getönt. */
.gz-chat__eingabe input { border-color: var(--gz-kante); }

@media (max-width: 900px) {
  .gz-kz__spalte + .gz-kz__spalte { border-left: 1px solid var(--border); border-top: 1px solid var(--border); padding-top: 18px; margin-top: 0; }
}

/* Zwei Wurzeln aus dem Render 31.07. abends:
   · Die Tür «N weitere Bereiche» erbte min-height:168px der Basiskarte und
     stand als riesiger leerer Kasten da.
   · Die Aktivitätsliste erzwingt in der Basisregel 380px-Spalten — in der
     ~300px-Fussspalte ragten die Zeilen damit RECHTS AUS DEM PANEL heraus
     (Owner: «irgendwo neben aussen»). Hier: eine Spalte, die sich fügt. */
/* 44px bleibt der Tap-Boden am Handy (Memory mobile-pwa): die Tür ist klein,
   aber nie kleiner als ein Daumen. */
.gz-karte--mehr { min-height: 44px; }
.gz-kz__fuss .gz-akt { grid-template-columns: minmax(0, 1fr); }
.gz-kz__fuss .gz-akt__zeit { font-size: 11px; }

/* ===== MATERIAL-PASS 31.07. — dritter Nebeneinander-Beleg =====
   Owner: «sieht immer noch nicht aus wie das Referenzbild, es wird immer
   billiger». Die Anatomie stand, das MATERIAL fehlte. Vier Wahrheiten der
   Referenz `13_25_27.png`, die die vorigen Pässe ausgelassen haben:
     1. Die KPI-Box ist TÜRKIS und leuchtet — und steht LINKS NEBEN der
        grossen Zahl, nicht klein darüber. Bereichsfarben gehören den
        Portfolio-Karten, nie der Kachelzeile.
     2. Der Fortschrittsbalken ist ein satter 6px-Strang mit Schein — kein
        Haarstrich.
     3. Die Fläche hat TIEFE: ein grüner Schimmer liegt über dem Schwarz,
        Karten stehen mit Türkis-Hauch darauf.
     4. Überfällig ist eine WARNUNG (Bernstein), kein Systemfehler (Rot) —
        die Referenzliste ist ruhig, die Wahrheit bleibt. */

/* 3. Tiefe: der Schimmer der Referenz, scoped — kein Fundament-Token ändert sich. */
.gz {
  background:
    radial-gradient(1100px 540px at 78% -8%, rgba(var(--accent-rgb), .085), transparent 60%),
    radial-gradient(880px 480px at -6% 108%, rgba(var(--accent-rgb), .05), transparent 55%);
}
.gz-buehne { --gz-kante: rgba(var(--accent-rgb), .2); }
/* FLACH STATT KASTEN (Owner «Widget», 2026-08-13): hier lag der letzte, am
   spaetesten gesetzte Grund — er hat jedes der fuenf Stuecke wieder zu einer
   abhebenden Flaeche gemacht und damit alle Regeln darueber ueberstimmt.
   Punkt 3 des Passes («die Flaeche hat TIEFE, ein Schimmer liegt ueber dem
   Schwarz») bleibt vollstaendig: er steht auf `.gz` und gehoert der FLAeCHE,
   nicht ihren Teilen. Nur das Aufhellen der einzelnen Stuecke faellt. */
.gz-buehne .gz-karte:hover { background: rgba(var(--accent-rgb), .06); }

/* 1. Die Kachelzeile der Referenz: [türkise Box] [grosse Zahl] / CAPS-Label.
   «Leuchtend» hiess hier bis zum 03.08. ein 18px-Hof um die Box. Das Bild
   kennt ihn nicht: Schnitt durch 13_25_27.png bei x=977 durch die Box der
   Kachel «Aktive Projekte» — Grund 14,22,29 · Kante 28,39,46 · Boxfläche
   26,42,50 · eine Zeile unter der Box 16,27,35 · zwei darunter 13,20,28.
   Der Übergang zum Grund dauert ZWEI Pixel; ein 18px-Radius hätte achtzehn
   angehoben. Die Box behält, was sie im Bild hat: getönte Fläche und einen
   1px-Ring. Der Ring ist eine KANTE (inset, ohne Weichzeichnung) und bleibt. */
/* 15px = 14px + die 1px des Rahmens, den die Kachel seit dem 13.08. nicht mehr
   traegt (FLACH STATT KASTEN): die senkrechte Hoehe der Kachelzeile bleibt
   damit exakt, wo sie war — gemessen 115px vorher, 115px nachher. Diese Regel
   ist die LETZTE der vier `.gz-kachel`-Padding-Regeln und damit die geltende;
   wer nur die weiter oben aendert, aendert nichts. */
.gz-buehne .gz-kachel { --gz-feld: var(--accent-rgb); gap: 7px; padding: 18px; }
/* DIE ZAHL DARF NIE ABGESCHNITTEN WERDEN (25.08., am Bild gefunden).
   Die Referenz («… 13_25_27.png») stellt das Zeichen LINKS NEBEN die Zahl —
   dort heissen die Zahlen «4», «13», «328». Hier heissen sie «CHF 6'486».
   Gemessen bei 1400px: die Spalte der Zentrale ist 716px breit, vier Kacheln
   mit Fuge ergeben je 168px, davon gehen 40px Polsterung, 2px Kante, 40px
   Zeichen und 12px Fuge ab — es bleiben 74px fuer eine Zahl, die 118px
   braucht. VORHER fiel das nicht auf, weil die Kachel keine Kante hatte und
   die Zahl einfach in die Nachbarkachel hineinlief (im Bild vom 25.08. steht
   «CHF 6'486» ueber dem Zeichen der zweiten Kachel). Die Karte macht den
   alten Fehler sichtbar; `flex-wrap` behebt ihn: passt die Zahl neben das
   Zeichen, steht sie dort — sonst rutscht sie darunter, also genau in die
   Anatomie, die jede andere Flaeche des Hauses ohnehin hat (EINHEIT §4.1).
   `nowrap` an der Zahl, damit sie nicht mitten im Betrag umbricht. */
.gz-kachel__zeile { display: flex; align-items: center; flex-wrap: wrap; gap: 8px 12px; min-width: 0; }
.gz-buehne .gz-kachel .stat__value { white-space: nowrap; }
.gz-buehne .gz-kachel .gz-ic {
  width: 40px; height: 40px; margin-bottom: 0; border-radius: var(--radius-card);
  background: rgba(var(--accent-rgb), .12);
  box-shadow: inset 0 0 0 1px rgba(var(--accent-rgb), .25);
}
.gz-buehne .gz-kachel .gz-ic svg { width: 19px; height: 19px; }
.gz-buehne .gz-kachel .stat__value { font-size: 26px; font-weight: 650; letter-spacing: -.5px; line-height: 1.12; }

/* 2. Der Balken der Referenz: satt, rund, flach. «Mit Schein» stand hier bis
   zum 03.08. und meinte den Hof aus dem Rahmen-Pass — der ist am Bild
   widerlegt (Pixelschnitt oben bei x=1050) und entfernt. Stärke und
   Strang-Form bleiben, die Farbe bleibt: sie ist die Aussage. */
.gz .stat__bar { height: 6px; border-radius: 999px; background: rgba(var(--tint-rgb), .13); overflow: hidden; }
.gz .stat__bar > i { border-radius: 999px; background: linear-gradient(90deg, var(--accent), var(--accent-strong)); }
.gz .stat__bar.is-warn > i { background: linear-gradient(90deg, var(--warn), var(--warn-strong)); }
.gz-mission__balken { height: 5px; }

/* Missions-Träger im Chat: die Türkis-Box der Referenz statt grauem Kreis. */
.gz-chat .gz-avatar {
  width: 30px; height: 30px; border-radius: 10px;
  background: rgba(var(--accent-rgb), .12);
  border: 1px solid rgba(var(--accent-rgb), .22);
  color: var(--accent-strong);
}
.gz-mission { border: 1px solid rgba(var(--accent-rgb), .1); background: rgba(var(--tint-rgb), .045); }
.gz-mission:hover { border-color: rgba(var(--accent-rgb), .3); }

/* 4. Überfällig: Bernstein, nicht Rot. Steht NACH der Dichte-Pass-Regel und
   gewinnt darum — die Wahrheit bleibt, der Alarmton weicht der Warnung. */
.gz-mission__fuss.is-spaet { color: var(--warn-strong); }

/* Senden wie die Referenz: runder Türkis-Knopf — gefüllt, ohne Hof. Schnitt
   durch 13_25_27.png bei x=861: Grund 13,22,30 · Knopffläche 9,73,77 ·
   Glyphe 86,237,239. Der Knopf ist der auffälligste Punkt seiner Zeile, weil
   er als einziger gefüllt ist — nicht weil er strahlt. Der `0 0 18px` hier
   war derselbe Fehlgriff wie im Chat-Panel (03.08. dort schon entfernt). */
.gz-chat__senden {
  width: 40px; height: 40px; padding: 0; border-radius: 50%; flex: 0 0 auto;
  display: grid; place-items: center;
}
.gz-chat__senden svg { width: 17px; height: 17px; }
/* Am Finger 44 (E1d-Kleinteil, Rundgang 08.08.: «Chat-Senden 40px»). Der
   AgentOS-Chat hält die Norm längst (`.ao-eingabe__senden`), dieser eine
   Knopf in der Zentrale war übersehen. Rund bleibt rund. */
@media (max-width: 1024px), (pointer: coarse) {
  .gz-chat__senden { width: 44px; height: 44px; }
}

/* Leerfälle: eine leise Zeile, keine tote Riesenfläche. */
/* ENTFERNT, nicht ersetzt: `.gz .empty-state` (padding 8px 0, 12px, tertiaer,
   linksbuendig). Das war die FUENFZEHNTE Leer-Bauart des Hauses und die
   heimtueckischste: sie hatte keinen eigenen Namen, sondern hat den KANON
   innerhalb dieser Flaeche umgeschrieben — dieselbe Klasse sah in der Zentrale
   anders aus als ueberall sonst, und keine Namensliste konnte das finden.
   Die drei Stellen in views/zentrale.js tragen jetzt die Haus-Zeile. */

/* AM BILD NACHGEMESSEN, 25.08.2026 — DER SATZ DARUEBER WAR FALSCH.
   Hier stand: «Die CAPS-Labels tragen den Hauch der Marke — wie ‹PROJEKT
   OVERVIEW› im Bild», und daraus folgte `rgba(var(--accent-rgb), .72)`.
   Gemessen im Referenzbild selbst
   (docs/design/referenzen/Portaluikomplett/«… 13_25_27.png», Ausschnitt
   680/245–1000/285, hellste Pixel des Wortes «PROJEKT OVERVIEW»):
   239,252,255 · 240,247,246 · 238,242,241 · 236,240,240 — das ist WEISS,
   kein Tuerkis. Der «Hauch der Marke» kam aus dem Wort, nie aus dem Bild.
   Ein Abschnitts-Titel in Akzentfarbe ist ausserdem gegen EINHEIT §1.3:
   Tuerkis traegt Aktion, aktiven Zustand, Balken und Positivwert — keine
   Ueberschrift. Er traegt ab hier die Textfarbe des Hauses, wie `.panel h3`. */
.gz-kz__label { color: var(--text-primary); }

/* KEINE KARTE IN DER KARTE. «Bereiche» ist der einzige der drei Abschnitte,
   dessen Inhalt selbst aus Karten besteht (`.gz-karte`, das 2×2-Portfolio).
   Er bleibt darum ein Abschnitt mit Ueberschrift, ohne eigenen Kasten —
   genau wie die Referenz es zeigt («PROJEKT OVERVIEW» ist dort eine
   Ueberschrift ueber Karten, kein Rahmen um sie herum). Dieselbe Regel wie
   `.panel .panel` im Fundament, nur mit `:has()` statt Verschachtelung,
   weil hier die Karten GESCHWISTER im Block sind. */
.gz-kz__block:has(.gz-karte) {
  background: none; border: 0; border-radius: 0; padding: 0;
}

/* Handy: die Referenz-Zeile bleibt, aber im 2er-Raster schrumpfen Box und
   Zahl — 40px-Box + 27px-Zahl liefen bei 390px um 34px über (Bühnen-Beleg). */
@media (max-width: 720px) {
  .gz-buehne .gz-kachel .gz-ic { width: 30px; height: 30px; border-radius: var(--radius-card); }
  .gz-buehne .gz-kachel .gz-ic svg { width: 15px; height: 15px; }
  .gz-buehne .gz-kachel .stat__value { font-size: 20px; letter-spacing: -.3px; }
  .gz-kachel__zeile { gap: 8px; }
}

/* =========================================================================
   DIE HANDY-GESTALT DER ZENTRALE — Karte 01.08., Position 9
   =========================================================================
   Gemessen vorher (Bühne, 390×844): 2'247 px = 2,7 Bildschirme, und der
   erste zeigte den Chat: Begrüssung, Fallliste, Eingabefeld. Die erste Zahl
   des Geschäfts kam nach dem ersten Wischen.

   Die Owner-Referenz (`13_25_27.png`, das iPhone links) zeigt EINEN
   Bildschirm in dieser Ordnung: aktuelle Mission · Statuskacheln 2×2 ·
   letzte Aktivitäten · feste Leiste unten. Genau das wird hier gebaut —
   ohne ein einziges Element wegzunehmen: was nicht auf den ersten
   Bildschirm gehört, steht darunter, nicht im Nichts.

   WIE, OHNE DAS MARKUP UMZUBAUEN:
   Der eine nächste Fall liegt im Chat-Abschnitt, Kacheln und Verlauf in der
   Kommandozentrale — zwei verschiedene Eltern. `display: contents` löst
   beide Hüllen NUR am Handy auf; ihre Kinder werden dadurch direkte
   Rasterfelder der Bühne und lassen sich frei ordnen. Am grossen Bildschirm
   ändert sich nichts, weil dieser ganze Block in @media steckt.

   Die Panel-Kante, die die aufgelösten Hüllen trugen, bekommen die drei
   Stücke des ersten Bildschirms einzeln zurück — sonst schwämme am Handy
   alles rahmenlos, und genau das hat der Owner am 31.07. «billig» genannt.
   ========================================================================= */
@media (max-width: 720px) {
  .gz-buehne > .gz-chat,
  .gz-buehne > .gz-kz,
  .gz-kz__fuss { display: contents; }

  /* Die Ordnung des ersten Bildschirms. Kleinere Zahl = weiter oben. */
  .gz-kz__titel            { order: 1; }
  .gz-kacheln              { order: 2; }   /* 2×2, wie im Bild */
  .gz-chat__missionen      { order: 3; }   /* der EINE nächste Fall */
  .gz-kz__spalte--verlauf  { order: 4; }   /* drei Aktivitäten */
  /* Bewusst dahinter — vollständig da, nur nicht auf dem ersten Bildschirm. */
  .gz-kz__block            { order: 5; }   /* die Bereiche */
  .gz-buehne .gz-chat > .panel__header { order: 6; }
  .gz-chat__lauf           { order: 7; }
  .gz-chat__eingabe        { order: 8; }
  /* SB1, der Fall der LEITUNG (10.08.): Wer den Assistenten nicht bedienen
     darf, sieht statt des Eingabefeldes einen Satz — und der trug als
     einziges Kind KEINE Ordnungszahl. Ohne Zahl gilt `order: 0`, also stand
     ausgerechnet der gesperrte Assistent als ERSTES auf dem Bildschirm eines
     Managers (Dramaturgie Teil 1, Zeile 2: «ein für sie gesperrtes Panel
     steht ganz oben»). Er steht jetzt dort, wo bei der Leitung das Feld
     stünde: zuletzt. */
  .gz-buehne .gz-chat > .empty-state { order: 8; }
  .gz-kz__spalte--agenten  { order: 9; }

  /* FLACH STATT KASTEN (Owner «Widget», 2026-08-13): hier standen sieben
     einzeln umrandete Kaesten untereinander — am Handy die dichteste
     Widget-Sammlung der ganzen Software. Der Grund von damals («sonst
     schwaemme alles rahmenlos») bleibt beantwortet, nur anders: jedes Stueck
     traegt eine Haarlinie oben und behaelt seinen Innenabstand. Das trennt
     genauso deutlich und laesst die Flaeche EINE Flaeche sein.
     13px = 12px + die 1px des alten Rahmens (gleiche Hoehe). */
  .gz-chat__missionen,
  .gz-kz__spalte--verlauf,
  .gz-kz__spalte--agenten {
    background: transparent;
    border: 0;
    border-top: 1px solid var(--border);
    border-radius: 0;
    padding: 13px 0;
    margin: 0;
  }
  .gz-kz__spalte + .gz-kz__spalte { border-left: 1px solid var(--border); padding-top: 18px; margin-top: 0; }
  .gz-buehne .gz-chat > .panel__header,
  .gz-chat__lauf,
  .gz-buehne .gz-chat > .empty-state,
  .gz-chat__eingabe {
    background: transparent;
    border: 0;
    border-top: 1px solid var(--border);
    border-radius: 0;
    padding: 13px 0;
    margin: 0;
  }
  /* Kopf, Verlauf und Eingabe des Chats gehören zusammen: eine Kante um alle
     drei, nicht drei Kästen untereinander. */
  .gz-buehne .gz-chat > .panel__header { border-bottom: 0; border-radius: var(--radius-card) var(--radius-card) 0 0; }
  .gz-chat__lauf { border-top: 0; border-bottom: 0; border-radius: 0; }
  .gz-chat__eingabe,
  .gz-buehne .gz-chat > .empty-state { border-top: 0; border-radius: 0 0 var(--radius-card) var(--radius-card); }

  /* Drei Aktivitäten wie im Bild, nicht fünf. Die Tür «Alle →» steht direkt
     darüber — es geht nichts verloren, es steht nur nicht alles hier. */
  .gz-kz__fuss .gz-akt .gz-akt__item:nth-child(n+4) { display: none; }
}

/* A working desk precedes the secondary company overview. */
/* Workplace: one agenda, one task list, an inspectable selected record. */
.gz-workplace .work-tabs { margin-bottom:24px; }
.gz-workplace h2,.od h2 { font-size:20px; font-weight:650; letter-spacing:-.025em; line-height:1.3; text-transform:none; margin:0; }
.gz-workplace h3 { text-transform:none; letter-spacing:-.02em; }
.gz-day { margin:0 0 32px; }
.gz-day__head,.od-heading,.person-work-leads__head { display:flex; align-items:center; justify-content:space-between; gap:16px; margin-bottom:16px; }
.gz-day__head>div { display:flex; align-items:baseline; gap:14px; flex-wrap:wrap; }
.gz-day__head span,.od-total { color:var(--text-secondary); font-size:13px; }
.gz-day__agenda { list-style:none; margin:0; padding:0; display:grid; grid-template-columns:repeat(auto-fit,minmax(min(100%,260px),1fr)); gap:12px; }
.gz-day__entry { display:flex; align-items:center; gap:16px; width:100%; min-height:76px; padding:16px; border:1px solid var(--border); background:var(--surface); border-radius:var(--radius-card); color:var(--text); text-align:left; text-decoration:none; cursor:pointer; font:inherit; }
.gz-day__entry:hover { border-color:var(--accent); }
.gz-day__entry time { color:var(--accent); font-weight:650; font-size:19px; font-variant-numeric:tabular-nums; }
.gz-day__entry>span:not([aria-hidden]) { flex:1; min-width:0; }
.gz-day__entry strong,.gz-day__entry small { display:block; }
.gz-day__entry strong { font-size:14px; line-height:1.4; overflow-wrap:anywhere; }
.gz-day__entry small { font-size:12px; color:var(--text-secondary); margin-top:4px; }
.gz-day__empty { padding:16px 0; margin:0; color:var(--text-secondary); border-bottom:1px solid var(--border); }
.gz-day__error { margin-bottom:12px; }
.gz-overview { padding:0; }
.gz-overview__focus { display:grid; grid-template-columns:1fr 1fr; gap:24px; }
.gz-workplace .gz-kz { display:block; background:transparent; border:0; padding:0; border-radius:0; }
.gz-workplace .gz-kachel .gz-ic { width:32px; height:32px; margin:0; background:rgba(var(--accent-rgb),.12); box-shadow:none; }
.gz-workplace .gz-kz__kopf a { font-size:13px; color:var(--accent); min-height:44px; display:inline-flex; align-items:center; }
.od { margin:0; }
.od-heading>div { display:flex; gap:12px; flex-wrap:wrap; align-items:baseline; }
.od select,.od input { background:var(--surface); color:var(--text); border:1px solid var(--border); border-radius:var(--radius-button); font:inherit; min-height:44px; padding:10px 12px; min-width:0; }
.od-heading>select { width:auto; max-width:240px; flex-shrink:0; }
.od [data-od-capture] { display:flex; gap:8px; margin-bottom:16px; }
.od [data-od-capture] input { flex:1; min-width:0; font-size:15px; }
.od [data-od-capture] button { height:auto; min-height:44px; white-space:normal; }
.od-toolbar { display:flex; align-items:center; gap:12px; border-bottom:1px solid var(--border); padding:0 0 12px; margin-bottom:0; flex-wrap:wrap; }
.od-filters { display:flex; gap:4px; flex-wrap:wrap; flex:1; }
.od-filters button { display:inline-flex; gap:8px; align-items:center; background:transparent; color:var(--text-secondary); border:0; border-radius:var(--radius-button); min-height:44px; padding:8px 12px; font-size:13px; font-weight:550; text-transform:none; letter-spacing:0; cursor:pointer; }
.od-filters button span { font-size:12px; font-variant-numeric:tabular-nums; opacity:.8; }
.od-filters button[aria-pressed=true] { background:var(--accent-soft); color:var(--accent); }
.od-search { width:190px; }
.od-search input { width:100%; font-size:13px; }
.od-work { display:grid; grid-template-columns:minmax(0,1.15fr) minmax(280px,.85fr); min-height:300px; align-items:start; }
.od-list { max-height:560px; overflow:auto; overscroll-behavior:contain; padding:8px 16px 8px 0; }
.od-row { display:flex; gap:12px; align-items:start; width:100%; padding:14px 12px; border:1px solid transparent; border-bottom-color:var(--border); border-radius:var(--radius-button); background:transparent; color:var(--text); text-align:left; cursor:pointer; }
.od-row:hover { background:var(--surface); }
.od-row[aria-pressed=true] { background:var(--surface); border-color:var(--accent); }
.od-row__status { width:12px; height:12px; border:1.5px solid var(--text-tertiary); border-radius:50%; flex:0 0 12px; margin-top:4px; }
.od-row__status[data-state=progress] { background:var(--accent-soft); border-color:var(--accent); box-shadow:inset 0 0 0 2px var(--surface); }
.od-row__content { flex:1; min-width:0; }
.od-row strong { display:block; font-size:14px; font-weight:600; line-height:1.45; overflow-wrap:anywhere; }
.od-row small { display:block; color:var(--text-secondary); font-size:12px; margin-top:4px; overflow-wrap:anywhere; }
.od-row__meta { display:flex; justify-content:space-between; flex-wrap:wrap; gap:6px; color:var(--text-secondary); font-size:12px; margin-top:10px; }
.od-overdue { color:var(--warn); font-weight:600; }
.od-detail { padding:24px; background:var(--surface); border:1px solid var(--border); border-radius:var(--radius-card); min-width:0; margin-top:8px; }
.od-detail__head>span { color:var(--text-secondary); font-size:12px; }
.od-detail h3 { font-size:22px; line-height:1.3; margin:6px 0 20px; overflow-wrap:anywhere; }
.od-detail p { font-size:14px; line-height:1.6; white-space:pre-wrap; overflow-wrap:anywhere; }
.od-detail dl { margin:0; }
.od-detail dl>div { display:flex; gap:16px; justify-content:space-between; border-bottom:1px solid var(--border); padding:10px 0; font-size:13px; }
.od-detail dt { color:var(--text-secondary); }
.od-detail dd { margin:0; text-align:right; min-width:0; overflow-wrap:anywhere; }
.od-detail a { color:var(--accent); text-underline-offset:3px; }
.od-detail>a { display:block; margin-top:16px; min-height:44px; }
.od-actions { display:flex; gap:8px; flex-wrap:wrap; margin-top:20px; }
.od-actions button,.od-assign button { min-height:44px; white-space:normal; height:auto; }
.od-assign { display:flex; gap:8px; align-items:end; margin-top:24px; }
.od-assign label { display:grid; gap:6px; min-width:0; flex:1; font-size:12px; }
.od-notes { margin-top:20px; border-top:1px solid var(--border); }
.od-notes>summary { min-height:44px; padding:12px 0; cursor:pointer; font-size:14px; line-height:20px; }
.od-empty { padding:28px 12px; color:var(--text-secondary); font-size:14px; line-height:1.6; }
.od-empty strong { color:var(--text); }
.od-feedback { padding:12px 0; font-size:14px; }
.od-feedback[role=alert] { color:var(--danger); }
.od :is(button,input,select,a):focus-visible,.gz-day__entry:focus-visible { outline:2px solid var(--accent); outline-offset:3px; }
@media(max-width:1050px) {
  .od-search { width:100%; }
  .od-work { grid-template-columns:minmax(0,1fr) minmax(250px,1fr); }
}
@media(max-width:760px) {
  .gz-day__head>div { display:block; }
  .gz-day__head span { display:block; margin-top:4px; }
  .gz-overview__focus { grid-template-columns:1fr; gap:0; }
  .od-heading { flex-wrap:wrap; }
  .od-heading>select { max-width:100%; }
  .od-work { grid-template-columns:minmax(0,1fr); }
  .od-list { padding-right:0; max-height:300px; }
  .od-detail { padding:20px; margin-top:12px; }
  .od [data-od-capture] { flex-wrap:wrap; }
  .od [data-od-capture] input { flex-basis:100%; }
  .od [data-od-capture] button { width:100%; }
  .od-filters { gap:2px; }
  .od-filters button { padding:8px; }
}

/* Company steering: a shared operational reading, not another card catalogue. */
.company { container-type:inline-size; color:var(--text); }
.company-heading,.company-section-head { display:flex; align-items:center; justify-content:space-between; gap:16px; }
.company-heading { margin:12px 0 24px; }
.company-heading h2 { font-size:24px; font-weight:650; line-height:1.3; margin:0 0 4px; }
.company-heading p,.company-caption { font-size:13px; color:var(--text-secondary); line-height:1.5; margin:4px 0 16px; }
.company-heading p { margin:0; }
.company :is(a,button,select) { -webkit-tap-highlight-color:transparent; }
.company a { color:var(--accent); text-decoration:none; text-underline-offset:4px; }
.company a:hover { text-decoration:underline; }
.company :is(button,select) { min-height:44px; }
.company :is(a,button,select,summary):focus-visible { outline:2px solid var(--accent); outline-offset:4px; }
.company-attention { display:flex; flex-wrap:wrap; align-items:center; gap:8px 24px; padding:12px 0; border-block:1px solid var(--border); margin-bottom:24px; font-size:14px; }
.company-attention[hidden] { display:none; }
.company-attention a { min-height:44px; display:inline-flex; align-items:center; gap:8px; }
.company-section-head { margin-bottom:10px; }
.company-section-head h3 { font-size:17px; font-weight:650; margin:0; }
.company-section-head>a,.company-link { font-size:13px; min-height:44px; display:inline-flex; align-items:center; gap:6px; }
.company-section-head select { max-width:100%; font-size:13px; }
.company-flow { padding:22px 24px 0; background:var(--surface); border-radius:var(--radius-card); margin-bottom:24px; }
.company-flow__steps { display:grid; grid-template-columns:repeat(4,minmax(0,1fr)); list-style:none; margin:0; padding:0; }
.company-flow__steps li { min-width:0; padding:12px 20px 20px 0; }
.company-flow__steps li+li { padding-left:20px; border-left:1px solid var(--border); }
.company-flow__label { display:block; font-size:14px; font-weight:600; }
.company-flow__steps strong { display:block; margin:10px 0 4px; font-size:28px; font-weight:600; line-height:1.2; font-variant-numeric:tabular-nums; }
.company-flow__steps small { display:block; font-size:12px; color:var(--text-secondary); line-height:1.5; }
.company-flow__steps a { display:inline-flex; align-items:center; gap:6px; min-height:44px; margin-top:8px; font-size:13px; }
.company-grid { display:grid; grid-template-columns:minmax(0,1.4fr) minmax(0,1fr); gap:28px 32px; align-items:start; }
.company-grid>section { min-width:0; padding:0; }
.company-chart-value { display:flex; align-items:baseline; flex-wrap:wrap; gap:6px 14px; min-height:44px; margin:20px 0 12px; }
.company-chart-value strong { font-size:24px; font-weight:600; font-variant-numeric:tabular-nums; }
.company-chart-value span { font-size:13px; color:var(--text-secondary); }
.company-chart { display:grid; grid-template-columns:repeat(8,minmax(0,1fr)); gap:10px; height:170px; margin-bottom:16px; }
.company-bar { display:flex; flex-direction:column; gap:10px; justify-content:end; padding:0; background:none; color:var(--text-secondary); border:0; cursor:pointer; font-family:inherit; font-size:12px; border-radius:0; }
.company-bar__plot { display:flex; align-items:end; flex:1; width:100%; border-bottom:1px solid var(--border-strong,var(--border)); }
.company-bar__plot i { display:block; width:100%; background:var(--text-tertiary); border-radius:var(--radius-button) var(--radius-button) 0 0; transition:background 160ms ease-out; }
.company-bar[aria-pressed=true] { color:var(--accent); font-weight:650; }
.company-bar[aria-pressed=true] i,.company-bar:hover i { background:var(--accent); }
.company-bar>span:last-child { width:100%; text-align:center; }
.company-chart-placeholder { min-height:250px; display:grid; place-content:center; text-align:center; color:var(--text-secondary); font-size:14px; }
.company-finance { padding:22px 24px!important; background:var(--surface); border-radius:var(--radius-card); }
.company-money-row { display:flex; justify-content:space-between; align-items:start; gap:16px; padding:17px 0; border-bottom:1px solid var(--border); }
.company-money-row>div { min-width:0; font-size:14px; line-height:1.5; }
.company-money-row small { display:block; font-size:12px; color:var(--text-secondary); margin-top:4px; }
.company-money-row>strong { font-size:18px; white-space:nowrap; font-variant-numeric:tabular-nums; font-weight:600; }
.company-due { display:flex; gap:12px; justify-content:space-between; font-size:13px; line-height:1.5; margin:18px 0; }
.company-due strong { white-space:nowrap; font-weight:600; }
.company-disclosure { border-top:1px solid var(--border); font-size:13px; }
.company-disclosure summary { cursor:pointer; min-height:44px; display:list-item; padding:13px 0; }
.company-disclosure table { width:100%; border-collapse:collapse; font-size:13px; }
.company-disclosure :is(th,td) { text-align:left; padding:9px 4px; border-bottom:1px solid var(--border); }
.company-disclosure :is(th,td):last-child { text-align:right; font-variant-numeric:tabular-nums; }
.company-team__rows { border-top:1px solid var(--border); }
.company-person { display:grid; grid-template-columns:minmax(0,1.3fr) minmax(0,1fr) minmax(0,1fr) 14px; align-items:center; gap:12px; padding:14px 0; border-bottom:1px solid var(--border); color:var(--text)!important; }
.company-person:hover { background:var(--accent-soft); text-decoration:none!important; }
.company-person strong { display:block; font-size:14px; font-weight:600; font-variant-numeric:tabular-nums; overflow-wrap:anywhere; }
.company-person small { display:block; margin-top:4px; color:var(--text-secondary); font-size:12px; line-height:1.4; }
.company-late strong { color:var(--warn); }
.company-person>span:last-child { color:var(--accent); }
.company-team__actions { display:flex; justify-content:space-between; flex-wrap:wrap; gap:8px 16px; }
.company-team__actions a { min-height:44px; display:inline-flex; align-items:center; gap:6px; font-size:13px; }
.company-network__numbers { display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); margin:0 0 20px; gap:16px; }
.company-network__numbers dt { font-size:13px; color:var(--text-secondary); }
.company-network__numbers dd { margin:8px 0 0; }
.company-network__numbers strong { display:block; font-size:24px; font-weight:600; font-variant-numeric:tabular-nums; }
.company-network__numbers a { font-size:13px; display:inline-flex; align-items:center; gap:6px; min-height:44px; }
.company-network__signal { font-size:14px; border-top:1px solid var(--border); padding-top:16px; line-height:1.5; }
.company-network__signal a { display:flex; align-items:center; gap:6px; min-height:44px; font-size:13px; }
.company-tools { display:flex; flex-wrap:wrap; gap:4px 28px; padding:18px 0 8px; border-top:1px solid var(--border); margin-top:28px; }
.company-tools a { display:inline-flex; align-items:center; gap:8px; font-size:13px; min-height:44px; }
.company-empty { font-size:14px; color:var(--text-secondary); line-height:1.6; margin:16px 0; }
@container(max-width:850px) {
  .company-grid { grid-template-columns:minmax(0,1fr); }
  .company-flow { padding:16px 16px 0; }
  .company-flow__steps li { padding-right:12px; }
  .company-flow__steps li+li { padding-left:12px; }
  .company-flow__steps a { font-size:12px; }
}
@container(max-width:520px) {
  .company-heading { margin-top:4px; }
  .company-heading h2 { font-size:20px; }
  .company-flow>.company-section-head { display:block; }
  .company-flow__steps { grid-template-columns:repeat(2,minmax(0,1fr)); }
  .company-flow__steps li:nth-child(3) { border-left:0; padding-left:0; }
  .company-flow__steps li:nth-child(n+3) { border-top:1px solid var(--border); }
  .company-section-head { gap:8px; }
  .company-section-head h3 { font-size:16px; }
  .company-section-head label { min-width:0; max-width:48%; }
  .company-section-head select { padding-left:8px; padding-right:24px; }
  .company-chart { gap:6px; }
  .company-finance { padding:16px!important; }
  .company-money-row { gap:10px; }
  .company-money-row>strong { font-size:16px; }
  .company-money-row>div { font-size:13px; }
  .company-person { grid-template-columns:minmax(0,1.4fr) minmax(0,1fr) minmax(0,1fr); gap:8px; }
  .company-person>span:last-child { display:none; }
  .company-person small { font-size:11px; }
  .company-tools { gap:4px 18px; }
}
@media(prefers-reduced-motion:reduce) { .company-bar__plot i { transition:none; } }

/* ============================================================
   Patch-Integration — Namensraum pl-; Quelle: docs/design/patch-partnerliste.css
   Der Block wird bei Integration als GANZES ersetzt, nie editiert.
   ============================================================ */
/* =========================================================================
   Partner-Liste (#/p/partners) — Erscheinung zur Owner-Referenz vom 28.07.
   («Nachtrag … Partner-Liste» in docs/design/ZIELBILD-2026-07-28.md).

   EINSETZEN: Diesen Block unveraendert an das ENDE von public/style.css
   haengen — nach dem bestehenden Mobile-Block der Verkaufs-Views
   (Projekt-Cascade-Regel, Memory project_css_cascade_mobile: ein eigener
   @media-Block gehoert NACH die Basis-Regeln, sonst wirkt er nicht).
   Danach die Service-Worker-VERSION in public/sw.js hochzaehlen und ueber
   ./scripts/jetzt-ausliefern.sh ausliefern.

   Warum als Patch-Datei und nicht direkt in style.css: diese Etappe lief in
   einer Welle mit drei parallelen Teams. Vier Haende in derselben 5'400-Zeilen-
   Datei sind ein Konflikt mit Ansage; der Wellen-Integrator haengt die Bloecke
   in einem Zug an.

   Bausteine, die WIEDERVERWENDET werden (kein Nachbau): .panel, .stat-strip/
   .stat/.stat__sub, .sl-filters/.field, .sl-count, .table-wrap/.team-table/
   .sl-table samt Mobile-Stapelung, .sl-badge--aktiv/--storniert, .pagination,
   .modal-backdrop/.modal, .panel-row, .icon-btn, .primary-btn/.ghost-btn.
   Neu ist nur, was es noch nirgends gibt: Auswahlspalte, Auswahl-Panel,
   Zeilenmenue und die Fusszeile mit Seitengroesse.
   ========================================================================= */

/* Welle 8 «Muster», 18.08.2026 — ENTFERNT, nicht ersetzt: .pl-head (1×), .pl-head__actions (1×).
   Diese Hülle(n) waren eine Nachbildung der EINEN Kopfreihe. Sie kommt jetzt
   aus `components/seiten-kopf.js` (Blatt patch-seitenkopf.css, Abschnitt 1b/2).
   «Ersetzen statt daneben» — Hausregel 7. */


/* Knopf mit Zeichen — dieselbe Bauart fuer Kopf, Filterzeile und Auswahlleiste. */
.pl-btn-ic { display: inline-flex; align-items: center; gap: 7px; }
.pl-btn-ic svg { width: 16px; height: 16px; flex: 0 0 auto; }

/* --- Suchzeile + Filterzeile (Referenz 13_25_56 (2)) ---------------------
   Zwei Zeilen statt eines Feld-Rasters: oben die Suche ueber die Breite und
   rechts die gespeicherten Ansichten, darunter die Filter als Chips
   «Zeichen · Wort: Wert». Gestapelte Feld-Labels («SUCHE», «STATUS») kosteten
   vorher eine halbe Bildschirmhoehe und stehen in keiner Referenz. */
.pl-suchzeile { display: flex; gap: 12px; align-items: center; flex-wrap: wrap; margin-bottom: 10px; }
.pl-suche { position: relative; flex: 1 1 340px; min-width: 0; display: block; }
.pl-suche__ic {
  position: absolute; left: 12px; top: 50%; transform: translateY(-50%);
  display: grid; place-items: center; color: var(--text-tertiary); pointer-events: none;
}
.pl-suche__ic svg { width: 17px; height: 17px; }
.pl-suche .search-input { width: 100%; min-height: 42px; padding-left: 38px; }
.pl-ansichten { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.pl-filterzeile { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin-bottom: 14px; }
.pl-filter-actions { display: flex; gap: 8px; flex-wrap: wrap; margin-left: auto; align-items: center; }

/* Der Filter-Chip: eine Pille, in der die Auswahlliste ohne eigenen Rahmen
   sitzt — sichtbar bleibt «Status: Aktiv ▾», nicht ein Formularfeld. */
.pl-chip {
  display: inline-flex; align-items: center; gap: 6px;
  min-height: 38px; padding: 0 10px 0 12px;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-badge);
  font-size: 13px; color: var(--text-secondary); cursor: pointer;
}
.pl-chip:hover { border-color: var(--line-strong); }
.pl-chip:focus-within { border-color: var(--accent-line); }
.pl-chip__ic { display: grid; place-items: center; color: var(--text-tertiary); }
.pl-chip__ic svg { width: 15px; height: 15px; }
.pl-chip__wort { white-space: nowrap; }
.pl-chip select {
  min-height: 34px; padding: 0 4px; border: 0; background: transparent;
  color: var(--text-primary); font-size: 13px; font-weight: 550; cursor: pointer;
}
.pl-chip select:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: var(--radius-card); }

/* Gespeicherte Ansichten (W-G/G3) — das gemeinsame Element `components/
   ansicht-wahl.js`. Es benutzt bewusst dieselbe Chip-Bauart wie die Filter
   dieser Fläche (EINHEIT: eine Form je Sache); eigen ist ihm nur die
   Touch-Untergrenze. Sie steht hier, weil das Element auf drei Flächen läuft
   (Standortbetreiber, Medien, Missionen) und dort je 44px zu wiederholen
   genau die Uneinheitlichkeit erzeugte, gegen die EINHEIT geschrieben ist.
   Breakpoint nach Memory `project_tablet_touch_breakpoint`: max-width 1024px
   ODER grober Zeiger — 720px allein lässt die Tablet-Bruchzone offen. */
.aw .aw-name { flex: 1 1 220px; min-width: 0; }
/* 28.08.2026 — DER BODEN GALT NUR DEN ANSICHTEN-CHIPS, NICHT DEN FILTERN.
   Der Block darunter stand seit W-G/G3 hier und nannte als Grund die
   Touch-Untergrenze; das `.aw ` davor liess aber genau die Chips aus, die auf
   dieser Flaeche taeglich angefasst werden. Gemessen an diesem Tag auf
   /p/partners: jeder Filter-Chip 115 x 38 px am Handy — sechs Pixel unter dem
   Boden, auf jeder Fingerbreite, seit es sie gibt. Kein Pruefstand sah es,
   weil die Flaeche in keiner Messliste stand.
   Die Knopfgruppe (.pl-filter-actions) steht NICHT eigens darin: sie liegt im
   Markup INNERHALB der Filterzeile (partner-list.js:351/365), der
   Nachfahren-Selektor deckt sie also mit — und ein zweites Mal genannt liess
   sie `_stil_einmalig_test.mjs` prompt auf 1044 steigen (sie steht schon in
   der 720px-Regel weiter unten).
   Die Selektoren sind absichtlich laenger als noetig (`.pl-filterzeile .pl-chip
   select` statt `.pl-chip select`): ein zweites Mal derselbe Selektor liesse
   `_stil_einmalig_test.mjs` steigen, und dessen Grundlinie schrumpft nur. */
@media (max-width: 1024px), (pointer: coarse) {
  .aw .pl-chip,
  .pl-filterzeile .pl-chip { min-height: 44px; }
  .aw .pl-chip select,
  .aw .ghost-btn,
  .aw .primary-btn,
  .aw .aw-name,
  .pl-suchzeile .search-input,
  .pl-table .pl-sortkopf { min-height: 44px; }
  /* `label.` davor, nicht nur die Klasse: die 34px-Regel dieser Datei steht
     WEITER UNTEN und traegt dieselbe Spezifitaet — bei Gleichstand gewinnt die
     spaetere. Ein Element-Name mehr entscheidet es, ohne die Reihenfolge der
     Datei umzustellen. */
  label.pl-seitengroesse > select { min-height: 44px; }
  .pl-table .pl-sortkopf::after { content: none; }
  /* Hoehe UND Breite in EINER Regel: kurze Auswahllisten sind so breit wie ihr
     laengstes Wort — `Kanton: Alle` mass 38 px. Am Finger zaehlt die Breite
     genauso wie die Hoehe. Zwei Regeln fuer denselben Selektor liessen
     `_stil_einmalig_test.mjs` steigen, und dessen Grundlinie schrumpft nur. */
  .pl-filterzeile .pl-chip select { min-height: 44px; min-width: 44px; }
}

/* Arbeitsflaeche: Liste links, Auswahl-Panel rechts — das Panel erscheint
   erst mit einer Auswahl, sonst nimmt die Liste die ganze Breite. */
.pl-arbeit { display: grid; gap: 16px; align-items: start; }
.pl-arbeit[data-auswahl="1"] { grid-template-columns: minmax(0, 1fr) 320px; }
.pl-liste { min-width: 0; }

/* Auswahl-Aktionsleiste ueber dem Tabellenkopf (EINHEIT 4.9). Sie sitzt
   zwischen Filter und Tabelle und traegt nur Handlungen mit einer Tuer. */
.pl-massen {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  padding: 8px 10px; margin-bottom: 8px;
  background: var(--accent-soft); border: 1px solid var(--accent-line);
  border-radius: var(--radius-card);
}
.pl-massen__zahl {
  font-size: 13px; font-weight: 650; color: var(--text-primary);
  padding: 0 6px; font-variant-numeric: tabular-nums; white-space: nowrap;
}
.pl-massen .ghost-btn { min-height: 34px; padding: 0 12px; font-size: 12.5px; background: var(--surface); }
.pl-massen__zu { margin-left: auto; }

/* Tabelle: Auswahlspalte und Zeilenmenue sind schmal und zentriert. */
.pl-table th.pl-pick, .pl-table td.pl-pick { width: 44px; text-align: center; }
.pl-table th.pl-menu-cell, .pl-table td.pl-menu-cell { width: 52px; text-align: right; }
/* DIE ZELLE IST DER GRIFF (28.08.2026). Das Kaestchen selbst mass 18 x 18 px
   und sass roh in der Zelle — kein Label drumherum, also war NUR das Kaestchen
   antippbar, obwohl die Zelle daneben 44 px breit ist (Regel darueber). Am
   Finger traf man es nicht, und `breiten-mass.mjs` meldete es zu Recht: dessen
   Label-Ausnahme greift erst, wenn eines da IST (`el.closest('label')`).
   Jetzt traegt ein Label die ganze Zelle; das Kaestchen darf klein bleiben. */
.pl-pick__fang {
  display: flex; align-items: center; justify-content: center;
  min-width: 44px; min-height: 44px; margin: -10px 0; cursor: pointer;
}
.pl-table td.pl-pick input { width: 18px; height: 18px; accent-color: var(--accent); cursor: pointer; }
.pl-table tr.is-gewaehlt td { background: rgba(var(--accent-rgb), .07); }

/* Sortierbarer Spaltenkopf: der Kopf IST der Knopf — Beschriftung erbt die
   gesperrten Versalien von .team-table th, der Pfeil zeigt die Richtung. */
.pl-sortkopf {
  display: inline-flex; align-items: center; gap: 5px; position: relative;
  background: transparent; border: 0; padding: 0; cursor: pointer;
  font: inherit; color: inherit; letter-spacing: inherit; text-transform: inherit;
}
/* Die Fangflaeche ohne die Hoehe (Muster grund.css «.case-work__link::after»,
   28.08.2026): der Kopf mass 144 x 16.5 px am Rechner — die Zeilenhoehe der
   Versalien, weit unter dem Maus-Boden 24. Ihn zu strecken hiesse die
   Kopfzeile der Tabelle zu strecken. Am Finger traegt er seine 44 px selbst
   (Touch-Block weiter unten), dort ist das Kaestchen darum aus. */
.pl-sortkopf::after {
  content: ""; position: absolute; left: 0; right: 0; top: 50%;
  height: 24px; transform: translateY(-50%);
}
.pl-table th.num .pl-sortkopf { flex-direction: row-reverse; }
.pl-sortkopf:hover, .pl-sortkopf:focus-visible { color: var(--text-primary); outline: none; }
.pl-sortkopf__pfeil { color: var(--text-tertiary); font-size: 11px; line-height: 1; }
.pl-sortkopf.is-aktiv { color: var(--accent-strong); }
.pl-sortkopf.is-aktiv .pl-sortkopf__pfeil { color: var(--accent); }

/* Hauptspalte zweizeilig: Kennung klein ueber dem Namen (EINHEIT 4.9). */
.pl-kennung {
  color: var(--text-tertiary); font-size: 11.5px; font-variant-numeric: tabular-nums;
  white-space: nowrap; letter-spacing: .02em;
}
.pl-table td.pl-haupt .pl-kennung { display: block; margin-bottom: 1px; }
.pl-table td.pl-haupt strong { font-size: 13.5px; font-weight: 600; }
.pl-table td.num { font-variant-numeric: tabular-nums lining-nums; }
/* Negativer Saldo in Rot — der eine Wert, den man auf einer Liste mit 257
   Zeilen sofort finden muss. */
.pl-minus { color: var(--bad-strong); }

/* Vierter Status-Chip im bestehenden sl-badge-Vokabular: RUHEND. «Inaktiv»
   ist kein Fehler und kein Storno — mit --storniert schrie auf der Referenz-
   liste jede achte Zeile rot. Neutraler Ton, gleiche Bauart, systemweit
   verfuegbar (der Block haengt am Ende von style.css). */
.sl-badge--ruhend { background: rgba(var(--tint-rgb), .10); color: var(--text-secondary); }
.pl-pausiert { display: block; font-size: 11.5px; color: var(--warn-strong); }

/* Zeilenmenue: kleines Blatt am Knopf (Lage setzt das Modul inline). */
.pl-menu {
  min-width: 220px; padding: 6px;
  background: var(--surface-2); border: 1px solid var(--border);
  border-radius: var(--radius-card); box-shadow: 0 18px 40px rgba(0,0,0,.45);
  display: grid; gap: 2px;
}
.pl-menu button {
  text-align: left; padding: 10px 12px; min-height: 40px;
  background: transparent; border: 0; border-radius: var(--radius-card);
  color: var(--text); font-size: 13.5px; cursor: pointer;
}
.pl-menu button:hover, .pl-menu button:focus-visible { background: var(--surface-3); outline: none; }

/* Auswahl-Panel: klebt beim Scrollen, traegt Aktionen und die Auswahl selbst. */
.pl-panel {
  position: sticky; top: 16px;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-card); padding: 16px;
  display: grid; gap: 12px; max-height: calc(100vh - 32px); overflow-y: auto;
}
.pl-panel__head { display: flex; justify-content: space-between; align-items: center; gap: 10px; }
.pl-panel__head h2 { margin: 0; font-size: 15px; font-weight: 650; letter-spacing: -.01em; }
.pl-panel__meta { margin: 0; color: var(--text-secondary); font-size: 12.5px; font-variant-numeric: tabular-nums; }
/* Zwischentitel im Panel: gesperrte Versalien wie ein Spaltenkopf — sie
   gliedern, sie ueberschreiben nicht. */
.pl-panel__h {
  margin: 4px 0 0; font-size: 11.5px; font-weight: 600; letter-spacing: .08em;
  text-transform: uppercase; color: var(--text-tertiary);
}
.pl-panel__actions { display: grid; gap: 6px; }
/* Aktionszeile mit Zeichen, Titel und Erklaerung (Referenz «SCHNELL-AKTIONEN»). */
.pl-panel__akt {
  display: flex; align-items: center; gap: 10px; width: 100%; min-height: 52px;
  padding: 8px 10px; text-align: left; cursor: pointer;
  background: var(--surface-inset); border: 1px solid var(--border);
  border-radius: var(--radius-card); color: inherit;
  transition: background var(--transition), border-color var(--transition);
}
.pl-panel__akt:hover { background: var(--surface-2); border-color: var(--line-strong); }
.pl-panel__akt:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.pl-panel__akt .gz-ic { --gz-ic-gr: 28px; }
.pl-panel__akt-text { display: grid; gap: 1px; min-width: 0; }
.pl-panel__akt-label { font-size: 13px; font-weight: 600; color: var(--text-primary); }
.pl-panel__akt-sub { font-size: 11.5px; color: var(--text-tertiary); line-height: 1.35; }
.pl-panel__liste { list-style: none; margin: 0; padding: 0; display: grid; gap: 2px; }
.pl-panel__liste li {
  display: flex; justify-content: space-between; align-items: center; gap: 8px;
  padding: 7px 0; border-top: 1px solid var(--border); font-size: 13px;
}
.pl-panel__liste li span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pl-panel__weg { width: 100%; min-height: 40px; }

/* Fusszeile nach EINHEIT 4.10: links «Zeige 1 bis 30 von 40», rechts
   Seitengroesse und Blaetterung. */
.pl-fuss { display: flex; justify-content: space-between; align-items: center; gap: 12px; flex-wrap: wrap; margin-top: 6px; }
.pl-fuss__zahl { margin: 0; color: var(--text-secondary); font-size: 12.5px; font-variant-numeric: tabular-nums; }
.pl-fuss__rechts { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-left: auto; }
.pl-fuss .pagination { margin: 0; }
.pl-seitengroesse { display: flex; align-items: center; gap: 8px; color: var(--text-secondary); font-size: 12.5px; }
.pl-seitengroesse select { min-height: 34px; }

/* Vorschau-Karte im Dialog: links wer, rechts was passiert. */
.pl-vorschau { padding: 4px 12px; max-height: 46vh; overflow-y: auto; }
.pl-vorschau .panel-row { display: flex; justify-content: space-between; align-items: center; gap: 12px; }
.pl-vorschau__wirkung { color: var(--text-secondary); font-size: 12.5px; text-align: right; }
.pl-vorschau--blockiert .pl-vorschau__wirkung { color: var(--warn-strong); }
.pl-check { display: flex; align-items: center; gap: 10px; font-size: 13.5px; }
.pl-check input { width: 18px; height: 18px; accent-color: var(--accent); }
.pl-hinweis { margin: 0; color: var(--text-secondary); font-size: 12.5px; line-height: 1.5; }
.pl-fehler { margin: 0; color: var(--bad-strong); font-size: 13px; }
.pl-fehler:empty { display: none; }

/* =========================================================================
   Mobile — eigener Block NACH den Basis-Regeln (Projekt-Cascade-Regel).
   Das Auswahl-Panel wird zum unteren Blatt; die Liste bekommt Platz darunter,
   damit die letzte Zeile nicht darunter verschwindet.
   ========================================================================= */
@media (max-width: 900px) {
  .pl-arbeit[data-auswahl="1"] { grid-template-columns: minmax(0, 1fr); }
  .pl-panel {
    position: fixed; left: 0; right: 0; bottom: 0; top: auto;
    z-index: 90; border-radius: var(--radius-card) var(--radius-card) 0 0;
    border-left: 0; border-right: 0; border-bottom: 0;
    max-height: 62vh; padding: 14px 16px calc(16px + env(safe-area-inset-bottom));
    box-shadow: 0 -18px 40px rgba(0,0,0,.5);
  }
  .pl-arbeit[data-auswahl="1"] .pl-liste { padding-bottom: 62vh; }
  .pl-panel__actions { grid-template-columns: 1fr 1fr; }
  .pl-panel__akt { min-height: 56px; }
  .pl-panel__liste { max-height: 22vh; overflow-y: auto; }
}

@media (max-width: 720px) {
  /* Die Knopfgruppe rutscht auf eine eigene volle Zeile — sonst draengt sie
     sich neben zwei Filter-Chips und jeder wird unlesbar schmal. */
  .pl-filter-actions { margin-left: 0; width: 100%; }
  /* 150px statt 0 (28.08.2026): `min-width: 0` heisst «schrumpf so weit du
     musst». Vier Chips auf 390 px Breite taten genau das — gemessen mass
     select#pl-einstufung 8 x 34 px, waehrend dasselbe Feld auf dem Tablet
     175 px breit ist. Ein Faktor 22, und damit der Fall, den das Owner-Gesetz
     vom 25.08. beim Namen nennt («unter 8 px hier, ueber 40 px dort»). Mit
     einer Mindestbreite bricht die Zeile um, statt sich aufzureiben — der
     Kommentar zwei Zeilen hoeher hatte genau das schon fuer die Knopfgruppe
     verlangt («sonst wird jeder unlesbar schmal»), nur nie fuer die Filter. */
  .pl-filter-actions .pl-chip { flex: 1 1 150px; min-width: 150px; }
  .pl-filter-actions .ghost-btn { flex: 0 0 auto; }
  .pl-suchzeile, .pl-filterzeile { gap: 8px; }
  /* Ansicht-Chip auf eine eigene Zeile, die beiden Knoepfe teilen die naechste:
     nebeneinander schnitt «Löschen» am rechten Rand ab. */
  .pl-ansichten { width: 100%; display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
  .pl-ansichten .pl-chip { grid-column: 1 / -1; min-width: 0; }
  /* 44px, nicht 40: seit W-G/G3 tragen diese Knoepfe das gemeinsame
     Ansichten-Element (auch auf Medien und Missionen), und dort gilt die
     Touch-Untergrenze ohne Ausnahme (Memory feedback_mobile_pwa_mandatory).
     Der alte Wert stammt aus der Zeit, als sie nur hier standen. */
  .pl-ansichten .ghost-btn { min-height: 44px; }
  .pl-filterzeile > .pl-chip { flex: 1 1 150px; min-width: 150px; }
  /* Die Auswahlleiste stapelt ihre Knoepfe zweispaltig statt in einer Reihe. */
  .pl-massen { gap: 6px; }
  .pl-massen .ghost-btn { flex: 1 1 44%; min-height: 40px; justify-content: center; }
  .pl-massen__zahl { width: 100%; }
  .pl-massen__zu { flex: 0 0 auto; }
  /* Die geerbte Stapelung (.sl-table) gibt jeder Zelle eine eigene Zeile — bei
     elf Spalten waere ein Partner eine halbe Bildschirmhoehe hoch. Darum hier
     zwei Spalten: Auswahl und Menue teilen die Kopfzeile, Firma bekommt die
     volle Breite, die acht Zahlen stehen paarweise. Nichts wird versteckt. */
  .pl-table tbody tr { display: grid; grid-template-columns: 1fr 1fr; align-items: center; }
  .pl-table tbody td { padding: 6px 12px; }
  .pl-table tbody td.pl-pick { grid-row: 1; grid-column: 1; justify-content: flex-start; gap: 8px; }
  /* `justify-self`, nicht nur `justify-content`: die Zelle ist 52px breit
     (style.css:6300) und sass darum am ANFANG ihrer Rasterspalte — das ⋮ stand
     bei 202px in einer 388px-Karte, also mitten im Bild (gemessen 09.08.,
     390px). Erst `end` schiebt die Zelle selbst an den rechten Rand. */
  .pl-table tbody td.pl-menu-cell { grid-row: 1; grid-column: 2; justify-self: end; justify-content: flex-end; }
  .pl-table tbody td.pl-haupt {
    grid-column: 1 / -1; display: block; text-align: left; padding-top: 2px;
  }
  .pl-table tbody td.pl-haupt::before { display: none; }
  /* Drei Wort-Zellen bekommen die ganze Zeile. «Belegung» kam am 30.07. dazu
     und blieb aussen vor: damit standen SIEBEN halbe Zellen paarweise
     nebeneinander — eine ungerade Zahl, also lag «Belegung» allein in der
     linken Haelfte und die rechte blieb leer (gemessen 09.08., 390px:
     neun halbe Zellen auf sechs Stapelzeilen statt fuenf). Ein Chip-Wort
     gehoert ohnehin nicht in eine Zahlenspalte. */
  .pl-table tbody td[data-label="Inhaber"],
  .pl-table tbody td[data-label="Belegung"],
  .pl-table tbody td[data-label="Status"] { grid-column: 1 / -1; }
  .pl-table td.pl-pick input { width: 24px; height: 24px; }
  .pl-fuss { justify-content: center; }
  .pl-fuss__rechts { margin-left: 0; }
}

/* ============================================================
   Patch-Integration — Namensraum pd2-; Quelle: docs/design/patch-partnerdetail.css
   Der Block wird bei Integration als GANZES ersetzt, nie editiert.
   ============================================================ */
/* =========================================================================
   Patch «Partner-Detail exakt nach Referenz» — Welle 2026-07-29, Team B.
   Gehört als Block ans ENDE von public/style.css (nach dem Basis-Block, sonst
   greift kein Mobile-Override — Memory project_css_cascade_mobile).

   Präfix pd2-, damit kein bestehender Klassenvertrag berührt wird. Farben,
   Radien, Abstände kommen ausschliesslich aus den Fundament-Tokens
   (style.css:21 ff.) — hier steht kein einziger roher Hex.

   Belegte Flächen: Partner-Cockpit (Übersicht), Präzedenz-Baum + Versionen
   (Vereinbarung), Slot-Kacheln + Belegungsplan (Standorte & Screens).
   ========================================================================= */

/* --- Kopf: Brotkrume, Name + Status, Meta-Zeile, Handgriffe ---------------- */
.pd2-kopf { margin-bottom: 16px; }
/* Der eigene Brotkrumen-Pfad dieser Flaeche ist am 17.08. ERSETZT worden:
   das Ortsschild zeichnet die Schale seither zentral fuer JEDE Flaeche
   (`components/ortsschild.js`, Tabelle `config/bereiche.js`, Gesetz
   docs/BEREICHE.md §3). Die Klassen `.pd2-krume` standen danach noch hier und
   trugen nichts mehr — «Ersetzen statt daneben»; entfernt 18.08. */
.pd2-kopf__zeile { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.pd2-kopf__zeile h1 { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.pd2-kopf__aktionen { display: flex; gap: 8px; flex-wrap: wrap; }
.pd2-btn-ic { display: inline-flex; align-items: center; gap: 7px; }
.pd2-btn-ic svg { width: 16px; height: 16px; flex: 0 0 auto; }
.pd2-kopf__meta {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  margin: 8px 0 0; font-size: 12.5px; color: var(--text-secondary);
}
.pd2-kopf__id { font-variant-numeric: tabular-nums; color: var(--text-tertiary); letter-spacing: .02em; }
.pd2-kopf__ort { display: inline-flex; align-items: center; gap: 5px; }
.pd2-kopf__ort svg { width: 14px; height: 14px; color: var(--text-tertiary); }
.pd2-kopf__punkt { color: var(--text-tertiary); }

/* Tabs mit Zeichen (EINHEIT 4.12) — die Reihe bleibt in jedem Tab dieselbe. */
.pd2-tabs { margin-bottom: 16px; }
.pd2-tabs .modal__tab { display: inline-flex; align-items: center; gap: 7px; }
.pd2-tab__ic { display: grid; place-items: center; }
.pd2-tab__ic svg { width: 15px; height: 15px; }

/* --- Kachelzeile im Kopf -------------------------------------------------- */
.pd2-kpis { margin-bottom: 18px; }
.pd2-kpis__head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; flex-wrap: wrap; margin-bottom: 10px;
}
.pd2-kpis__label {
  font-size: 12px; font-weight: 600; letter-spacing: .04em;
  text-transform: uppercase; color: var(--text-tertiary);
}
/* Acht Kacheln, gleiche Breite (EINHEIT 4.2: dieselben acht Werte in jedem
   Tab); .stat/.stat__value erbt aus dem Fundament. */
/* UND JEDE KACHELZEILE IST GLEICH HOCH (06.09.2026). Bricht die Reihe um,
   standen zwei Zeilen verschieden hoch untereinander — gemessen 155 zu 140 px
   auf 768 und 1024, 155 zu 126 auf 1280. Die Ursache ist die Kurve: sie steht
   nur in der ERSTEN Kachel, macht deren Zeile 15 bis 29 px hoeher und damit
   den Block zu einer Treppe. `1fr` je Zeile gibt allen dieselbe Hoehe; der
   Block waechst dadurch um genau diese 15 bis 29 px. Am Telefon aendert sich
   nichts, dort schweigt die Kurve und alle vier Zeilen messen 70 px. */
.pd2-kpi-row { grid-template-columns: repeat(8, minmax(0, 1fr)); grid-auto-rows: 1fr; margin-bottom: 0; }
.pd2-kpi-row .stat { padding: 13px 13px; }
.pd2-kpi-row .stat__value { font-size: 20px; }
.pd2-kpi-row .stat__label { font-size: 12px; }
.pd2-kpi-row .stat__sub { font-size: 11px; }
.pd2-kpi-row .gz-ic { --gz-ic-gr: 26px; margin-bottom: 8px; }
.pd2-kpi__spark { display: block; height: 20px; margin-top: 6px; opacity: .85; }
.pd2-kpi__spark .sparkline { width: 100%; height: 100%; }
/* AM TELEFON SCHWEIGT SIE — wie Zeichen und Unterzeile (grund.css, Block
   «Das gleiche Raster», 05.09.2026: «flach ist flach»). GEMESSEN am Stand
   93d3ff39 auf 390px: die Kachelreihe steht dort als 2x4-Raster, und weil
   GENAU EINE Kachel die Kurve traegt, war die erste Zeile 97px hoch und die
   drei darunter 70px — vier Zeilen, eine davon 27px hoeher, ohne dass ein
   Mensch sehen koennte warum. Auf 430px dasselbe. Die Kurve fehlt damit
   nirgends: am Schreibtisch steht sie weiter da. */
@media (max-width: 640px) {
  .stat-strip .pd2-kpi__spark { display: none; }
}

/* --- Cockpit-Raster -------------------------------------------------------
   KAESTEN IN EINER REIHE TEILEN IHRE UNTERKANTE (06.09.2026).
   Hier stand `align-items: start`. Damit war jeder Kasten nur so hoch wie sein
   Inhalt, und die Unterkanten flatterten. GEMESSEN am Stand 93d3ff39 auf
   1440 px: Reihe 2 endete bei 796 / 758 / 1010 px (252 px Spanne), Reihe 3 bei
   1457 / 1230 / 1536 (306 px), Reihe 4 bei 1694 / 2010 (316 px) — und die
   dritte Spalte der letzten Reihe war leer. Owner-Wort dazu: «Hier sind so
   viele Bereiche versetzt und nicht schoen geordnet.»
   `stretch` ist die Vorgabe von Grid; die Zeile faellt darum ersatzlos weg
   statt durch eine zweite ersetzt zu werden. Der Kasten ist ein Flex-Spalte,
   der Inhalt bleibt oben, und `.pd2-card__foot` sitzt auf der gemeinsamen
   Unterkante (siehe dort). Waechter: `npm run test:partnerakte:ordnung`. */
.pd2-grid {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 16px;
}
.pd2-card { padding: 16px 18px; display: flex; flex-direction: column; gap: 12px; }
.pd2-card--wide { grid-column: 1 / -1; }
/* Zwei von drei Spalten (06.09.2026): «Offene Aufgaben» steht neben dem
   Griff-Kasten, der die Aufgabe anlegt.
   SIE GILT NUR, WO ES DREI SPALTEN GIBT — darum als `min-width`, nicht als
   Grundregel mit Ruecknahme. Zwei Gruende, beide gemessen: (1) Unter 1200px
   hat das Raster zwei Spalten und unter 720px eine; `span 2` machte dort eine
   IMPLIZITE dritte Spalte auf und schoebe den Kasten aus der Flucht.
   (2) Bei zwei Spalten wuerde die Doppelbreite ein halbes Loch lassen — auf
   768px stand «Ausspielungen» als achter Kasten allein neben einer leeren
   Haelfte (Reihe t=1998). Ohne sie gehen acht Kaesten glatt in vier Reihen auf,
   und «Letzte Aktivitaeten» schliesst als ganze Breite ab. */
@media (min-width: 1201px) { .pd2-card--breit { grid-column: span 2; } }
.pd2-card__head { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.pd2-card__head h2 { font-size: 13px; font-weight: 600; margin: 0; }
/* DER KOERPER BESITZT DEN REST DER HOEHE (06.09.2026, zweite Runde).
   Ohne diese Zeile blieb der Koerper so hoch wie sein Inhalt, und die
   gestreckte Karte trug die gewonnene Hoehe als LEERE unter dem letzten Wort.
   Gemessen auf 1440 px: «Verlauf der Verguetung» 255 px Luft, «Screen-
   Auslastung» 252 px, «Standorte» 222 px. `flex: 1 1 auto` gibt den Raum an
   den Inhalt weiter; wer ihn fuellen kann (das Balkenbild), fuellt ihn, alle
   anderen bleiben wie sie waren. `min-height` bleibt bei `auto` — ein Koerper
   darf nie unter seinen Inhalt schrumpfen. */
.pd2-card__body { display: flex; flex-direction: column; gap: 8px; min-width: 0; flex: 1 1 auto; }
/* Die Fussgriffe eines Kastens stehen UNTEN, nicht direkt unter dem Text: in
   einer Reihe mit gemeinsamer Unterkante liegen sie damit selbst auf einer
   Linie. `auto` statt `4px` — der Abstand nach oben ist mindestens die Fuge
   des Kastens (`gap: 12px`). */
.pd2-card__foot { display: flex; gap: 8px; flex-wrap: wrap; margin-top: auto; padding-top: 4px; }

/* --- Schnellaktionen: jede Zeile ist eine echte Tür ----------------------- */
.pd2-acts { display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: 8px; }
.pd2-act {
  display: flex; align-items: center; gap: 10px; text-align: left;
  min-height: 58px; padding: 10px 12px; cursor: pointer;
  background: var(--surface-2); border: 1px solid var(--border);
  border-radius: var(--radius-button); color: inherit;
  transition: background var(--transition), border-color var(--transition);
}
.pd2-act:hover { background: var(--surface-3); border-color: var(--accent-line); }
.pd2-act:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.pd2-act .gz-ic { --gz-ic-gr: 30px; }
.pd2-act__text { display: grid; gap: 2px; min-width: 0; flex: 1; }
.pd2-act__label { font-size: 13px; font-weight: 600; color: var(--text-primary); }
.pd2-act__sub { font-size: 11.5px; color: var(--text-tertiary); line-height: 1.35; }
.pd2-act__pfeil { display: grid; place-items: center; color: var(--text-tertiary); flex: 0 0 auto; }
.pd2-act__pfeil svg { width: 15px; height: 15px; }

/* --- Angaben («Key Partner Info» der Referenz) ---------------------------- */
.pd2-angabe {
  display: grid; grid-template-columns: 18px minmax(70px, .8fr) minmax(0, 1.4fr);
  align-items: center; gap: 10px;
  padding: 7px 0; border-top: 1px solid var(--hairline); font-size: 12.5px;
}
.pd2-angabe:first-child { border-top: 0; }
.pd2-angabe__ic { display: grid; place-items: center; color: var(--text-tertiary); }
.pd2-angabe__ic svg { width: 15px; height: 15px; }
.pd2-angabe__label { color: var(--text-secondary); }
.pd2-angabe__wert {
  color: var(--text-primary); font-weight: 550; text-align: right;
  font-variant-numeric: tabular-nums; min-width: 0; white-space: normal; overflow-wrap: anywhere;
  /* Traeger der Fangflaeche des Links darin (Geraete-Block unten). */
  position: relative;
}
.pd2-angabe__wert a { color: inherit; }

/* --- Panel-Zeilen (Listen sind Rows, keine Karten — DESIGN.md §1) --------- */
.pd2-row {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  width: 100%; min-height: 44px; padding: 8px 0; text-align: left;
  background: none; border: 0; border-top: 1px solid var(--hairline);
  color: inherit; cursor: pointer;
}
.pd2-row:first-child { border-top: 0; }
.pd2-row--static { cursor: default; }
.pd2-row:not(.pd2-row--static):hover { background: var(--surface-2); }
.pd2-row:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.pd2-row .gz-ic { --gz-ic-gr: 30px; }
.pd2-row__main { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1; }
.pd2-row__title { font-size: 13px; font-weight: 600; color: var(--text-primary); overflow: hidden; text-overflow: ellipsis; }
.pd2-row__meta { font-size: 11.5px; color: var(--text-tertiary); }
.pd2-row__right { display: flex; align-items: center; gap: 8px; flex: none; }
.pd2-row__num { font-size: 13px; font-weight: 600; font-variant-numeric: tabular-nums; flex: none; }
.pd2-row__num--minus { color: var(--bad-strong); }

/* --- Ring (Screen-Auslastung) -------------------------------------------- */
.pd2-ring { position: relative; width: 132px; margin: 2px auto 0; }
.pd2-ring svg { width: 100%; height: auto; transform: rotate(-90deg); }
.pd2-ring circle { fill: none; stroke-width: 13; }
.pd2-ring__bg { stroke: rgba(var(--tint-rgb), .10); }
.pd2-ring__seg.is-belegt { stroke: var(--accent); }
.pd2-ring__seg.is-blockiert { stroke: var(--warn); }
.pd2-ring__seg.is-frei { stroke: rgba(var(--tint-rgb), .22); }
.pd2-ring__mitte {
  position: absolute; inset: 0; display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 1px;
}
.pd2-ring__mitte b { font-size: 20px; font-weight: 650; font-variant-numeric: tabular-nums; color: var(--text-primary); }
.pd2-ring__mitte span { font-size: 11px; color: var(--text-tertiary); }

/* Ring links, Legende rechts (Referenz 13_25_56 (3)). */
.pd2-ausl { display: flex; align-items: center; gap: 18px; flex-wrap: wrap; }
.pd2-ausl .pd2-ring { margin: 0; flex: 0 0 auto; }
.pd2-legende { display: flex; gap: 12px; flex-wrap: wrap; justify-content: center; }
.pd2-legende--klein { justify-content: flex-start; margin-top: 8px; }
.pd2-legende--spalte { flex-direction: column; gap: 8px; align-items: stretch; flex: 1; min-width: 130px; }
.pd2-legende--spalte .pd2-leg { justify-content: flex-start; }
.pd2-legende--spalte .pd2-leg b { margin-left: auto; }
.pd2-leg { display: inline-flex; align-items: center; gap: 5px; font-size: 11.5px; color: var(--text-secondary); }
.pd2-leg b { color: var(--text-primary); font-variant-numeric: tabular-nums; }
.pd2-leg i { font-style: normal; color: var(--text-tertiary); font-variant-numeric: tabular-nums; min-width: 34px; text-align: right; }
.pd2-leg::before { content: ''; width: 8px; height: 8px; border-radius: 2px; background: currentColor; }
.pd2-leg.is-belegt::before { background: var(--accent); }
.pd2-leg.is-blockiert::before { background: var(--warn); }
.pd2-leg.is-frei::before { background: rgba(var(--tint-rgb), .30); }

.pd2-note { margin: 0; font-size: 11.5px; line-height: 1.45; color: var(--text-tertiary); }
.pd2-note--bad { color: var(--bad-strong); }

/* --- W-D/D2: das Etikett an der Zahl -------------------------------------
   Eine gezählte und eine modellierte Zahl stehen nebeneinander. Ohne sichtbar
   VERSCHIEDENE Etiketten wären sie dasselbe — genau der Fehler der
   Referenzbilder («312k Impressionen» ohne Herkunft). Deshalb trägt jede Zelle
   ihr Wort, und die modellierte zusätzlich eine andere Farbe und einen
   gestrichelten Rahmen: gerechnet sieht nicht aus wie gemessen. */
.pd2-etikett {
  display: inline-flex; align-items: center; align-self: flex-start;
  margin-top: 4px; padding: 2px 7px; border-radius: var(--radius-badge);
  font-size: 11px; font-weight: 600; letter-spacing: .02em; line-height: 1.5;
}
.pd2-etikett--zaehlbar { background: var(--accent-soft); color: var(--accent-strong); }
.pd2-etikett--modell {
  background: rgba(var(--warn-rgb), .12); color: var(--warn-strong);
  border: 1px dashed rgba(var(--warn-rgb), .45);
}

/* --- Verlauf: beschriftete Achse links, Balken auf der Nulllinie ---------- */
/* DAS BALKENBILD FUELLT DEN KASTEN (06.09.2026, zweite Runde).
   Es ist der einzige Inhalt dieser Flaeche, der mehr Hoehe ehrlich brauchen
   kann: dieselben drei Monate, groesser gezeichnet und darum besser ablesbar.
   Die Achse traegt weiter max / max/2 / 0 und streckt mit — sie steht im
   selben Raster (`align-items: stretch`), darum genuegt `height: auto`.
   `min-height` haelt das alte Mass von 92 px, wo es nichts zu fuellen gibt.
   Was NICHT gestreckt wird: die Standortliste und der Ring. Eine Liste, die
   ihre Zeilen auseinanderzieht, behauptet mehr Inhalt als sie hat. */
.pd2-kurve { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 10px; align-items: stretch; flex: 1 1 auto; min-height: 92px; }
.pd2-kurve__achse {
  display: flex; flex-direction: column; justify-content: space-between;
  height: auto; text-align: right;
  font-size: 11px; color: var(--text-tertiary); font-variant-numeric: tabular-nums;
}
.pd2-bars { display: flex; align-items: flex-end; gap: 6px; height: auto; }
.pd2-bar { display: flex; flex-direction: column; justify-content: flex-end; align-items: center; gap: 4px; flex: 1; height: 100%; }
.pd2-bar > i {
  display: block; width: 100%; max-width: 56px; border-radius: 3px 3px 0 0;
  background: var(--accent); opacity: .78;
}
.pd2-bar:last-child > i { opacity: 1; }
.pd2-bar__label { font-size: 11px; color: var(--text-tertiary); }

/* --- Nächste Abrechnung: das Datum gross, darunter die Zeilen ------------- */
.pd2-termin {
  display: grid; gap: 2px; padding: 12px 14px;
  background: var(--surface-inset); border-radius: var(--radius-button);
}
.pd2-termin__label { font-size: 11px; font-weight: 600; letter-spacing: .03em; text-transform: uppercase; color: var(--text-tertiary); }
.pd2-termin__datum { font-size: 22px; font-weight: 650; letter-spacing: -.3px; font-variant-numeric: tabular-nums; color: var(--text-primary); }
.pd2-termin__zeile {
  display: flex; justify-content: space-between; gap: 10px; align-items: baseline;
  margin-top: 6px; padding-top: 6px; border-top: 1px solid var(--hairline);
  font-size: 12px; color: var(--text-secondary);
}
.pd2-termin__zeile b { color: var(--text-primary); font-variant-numeric: tabular-nums; }

/* --- Zwei-/Dreiwert-Zeile ------------------------------------------------- */
.pd2-zwei { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
.pd2-zwei--drei { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.pd2-zwei__zelle {
  display: flex; flex-direction: column; gap: 2px; padding: 10px 12px;
  background: var(--surface-inset); border-radius: var(--radius-button);
}
.pd2-zwei__label { font-size: 11px; font-weight: 600; letter-spacing: .03em; text-transform: uppercase; color: var(--text-tertiary); }
.pd2-zwei__wert { font-size: 17px; font-weight: 650; font-variant-numeric: tabular-nums; color: var(--text-primary); }

/* --- Belegungsplan: Slots | Kalender | Tag -------------------------------- */
/* `align-items: start` BLEIBT hier: die drei Kinder sind rahmenlose <div> in
   EINEM Kasten (`<section class="pd2-plan">` traegt kein `.panel`) — sie haben
   keine sichtbare Unterkante, die flattern koennte, und gestreckt wuerde der
   Kalender vom Tages-Panel auseinandergezogen. Die Regel gilt Kaesten, nicht
   jedem Raster. */
.pd2-plan { display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr) minmax(0, 1fr); gap: 16px; align-items: start; }
.pd2-plan__h { font-size: 12px; font-weight: 600; color: var(--text-tertiary); margin: 0 0 8px; }
.pd2-plan > div { min-width: 0; }

.pd2-kal__head { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 8px; }
.pd2-kal__monat { font-size: 13px; font-weight: 600; color: var(--text-primary); }
.pd2-kal__wd, .pd2-kal__grid { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 3px; }
.pd2-kal__wd { margin-bottom: 3px; }
.pd2-kal__wd span { text-align: center; font-size: 11px; font-weight: 600; color: var(--text-tertiary); }
.pd2-kal__tag {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px;
  min-height: 42px; padding: 4px 0; cursor: pointer;
  background: var(--surface-inset); border: 1px solid transparent;
  border-radius: var(--radius-card); color: var(--text-secondary);
  transition: background var(--transition), border-color var(--transition);
}
.pd2-kal__tag:hover { background: var(--surface-3); }
.pd2-kal__tag:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.pd2-kal__tag.is-zu { background: none; color: var(--text-tertiary); cursor: pointer; }
.pd2-kal__tag.is-heute { border-color: var(--accent-line); }
.pd2-kal__tag.is-gewaehlt { background: var(--accent-soft); border-color: var(--accent); color: var(--text-primary); }
.pd2-kal__tag.is-unter { box-shadow: inset 0 -2px 0 var(--bad); }
.pd2-kal__nr { font-size: 12px; font-variant-numeric: tabular-nums; }
.pd2-kal__punkte { display: flex; gap: 2px; }
.pd2-kal__punkte i { width: 5px; height: 5px; border-radius: 50%; }
.pd2-kal__punkte i.is-belegt { background: var(--accent); }
.pd2-kal__punkte i.is-blockiert { background: var(--warn); }
.pd2-kal__punkte i.is-frei { background: rgba(var(--tint-rgb), .30); }

/* --- W-D/D2: Kalenderstreifen «Was lief» ---------------------------------
   Eine Zeile je Monat, eine Zelle je Tag, waagerecht umbrechend. Bewusst KEIN
   Sieben-Spalten-Raster wie der Belegungsplan darüber: der Streifen beantwortet
   «lief es durchgehend», nicht «welcher Wochentag». Zwei gleich aussehende
   Kalender nebeneinander wären zwei Aussagen in einem Bild.
   Jede Zelle ist mindestens 22px breit und trägt ihre Tageszahl — eine Farbe
   ohne Zahl liesse sich nicht auf einen Tag zurückführen. */
.pd2-streifen { display: flex; flex-direction: column; gap: 8px; }
.pd2-streifen .pd2-kal__head { margin-bottom: 0; }
.pd2-streifen__reihe { display: flex; flex-wrap: wrap; gap: 3px; }
.pd2-streifen__tag {
  display: grid; place-items: center;
  width: 24px; height: 26px; border-radius: var(--radius-card);
  border: 1px solid transparent;
  font-variant-numeric: tabular-nums;
}
.pd2-streifen__tag i { font-style: normal; font-size: 11px; line-height: 1; }
.pd2-streifen__tag.is-gespielt { background: var(--accent-soft); border-color: var(--accent-line); color: var(--accent-strong); }
.pd2-streifen__tag.is-ausfall { background: rgba(var(--bad-rgb), .16); border-color: rgba(var(--bad-rgb), .45); color: var(--bad-strong); }
.pd2-streifen__tag.is-pause { background: rgba(var(--tint-rgb), .10); color: var(--text-tertiary); }
.pd2-streifen__tag.is-ohne_messung { background: rgba(var(--warn-rgb), .12); border-color: rgba(var(--warn-rgb), .40); color: var(--warn-strong); }
.pd2-streifen__tag.is-zu { background: none; color: var(--text-tertiary); opacity: .5; }
.pd2-streifen__tag.is-kuenftig { background: none; border-color: var(--hairline); color: var(--text-tertiary); }
.pd2-leg.is-gespielt::before { background: var(--accent); }
.pd2-leg.is-ausfall::before { background: var(--bad); }
.pd2-leg.is-pause::before { background: rgba(var(--tint-rgb), .30); }
.pd2-leg.is-ohne_messung::before { background: var(--warn); }
.pd2-leg.is-zu::before { background: rgba(var(--tint-rgb), .14); }
.pd2-leg.is-kuenftig::before { background: none; box-shadow: inset 0 0 0 1px var(--hairline); }

.pd2-tag__kopf { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; margin-bottom: 8px; font-size: 13px; }
.pd2-tag__h { font-size: 11px; font-weight: 600; letter-spacing: .04em; text-transform: uppercase; color: var(--text-tertiary); margin: 12px 0 2px; }

/* --- Slot-Kacheln je Screen ---------------------------------------------- */
.pd2-screen + .pd2-screen { margin-top: 12px; }
.pd2-screen__kopf { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; margin-bottom: 6px; }
.pd2-screen__kopf strong { font-size: 13px; }
.pd2-screen__meta { font-size: 11px; color: var(--text-tertiary); font-variant-numeric: tabular-nums; }
.pd2-slots__reihe { display: flex; gap: 4px; flex-wrap: wrap; }
.pd2-slot { width: 22px; height: 26px; border-radius: var(--radius-card); flex: none; }
.pd2-slot.is-belegt { background: var(--accent); }
.pd2-slot.is-blockiert { background: var(--warn); }
.pd2-slot.is-frei { background: rgba(var(--tint-rgb), .13); box-shadow: inset 0 0 0 1px var(--border); }

/* --- Formulare im Tages-Panel -------------------------------------------- */
.pd2-form { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; margin-top: 10px; }
.pd2-form .field--wide { grid-column: 1 / -1; }
.pd2-form .modal-actions { grid-column: 1 / -1; }
.pd2-fehler { grid-column: 1 / -1; margin: 0; font-size: 12.5px; color: var(--bad-strong); }

/* --- Standorte-&-Screens-Kopfkarte (Referenz 13_25_57 (4)) ---------------- */
.pd2-locs { padding: 16px 20px; }
.pd2-locs__kopf { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.pd2-locs__kopf .gz-ic { --gz-ic-gr: 44px; }
.pd2-locs__text { display: grid; gap: 2px; min-width: 0; flex: 1; }
.pd2-locs__name { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; font-size: 15px; font-weight: 650; color: var(--text-primary); }
.pd2-locs__meta { font-size: 12.5px; color: var(--text-secondary); }

/* --- Vereinbarungen: Baum links, Versionen rechts -------------------------
   Dieselbe Regel wie beim Cockpit-Raster: zwei Kaesten nebeneinander teilen
   ihre Unterkante. `align-items: start` ist am 06.09.2026 gefallen — es sind
   zwei `.panel`, und ein Panel, das in der Luft endet, ist derselbe Befund,
   den der Eigentuemer im Uebersichts-Reiter gesehen hat. */
/* EINE SPALTE, WEIL DIE ZWEI KAESTEN STRUKTURELL AUSEINANDERLAUFEN
   (06.09.2026, zweite Runde). Hier standen «Geltungsbereich» links (4fr) und
   «Versionen» rechts (6fr). Der linke Kasten ist FEST: drei Baumknoten und ein
   Satz. Der rechte ist APPEND-ONLY — er waechst mit jeder neuen Version und
   wird nie kuerzer. Auf einer gemeinsamen Unterkante heisst das eine Luecke,
   die mit der Zeit groesser wird; gemessen am 06.09. auf 1280/1366/1440/1680/
   1920 px: 507 / 524 / 504 / 521 / 521 px Leere unter dem Baum.
   Zwei Kaesten, deren Hoehen strukturell auseinanderlaufen, gehoeren nicht in
   eine Reihe. Untereinander tragen beide ihre eigene Hoehe, es gibt keine
   Kante zu teilen und keine Luecke — und der Reiter liest sich durchgehend
   von oben nach unten wie seine zwei unteren Flaechen, die schon immer ueber
   die ganze Breite gingen. */
.pd2-vgrid { display: grid; grid-template-columns: minmax(0, 1fr); gap: 16px; }
/* Der Geltungs-Baum: drei Knoten untereinander, jeder eine Stufe tiefer, mit
   Verbindungslinie nach links oben — die Richtung ist die Aussage. */
.pd2-baum { display: grid; gap: 8px; }
.pd2-baum__knoten {
  position: relative; display: flex; align-items: center; gap: 10px;
  margin-left: calc(var(--tiefe) * 22px);
  padding: 10px 12px;
  background: var(--surface-inset); border: 1px solid var(--border);
  border-radius: var(--radius-button);
}
.pd2-baum__knoten.is-leer { opacity: .62; }
.pd2-baum__knoten:not(:first-child)::before {
  content: ''; position: absolute; left: -12px; top: -9px; bottom: 50%;
  width: 11px; border-left: 1px solid var(--border); border-bottom: 1px solid var(--border);
  border-bottom-left-radius: 8px;
}
.pd2-baum__knoten .gz-ic { --gz-ic-gr: 30px; }
.pd2-baum__text { display: grid; gap: 1px; min-width: 0; flex: 1; }
.pd2-baum__name { font-size: 13px; font-weight: 600; color: var(--text-primary); overflow: hidden; text-overflow: ellipsis; }
.pd2-baum__was { font-size: 11.5px; color: var(--text-tertiary); }
.pd2-baum__stand { font-size: 11.5px; color: var(--text-secondary); font-variant-numeric: tabular-nums; flex: none; }

/* --- Präzedenz-Baum ------------------------------------------------------- */
.pd2-stufen { display: flex; align-items: stretch; gap: 8px; flex-wrap: wrap; margin: 14px 0 6px; }
.pd2-stufe {
  display: flex; flex-direction: column; gap: 2px; padding: 10px 14px; flex: 1; min-width: 150px;
  background: var(--surface-inset); border: 1px solid var(--border); border-radius: var(--radius-button);
}
.pd2-stufe.is-leer { opacity: .6; }
.pd2-stufe__name { font-size: 13px; font-weight: 600; color: var(--text-primary); }
.pd2-stufe__meta { font-size: 11.5px; color: var(--text-tertiary); }
.pd2-stufe__pfeil { align-self: center; color: var(--text-tertiary); font-size: 15px; }

.pd2-praez { margin-top: 16px; }
.pd2-praez__h { font-size: 13px; font-weight: 600; color: var(--text-primary); margin: 0 0 8px; }
.pd2-praez__t td { font-variant-numeric: tabular-nums; color: var(--text-tertiary); }
.pd2-praez__t td.is-quelle { color: var(--text-primary); font-weight: 600; }
.pd2-praez__gilt { color: var(--text-primary) !important; }
.pd2-praez__nichts { color: var(--text-tertiary); font-weight: 400; }

/* --- Versionen ------------------------------------------------------------ */
.pd2-vgruppe { margin-top: 16px; }
.pd2-version { padding: 12px 0; border-top: 1px solid var(--hairline); }
.pd2-version.is-abgelaufen { opacity: .72; }
.pd2-version__kopf { display: flex; gap: 10px; align-items: baseline; flex-wrap: wrap; margin-bottom: 4px; }
.pd2-version__nr { font-size: 13px; color: var(--text-primary); }
.pd2-version__zeit { font-size: 12px; color: var(--text-tertiary); font-variant-numeric: tabular-nums; }
.pd2-version__wer { font-size: 12px; color: var(--text-tertiary); }
.pd2-version__acts { margin-left: auto; display: flex; gap: 6px; flex-wrap: wrap; }
.pd2-version__text { font-size: 13px; line-height: 1.55; margin: 0; color: var(--text); }
.pd2-version__text--leer { color: var(--text-secondary); }

/* =========================================================================
   Schmale Geräte. Bewusst NACH den Basis-Regeln (Memory
   project_css_cascade_mobile) und bis 1024px/coarse, damit Tablets nicht in
   die Bruchzone fallen (Memory project_tablet_touch_breakpoint).
   ========================================================================= */
/* Acht Kacheln stehen in EINER Reihe, solange die GELDZAHL darin nicht bricht
   (die Referenz zeigt genau das). Darunter 4+4 statt acht gequetschter Spalten
   — ein abgeschnittenes «Vermittelte Kunden» wäre das Billige, das hier weg soll.

   DIE GRENZE IST GEMESSEN, NICHT GESCHAETZT (06.09.2026). Hier stand 1320px
   mit der Begruendung «solange jede rund 150px behaelt». Gemessen am Stand
   93d3ff39 auf einem 1366er Laptop: die Kachel war 159px breit, «CHF 1'855.00»
   brach bei 20px auf ZWEI Zeilen, die Kachelreihe wuchs von 155 auf 177px, und
   die Unterzeilen der ersten beiden Kacheln standen 52 bzw. 23px tiefer als
   die der sechs Nachbarn. Auf 1440px misst dieselbe Kachel 168px und nichts
   bricht. Also ist 1440 die Grenze — die Zahl kommt aus der Messung, nicht aus
   einem runden Wert. Ein 1366er Laptop zeigt jetzt 4+4 mit rund 310px je
   Kachel. Waechter: `npm run test:partnerakte:ordnung` misst auf allen neun
   Breiten, dass keine Geldzahl der Reihe zweizeilig wird. */
@media (max-width: 1439px) {
  .pd2-kpi-row { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}
@media (max-width: 1200px) {
  .pd2-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .pd2-plan { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  .pd2-plan__slots { grid-column: 1 / -1; }
}
@media (max-width: 720px) {
  /* Präzedenz auf dem Handy: die drei Stufen-Spalten fallen weg, «Gilt hier»
     trägt die Antwort samt Stufen-Chip. Sonst steht die wichtigste Spalte
     ausserhalb des Bildes (.team-table hat min-width:640px und scrollt). */
  .pd2-praez__t { min-width: 0; }
  /* Zeile ist th(Feld) + td(Global) + td(Partner) + td(Standort) + td(Gilt) —
     also Kind 2 bis 4 weg, Kind 1 und 5 bleiben. */
  .pd2-praez__t th:nth-child(2), .pd2-praez__t th:nth-child(3), .pd2-praez__t th:nth-child(4),
  .pd2-praez__t td:nth-child(2), .pd2-praez__t td:nth-child(3), .pd2-praez__t td:nth-child(4) { display: none; }
  .pd2-praez__t th, .pd2-praez__t td { padding: 9px 6px; }
  .pd2-kpi-row { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .pd2-grid { grid-template-columns: minmax(0, 1fr); }
  .pd2-plan { grid-template-columns: minmax(0, 1fr); }
  .pd2-acts { grid-template-columns: minmax(0, 1fr); }
  .pd2-form { grid-template-columns: minmax(0, 1fr); }
  .pd2-ring { width: 116px; }
  .pd2-slot { width: 20px; height: 24px; }
  /* Der Baum ruecken die Knoten am Handy nicht ein — 3 × 22px Einzug kosten
     dort ein Drittel der Breite und der Name bricht mitten im Wort. */
  .pd2-baum__knoten { margin-left: 0; }
  .pd2-baum__knoten:not(:first-child)::before { display: none; }
  /* Drei Handgriffe nebeneinander passen auf 390px nicht: «Vermittlung
     erfassen» braucht allein 140px und bricht nicht um. Also gestapelt —
     jeder über die volle Breite, jeder mit sicherer Tapfläche. */
  .pd2-kopf__aktionen { display: grid; grid-template-columns: minmax(0, 1fr); gap: 8px; width: 100%; }
  .pd2-kopf__aktionen button { width: 100%; justify-content: center; }
  /* Tab-Reihe scrollt waagerecht statt umzubrechen (Muster .modal__tabs). */
  .pd2-tabs { overflow-x: auto; flex-wrap: nowrap; scrollbar-width: none; }
  .pd2-tabs::-webkit-scrollbar { display: none; }
  .pd2-tabs .modal__tab { flex: 0 0 auto; }
}
/* Tapflächen: alles, was man antippt, hält 44px (DESIGN.md §7). */
@media (max-width: 1024px), (pointer: coarse) {
  .pd2-act { min-height: 60px; }
  .pd2-row { min-height: 48px; }
  /* DIE TAPFLAECHE OHNE DIE HOEHE (Muster: grund.css `.entity-link`, 28.08.2026).
     GEMESSEN am 06.09. auf 390, 430, 768 und 1024 px: die E-Mail-Adresse in der
     Zeile «E-Mail» der Angaben ist ein `mailto:`-Link und mass 15 px hoch — auf
     dem Geraet, auf dem der Eigentuemer einen Betreiber anruft oder anschreibt.
     Die WCAG-Ausnahme fuer Links IM SATZ greift hier NICHT (breiten-mass.mjs
     nennt die Bedingung: der Absatz drumherum muss mehr Text tragen als der
     Link) — der Link steht allein in seiner Zelle. Die Zeile wirklich auf 44 px
     zu setzen hiesse, die ganze Angaben-Liste zu strecken; darum waechst die
     Fangflaeche und nicht der Satz. */
  .pd2-angabe__wert > a::after {
    content: ""; position: absolute; left: 0; right: 0; top: 50%;
    height: 44px; transform: translateY(-50%);
  }
  .pd2-kal__tag { min-height: 44px; }
  .pd2-kal__head .ghost-btn--xs { min-height: 44px; min-width: 44px; }
  /* Die Streifen-Zelle ist KEINE Tapfläche (sie öffnet nichts) und bleibt
     darum klein — die Monatsknöpfe daneben erben ihre 44px aus der Regel
     oben, weil der Streifen denselben .pd2-kal__head benutzt. */
  .pd2-kopf__aktionen button { min-height: 44px; }
  .pd2-tabs .modal__tab { min-height: 44px; }
}
/* ============================================================
   Patch-Integration — Namensraum mi-; Quelle: docs/design/patch-missionen.css
   Der Block wird bei Integration als GANZES ersetzt, nie editiert.
   ============================================================ */
/* =========================================================================
   Missionen (#/faelle) — Erscheinung zur Owner-Referenz vom 28.07.
   («Missionen mit Phasen/Session-Baum» in docs/design/ZIELBILD-2026-07-28.md,
   Datenweg in docs/design/PROTOTYP-ANALYSE.md §C1).

   EINSETZEN: Diesen Block unveraendert an das ENDE von public/style.css
   haengen — nach dem bestehenden Mobile-Block (Projekt-Cascade-Regel,
   Memory project_css_cascade_mobile: ein eigener @media-Block gehoert NACH
   die Basis-Regeln, sonst wirkt er nicht). Danach die Service-Worker-VERSION
   in public/sw.js hochzaehlen und ueber ./scripts/jetzt-ausliefern.sh
   ausliefern.

   Warum als Patch-Datei und nicht direkt in style.css: diese Etappe lief in
   einer Welle mit drei parallelen Teams. Mehrere Haende in derselben
   5'900-Zeilen-Datei sind ein Konflikt mit Ansage; der Wellen-Integrator
   haengt die Bloecke in einem Zug an.

   Bausteine, die WIEDERVERWENDET werden (kein Nachbau): .admin-page/
   .admin-page__head, .panel, .stat-strip--auto/.stat/.stat__label/
   .stat__value/.stat__sub, .view-toggle, .sl-badge, .empty-state,
   .primary-btn/.ghost-btn, .case-work__link, .sr-only.
   Neu ist nur, was es noch nirgends gibt: die Missions-Zeile mit ihrem
   Klappknopf, der Verlaufsbaum und die Lage-Chips.

   NACHTRAG 30.07. (W-F/F3): der Gantt-Balkenplan IST jetzt gebaut. Der Grund
   fuer sein bisheriges Fehlen ist entfallen — Migration 20260730005040 gibt
   dem Arbeitsschritt zwei Enden (`geplant_ab`/`geplant_bis`). Ein Schritt ohne
   Plan bekommt trotzdem keinen Balken: er steht in der Spalte «Plan» als
   «ungeplant». Eine Agenten-Zuordnung fehlt weiterhin und wird nicht erfunden.
   ========================================================================= */

/* Kopf: Titel links, die beiden Umschalter rechts. Nur auf dieser Flaeche. */
.mi-page .admin-page__head {
  display: flex; justify-content: space-between; align-items: flex-start;
  gap: 12px; flex-wrap: wrap;
}
.mi-schalter { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
/* W-G/G3: die gespeicherten Ansichten stehen rechts neben den beiden
   Umschaltern und rutschen auf schmalen Bildschirmen auf eine eigene Zeile.
   Bauart des Chips: die der Partner-Liste (EINHEIT — eine Form je Sache). */
.mi-ansichten { margin-left: auto; }
@media (max-width: 720px) { .mi-ansichten { margin-left: 0; width: 100%; } }

/* Kachelzeile: die fünf Zahlen stammen aus derselben Liste, die darunter
   steht. Das Label darf zweizeilig werden — «Wartet auf Entscheid» passt
   sonst in keine Fünftelspalte. */
.mi-kacheln .stat__label { white-space: normal; overflow: visible; }
.mi-kacheln .stat__sub { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* Symbol-Quadrat oben (FINISH-STANDARD 1, EINHEIT.md 4.1) — nicht neben dem
   Label: in einer Fünferreihe blieben sonst keine 110px für das Wort. Der Ton
   folgt der Bedeutung, wie die fünf Zeichen der Referenz. */
.mi-kachel { justify-content: flex-start; gap: 3px; }
.mi-ic {
  display: grid; place-items: center; flex: 0 0 auto;
  width: 30px; height: 30px; border-radius: var(--radius-card); margin-bottom: 10px;
  background: rgba(var(--tint-rgb), .08); color: var(--text-tertiary);
}
.mi-ic svg { width: 16px; height: 16px; }
.mi-ic--gut { background: var(--accent-soft); color: var(--accent); }
.mi-ic--warn { background: rgba(var(--warn-rgb), .13); color: var(--warn-strong); }
.mi-ic--schlecht { background: rgba(var(--bad-rgb), .13); color: var(--bad-strong); }
.mi-kachel .stat__bar { margin-top: 10px; }

/* Die Liste ist EIN Panel mit Hairline-Zeilen (DESIGN §1), keine Tabelle:
   eine Mission ist eine Zeile plus ihr aufklappbarer Verlauf. Sie trägt aber
   den Spaltenkopf der Referenz — gesperrte Versalien, der eine Ort, an dem
   sie in diesem System stehen (EINHEIT.md 1.5 und 4.9). */
.mi-liste { padding: 4px 20px; }
.mi-mission { border-bottom: 1px solid var(--border); }
.mi-mission:last-of-type { border-bottom: 0; }

.mi-spalten,
.mi-mission__zeile {
  display: grid;
  /* 250px für den Status: «Überfällig» und «Wartet auf Entscheid» stehen an
     derselben Zeile nebeneinander — bei 200px brach der zweite Chip um und
     machte die Zeile eine Stufe höher als ihre Nachbarn. */
  grid-template-columns: 44px minmax(0, 1fr) minmax(0, 250px) 150px 230px;
  align-items: center; gap: 4px 14px;
}
.mi-spalten {
  padding: 12px 0 8px; border-bottom: 1px solid var(--border);
  font-size: 11.5px; font-weight: 600; letter-spacing: .09em; text-transform: uppercase;
  color: var(--text-tertiary);
}
.mi-mission__zeile { min-height: 60px; padding: 8px 0; }

/* Klappknopf: 44px Tapflaeche, Pfeil dreht beim Oeffnen. */
.mi-klapp {
  width: 44px; height: 44px; padding: 0; display: grid; place-items: center;
  background: transparent; border: 1px solid transparent; border-radius: var(--radius-button);
  color: var(--text-secondary); cursor: pointer;
  transition: background var(--transition), color var(--transition);
}
.mi-klapp:hover { background: var(--surface-2); color: var(--text-primary); }
.mi-klapp:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.mi-klapp__pfeil {
  width: 0; height: 0; border-left: 6px solid currentColor;
  border-top: 5px solid transparent; border-bottom: 5px solid transparent;
  transition: transform var(--transition);
}
.mi-klapp[aria-expanded="true"] { color: var(--accent); }
.mi-klapp[aria-expanded="true"] .mi-klapp__pfeil { transform: rotate(90deg); }

.mi-mission__haupt { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.mi-mission__haupt .case-work__link { font-size: 14.5px; }
.mi-mission__schritt {
  color: var(--text-secondary); font-size: 12.5px; line-height: 1.35;
  overflow: hidden; text-overflow: ellipsis;
}
.mi-mission__schritt strong { color: var(--text-primary); font-weight: 600; }

/* Drei eigene Spalten statt eines Sammelblocks rechts: Status · Frist ·
   Verantwortlich stehen damit über alle Zeilen hinweg auf einer Flucht — das
   ist der Unterschied zwischen einer Liste und der Tabelle der Referenz. */
.mi-mission__lage { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; min-width: 0; }
.mi-frist {
  color: var(--text-secondary); font-size: 12.5px;
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.mi-frist--spaet { color: var(--bad-strong); font-weight: 600; }
.mi-mission__wer { display: flex; align-items: center; gap: 8px; min-width: 0; }
.mi-mission__name {
  color: var(--text-secondary); font-size: 12.5px; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis;
}
/* Initialen im neutralen Kreis (FINISH-STANDARD 4, EINHEIT.md 1.8). */
.mi-avatar {
  display: grid; place-items: center; flex: 0 0 auto;
  width: 26px; height: 26px; border-radius: 50%;
  background: rgba(var(--tint-rgb), .09); border: 1px solid var(--border);
  color: var(--text-secondary); font-size: 11px; font-weight: 650;
}

/* Lage-Chips: die Flaechenfarbe fehlt im Badge-Vokabular nur fuer «offen»
   und «in Arbeit»; die Basis .sl-badge bleibt unveraendert in Gebrauch. */
.mi-chip { letter-spacing: .01em; }
.mi-chip--spaet { background: rgba(var(--bad-rgb), .13); color: var(--bad-strong); }
.mi-chip--wartet { background: rgba(var(--warn-rgb), .13); color: var(--warn-strong); }
.mi-chip--arbeit { background: rgba(var(--accent-rgb), .13); color: var(--accent-strong); }
.mi-chip--offen { background: rgba(var(--tint-rgb), .09); color: var(--text-secondary); }

/* Der Verlauf: eingerueckt unter der Zeile, mit durchgehender Zeitachse. */
.mi-baum { padding: 2px 0 14px 44px; }
.mi-baum[hidden] { display: none; }
.mi-baum__liste { list-style: none; margin: 0; padding: 0; }
.mi-baum__lade, .mi-baum__fehler {
  margin: 0; padding: 10px 14px; font-size: 12.5px; color: var(--text-secondary);
}
.mi-baum__fehler { color: var(--bad-strong); }

/* Die Zeitachse ist keine Rahmenlinie am Rand, sondern laeuft durch die
   Punkte: je Schritt ein Stueck, am ersten und letzten auf die Haelfte
   gekuerzt — sonst haengt die Linie oben und unten in der Luft. */
.mi-schritt {
  position: relative;
  display: grid; grid-template-columns: 20px minmax(0, 1fr) auto auto 150px;
  align-items: center; gap: 4px 12px; padding: 7px 0; min-height: 34px;
}
.mi-schritt::before {
  content: ''; position: absolute; left: 9px; top: 0; bottom: 0;
  width: 1px; background: var(--line-strong);
}
.mi-schritt:first-child::before { top: 50%; }
.mi-schritt:last-child::before { bottom: 50%; }
.mi-schritt__punkt {
  position: relative; z-index: 1;
  width: 20px; height: 20px; display: grid; place-items: center;
  border-radius: 50%; background: var(--surface-2); border: 1px solid var(--border);
  color: var(--text-tertiary); font-size: 11px; line-height: 1;
}
.mi-schritt__text {
  color: var(--text-primary); font-size: 13.5px;
  overflow: hidden; text-overflow: ellipsis;
}
.mi-schritt__wer { color: var(--text-tertiary); font-size: 12px; white-space: nowrap; }
.mi-schritt__zeit {
  color: var(--text-secondary); font-size: 12px;
  font-variant-numeric: tabular-nums; white-space: nowrap; text-align: right;
  min-width: 140px;
}
.mi-schritt.is-erledigt .mi-schritt__punkt { color: var(--good-strong); border-color: var(--accent-line); }
.mi-schritt.is-erledigt .mi-schritt__text { color: var(--text-secondary); }
.mi-schritt.is-zurueck .mi-schritt__punkt { color: var(--warn-strong); }
.mi-schritt.is-leer .mi-schritt__text { color: var(--text-tertiary); }
.mi-schritt.is-jetzt .mi-schritt__punkt {
  background: var(--accent-soft); border-color: var(--accent-line); color: var(--accent);
}
.mi-schritt.is-jetzt .mi-schritt__text { font-weight: 600; }

/* --- Zeitachse (Referenz 13_25_33 (6), Spalte ZEITACHSE) -----------------
   Eine gemeinsame Spur je Verlauf: der Punkt sitzt an der Stelle, an der sein
   Zeitpunkt WIRKLICH liegt (--p kommt aus occurred_at bzw. der Faelligkeit),
   die senkrechte Linie ist das Jetzt (--heute, einmal am <ol> gesetzt und
   dadurch ueber alle Zeilen deckungsgleich). Kein Balken: ein Ereignis hat
   einen Zeitpunkt, keine Dauer — ein Balken waere erfunden. */
/* Der Rand von 5px ist der Radius eines Punktes. Ein Punkt bei 0 % oder 100 %
   sitzt mit seiner Mitte auf dem Spurende und ragte sonst um genau diesen
   Radius aus der Zeile — was auf 390px jede Mission traf, deren Frist der
   spaeteste Zeitpunkt ihrer Achse ist (also jede gesunde). Die Spur wird
   eingerueckt, nicht der Punkt verschoben: sonst logen die Stellen. */
.mi-achse { position: relative; height: 20px; min-width: 0; margin-inline: 5px; }
.mi-achse::before {
  content: ''; position: absolute; left: 0; right: 0; top: 50%;
  height: 1px; background: var(--line-strong);
}
/* Das Jetzt laeuft durch alle Zeilen des Verlaufs durch. */
.mi-achse::after {
  content: ''; position: absolute; left: var(--heute); top: -7px; bottom: -7px;
  width: 1px; background: rgba(var(--warn-rgb), .55);
}
.mi-achse__punkt {
  position: absolute; top: 50%; left: var(--p);
  width: 8px; height: 8px; margin: -4px 0 0 -4px; border-radius: 50%;
  background: var(--accent);
}
.mi-achse__punkt--zurueck { background: var(--warn); }
.mi-achse__punkt--frist { background: transparent; border: 2px solid var(--accent); margin: -5px 0 0 -5px; width: 10px; height: 10px; }
.mi-achse__punkt--spaet { background: var(--bad); }

/* --- Legende (Referenz 13_25_33 (6), unterste Zeile) --------------------- */
.mi-legende {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px 18px;
  padding: 14px 0 4px; border-top: 1px solid var(--border);
  font-size: 12px; color: var(--text-tertiary);
}
.mi-legende__punkt { display: inline-flex; align-items: center; gap: 7px; white-space: nowrap; }
/* Die Zustandsfarben stehen sonst an `.mi-schritt.is-… .mi-schritt__punkt`;
   in der Legende traegt das Zeichen den Zustand selbst. */
.mi-legende__ic { font-style: normal; }
.mi-legende__ic.is-erledigt { color: var(--good-strong); border-color: var(--accent-line); }
.mi-legende__ic.is-zurueck { color: var(--warn-strong); }
.mi-legende__ic.is-jetzt { background: var(--accent-soft); border-color: var(--accent-line); color: var(--accent); }
.mi-legende__strich--heute { width: 2px; height: 14px; background: rgba(var(--warn-rgb), .55); }

/* =========================================================================
   Spot-Weg — die fuenf Schritte einer spot_produktion-Mission.

   EINE Bauart fuer Schrittleisten (EINHEIT.md 5.3, Referenz 13_21_08 (8)):
   waagerecht, nummerierte Kreise MIT Namen, duenne Verbindungslinie dazwischen;
   erledigt = gefuellter Kreis mit Haekchen, aktiv = gefuellter Kreis mit
   Nummer, offen = Umriss-Kreis mit Nummer. Keine Balkensegmente, keine
   Chevron-Trenner.

   Die Frist haengt am AKTIVEN Schritt, nicht an der Leiste: sie gilt fuer
   diesen einen Schritt. Ueberfaellig faerbt sie als Warnung — dieselbe Farbe
   wie `.mi-frist--spaet`, damit «zu spaet» im ganzen Bildschirm gleich
   aussieht. */
.mi-phasen {
  list-style: none; margin: 0 0 14px; padding: 0;
  display: flex; flex-wrap: wrap; gap: 6px 0;
}
.mi-phase {
  position: relative; flex: 1 1 0; min-width: 0;
  display: flex; flex-direction: column; align-items: center; gap: 4px;
  padding: 0 6px; text-align: center;
}
/* Die Verbindungslinie: sie laeuft vom Kreis dieses Schrittes zum naechsten.
   Der letzte Schritt bekommt keine — sie zeigte sonst ins Leere. */
.mi-phase::before {
  content: ''; position: absolute; top: 11px; left: 50%; right: -50%;
  height: 1px; background: var(--line-strong);
}
.mi-phase:last-child::before { display: none; }
.mi-phase.is-erledigt::before { background: var(--accent-line); }
.mi-phase__kreis {
  position: relative; z-index: 1;
  width: 22px; height: 22px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 11px; font-weight: 600; line-height: 1;
  border: 1px solid var(--border); background: var(--surface-1);
  color: var(--text-tertiary);
}
.mi-phase.is-erledigt .mi-phase__kreis {
  background: var(--accent-soft); border-color: var(--accent-line); color: var(--accent);
}
.mi-phase.is-aktiv .mi-phase__kreis {
  background: var(--accent); border-color: var(--accent); color: var(--on-accent, #fff);
}
.mi-phase__name {
  font-size: 12px; color: var(--text-tertiary); line-height: 1.25;
  overflow-wrap: anywhere;
}
.mi-phase.is-erledigt .mi-phase__name { color: var(--text-secondary); }
.mi-phase.is-aktiv .mi-phase__name { color: var(--text-primary); font-weight: 600; }
.mi-phase__wer { font-size: 11px; color: var(--text-tertiary); }
.mi-phase__frist { font-size: 11px; color: var(--text-secondary); font-variant-numeric: tabular-nums; }
.mi-phase__frist--spaet { color: var(--bad-strong); font-weight: 600; }

/* =========================================================================
   Owner-Gate-Spalte (Referenz 13_25_33 (6), Spalte OWNER / GATE)

   Dieselbe Spalte traegt zwei Dinge: WER zustaendig ist — oder, wenn etwas
   wartet, WORAUF. Ein Gate ersetzt den Namen, statt daneben zu stehen: der
   Name beantwortete sonst eine Frage, die gerade nicht die wichtige ist.
   Der Ton folgt der Bedeutung (Bernstein = wartet), wie ueberall hier.
   ========================================================================= */
.mi-gate {
  display: inline-flex; align-items: center; gap: 7px;
  min-width: 0; max-width: 100%;
  padding: 4px 9px; border-radius: var(--radius-button);
  background: rgba(var(--warn-rgb), .10); color: var(--warn-strong);
  font-size: 12.5px; line-height: 1.25;
}
/* Bei einem Gate weicht der ausgeschriebene Name, nicht die Person: der
   Avatar bleibt (mit vollem Namen im Titel), das Gate bekommt den Platz.
   `overflow: hidden` ist der Riegel: ein laengerer Grund kuerzt sich, statt
   die Spalte zu sprengen — sonst schoebe eine einzige Zeile die ganze
   Tabellenflucht nach rechts. */
.mi-mission__wer { overflow: hidden; }
.mi-mission__wer--gate { min-width: 0; }
.mi-gate__ic { display: inline-flex; flex: 0 0 auto; width: 14px; height: 14px; }
.mi-gate__ic svg { width: 14px; height: 14px; }
/* Das Gate selbst wird NIE gekuerzt — es ist die Aussage. Gekuerzt wird der
   Grund; er ist die Ergaenzung und steht vollstaendig im Titel. */
.mi-gate__text { flex: 0 0 auto; white-space: nowrap; font-weight: 600; }
.mi-gate__grund {
  flex: 0 1 auto; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  color: var(--text-secondary); font-weight: 400;
}
.mi-gate--blockiert { background: rgba(var(--tint-rgb), .10); color: var(--text-secondary); }

/* In der zugeklappten Zeile: an welcher Stelle des Weges der Fall steht.
   Zwei Missionen desselben Kunden lesen sich sonst gleich. */
.mi-mission__phase {
  font-size: 12px; color: var(--text-tertiary);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* Der aktuelle Schritt ist die Tuer in den Fall — dort stehen die Knoepfe.
   Hier wird nicht gehandelt: eine Tuer pro Handlung. */
.mi-tuer {
  display: inline-flex; align-items: center; min-height: 44px;
  color: var(--accent-strong); text-decoration: none;
}
.mi-tuer:hover { text-decoration: underline; }
.mi-tuer:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: var(--radius-card); }
.mi-tuer::after {
  content: '›'; margin-left: 8px; color: var(--accent);
  font-size: 15px; line-height: 1;
}

/* Die Luecke «offene Leads ohne Fall»: Text links, Handlung rechts. Sie steht
   zwischen Kachelzeile und Liste und braucht darum ihren eigenen Abstand —
   sonst klebt sie als zweites Stockwerk am Listen-Panel. Solange die Zahl
   noch nicht da ist, bleibt der Abschnitt unsichtbar statt als leerer Kasten
   zu blitzen. */
.mi-page [data-slot="luecke"] { margin-bottom: 16px; }
.mi-page [data-slot="luecke"]:empty { display: none; }
.mi-luecke {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px 20px; flex-wrap: wrap;
}
.mi-luecke__text { min-width: 0; }
.mi-luecke__text h2 { margin: 0; }
.mi-luecke__text p { margin: 6px 0 0; color: var(--text-secondary); font-size: 13px; }
.mi-luecke .primary-btn { min-height: 44px; }

/* =========================================================================
   Gantt (Referenz 13_25_33 (6), rechte Haelfte)

   Dieselbe Tabelle wie der Baum, nur mit einer breiten Zeitspalte statt des
   aufklappbaren Verlaufs. Die Balken kommen aus geplant_ab/geplant_bis; ein
   Schritt ohne Plan bekommt KEINEN Balken, sondern steht in der Spalte «Plan»
   als «ungeplant». Die «Heute»-Linie ist eine einzige Regel am Container und
   liegt darum ueber alle Zeilen hinweg auf derselben Flucht.
   ========================================================================= */
.mi-spalten--gantt,
.mi-mgruppe__kopf,
.mi-gzeile {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 180px) minmax(0, 200px) 200px minmax(0, 1.9fr);
  align-items: center; gap: 4px 14px;
}
.mi-liste--gantt { padding: 4px 20px 16px; }
/* Der Kopf traegt dasselbe Spaltenraster: die Spanne links, die «Heute»-Marke
   in DERSELBEN Spur, in der darunter die Balken liegen. */
.mi-gantt__kopf {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 180px) minmax(0, 200px) 200px minmax(0, 1.9fr);
  align-items: center; gap: 4px 14px;
  padding: 10px 0 6px; font-size: 12px; color: var(--text-tertiary);
  font-variant-numeric: tabular-nums;
}
.mi-gantt__spanne { grid-column: 1 / 5; }
.mi-gantt__heute {
  position: absolute; left: var(--heute); top: 0; transform: translateX(-50%);
  color: var(--warn-strong); font-weight: 600; white-space: nowrap;
}
.mi-spur--kopf::before { display: none; }
.mi-gantt__rest {
  margin: 10px 0 0; padding-top: 12px; border-top: 1px solid var(--border);
  color: var(--text-secondary); font-size: 12.5px;
}

/* Die Missionsklammer: mehrere Faelle unter EINEM Namen. Die Kopfzeile ist
   keine Ueberschrift im Sinne der Typo-Skala, sondern ein Gruppenband. */
.mi-mgruppe { border-bottom: 1px solid var(--border); }
.mi-mgruppe:last-of-type { border-bottom: 0; }
.mi-mgruppe__kopf {
  margin: 0; padding: 12px 0 6px;
  font-size: 13px; font-weight: 650; color: var(--text-primary);
}
.mi-mgruppe__name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mi-mgruppe__zahl { font-weight: 400; font-size: 12px; color: var(--text-tertiary); }

.mi-gzeile { position: relative; min-height: 56px; padding: 6px 0 6px 14px; }
.mi-gzeile + .mi-gzeile { border-top: 1px solid var(--line-soft, var(--border)); }
.mi-gzeile__haupt { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.mi-gzeile__haupt .case-work__link { font-size: 14px; }

/* Spalte «Plan»: entweder der Zeitraum oder ehrlich «ungeplant». */
.mi-plan { display: flex; align-items: center; gap: 8px; min-width: 0; flex-wrap: wrap; }
.mi-plan__zeit {
  font-size: 12.5px; color: var(--text-secondary);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.mi-plan__knopf { min-height: 44px; padding-inline: 10px; font-size: 12.5px; }
.mi-ungeplant {
  padding: 3px 8px; border-radius: var(--radius-button);
  border: 1px dashed var(--border); color: var(--text-tertiary);
  font-size: 12px; white-space: nowrap;
}

/* Die Spur ist die Zeitachse EINER Zeile; der Balken liegt auf ihr an genau
   der Stelle, die --l und --w vorgeben. Beides ist gerechnet, nichts ist
   gestaltet. */
.mi-spur { position: relative; height: 22px; min-width: 0; }
.mi-spur::before {
  content: ''; position: absolute; left: 0; right: 0; top: 50%;
  height: 1px; background: var(--line-strong);
}
/* Das Jetzt laeuft durch JEDE Spur an derselben Stelle: --heute steht einmal
   am Gantt-Container und wird vererbt. Dieselbe Bauart wie im Verlaufsbaum,
   wo sie seit W-B beweisbar deckungsgleich sitzt. */
.mi-spur::after {
  content: ''; position: absolute; left: var(--heute); top: -6px; bottom: -6px;
  width: 1px; background: rgba(var(--warn-rgb), .55); pointer-events: none;
}
.mi-balken {
  position: absolute; top: 50%; left: var(--l); width: var(--w);
  height: 10px; margin-top: -5px; border-radius: 5px;
  background: var(--accent);
}
.mi-balken--offen {
  background: linear-gradient(90deg, rgba(var(--accent-rgb), .85), rgba(var(--accent-rgb), .18));
}
.mi-balken--spaet { background: var(--bad); }
/* Die Frist als Raute — dasselbe Zeichen wie in der Referenz. */
.mi-raute {
  position: absolute; top: 50%; left: var(--l);
  width: 9px; height: 9px; margin: -4.5px 0 0 -4.5px;
  transform: rotate(45deg);
  background: var(--surface-1); border: 1.5px solid var(--accent);
}
.mi-raute--spaet { border-color: var(--bad); background: var(--bad); }

/* Der Zeitraum wird an der Zeile gesetzt, an der er gilt. */
.mi-planform {
  grid-column: 1 / -1;
  display: flex; align-items: flex-end; gap: 10px; flex-wrap: wrap;
  margin: 4px 0 8px; padding: 12px 14px;
  background: var(--surface-2); border-radius: var(--radius-panel, 12px);
}
.mi-planform__feld {
  display: flex; flex-direction: column; gap: 4px;
  font-size: 12px; color: var(--text-secondary);
}
.mi-planform__feld span { color: var(--text-tertiary); }
.mi-planform input[type="date"] {
  min-height: 44px; padding: 0 10px;
  background: var(--surface-1); color: var(--text-primary);
  border: 1px solid var(--border); border-radius: var(--radius-button);
  font: inherit; font-size: 13px;
}
.mi-planform .primary-btn,
.mi-planform .ghost-btn { min-height: 44px; }
.mi-planform__fehler {
  flex: 1 0 100%; margin: 0; color: var(--bad-strong); font-size: 12.5px;
}
.mi-planform__fehler[hidden] { display: none; }

/* Die Legende des Gantt fuehrt genau seine Zeichen. */
.mi-legende__balken {
  width: 22px; height: 8px; border-radius: 4px; background: var(--accent);
}
.mi-legende__balken--offen {
  background: linear-gradient(90deg, rgba(var(--accent-rgb), .85), rgba(var(--accent-rgb), .18));
}
.mi-legende__balken--spaet { background: var(--bad); }
.mi-legende__raute {
  width: 9px; height: 9px; transform: rotate(45deg);
  background: var(--surface-1); border: 1.5px solid var(--accent);
}

/* =========================================================================
   Schmal — eigener Block NACH den Basis-Regeln (Projekt-Cascade-Regel).
   Auf 390px stapelt die Zeile: Klappknopf und Firma oben, der naechste
   Schritt darunter, Lage und Frist in einer eigenen Zeile. Nichts wird
   versteckt; die Zeitachse rueckt unter den Schritt statt an den Rand.

   ⚠️ DIE GRENZE STAND AUF 900 PX — UND DAS WAR ZU SPÄT (25.08.2026).
   Gerechnet: die Basis-Zeile oben braucht 44 + 250 + 150 + 230 px feste
   Spalten plus vier Fugen à 14 = 730 px, BEVOR die Hauptspalte
   (`minmax(0, 1fr)`, Fallname und naechster Schritt) auch nur ein Pixel
   bekommt. Auf einem iPad quer (1024 px) ist die Zeile 690 px breit — die
   Seitenleiste ist dort schon wieder da und nimmt 292 px. Ergebnis, gemessen
   auf der echten Schale:

     .mi-mission__zeile  grid-template-columns: 44px  0px  210px 150px 230px
     .mi-mission__haupt  0 x 178 px      (Fallname + naechster Schritt)
     a.case-work__link   0 x 109 px      (der Weg in den Fall)

   Der Fallname und der EINZIGE Weg in den Fall waren null Pixel breit. Nicht
   ausgeblendet — null. Ein Berater mit einem iPad quer sah eine Liste aus
   leeren Zeilen, und kein Waechter hat je auf dieser Breite gemessen.

   Die Grenze liegt jetzt bei 1100 px: dort ist die Zeile 768 px breit und
   traegt die fuenf Spalten gerade noch (730 px). Darunter gilt die gestapelte
   Form, die es seit jeher gibt — es wird nichts Neues gebaut, die vorhandene
   schmale Form beginnt nur dort, wo sie wirklich gebraucht wird.
   ========================================================================= */
@media (max-width: 1100px) {
  /* Der Spaltenkopf gehoert zur Tabelle; sobald die Zeile stapelt, beschriftet
     er nichts mehr und waere ein leeres Versal-Band. */
  .mi-spalten { display: none; }
  .mi-mission__zeile { grid-template-columns: 44px minmax(0, 1fr); row-gap: 8px; }
  /* Lage, Frist und Verantwortliche unter den Titel, nicht unter den
     Klappknopf — sonst springt die zweite Zeile 58px nach links aus der
     Flucht. Sie stehen dort NEBENEINANDER, damit aus einer Zeile nicht vier
     werden. */
  /* NUR in der Baum-Zeile: `.mi-mission__lage` und `.mi-mission__wer` stehen
     auch im Gantt, und dort gibt es keine zweite Spalte. Ohne diese Bindung
     forderten sie dort eine — das Raster legte eine implizite Spalte an und
     drueckte die erste auf 0px, worauf der Missionsname buchstabenweise
     umbrach. Gemessen auf 390px, nicht vermutet. */
  .mi-mission__zeile > .mi-mission__lage,
  .mi-mission__zeile > .mi-frist,
  .mi-mission__zeile > .mi-mission__wer {
    grid-column: 2 / -1; justify-self: start; min-width: 0; max-width: 100%;
  }
  .mi-mission__schritt { white-space: normal; }
  .mi-mission__phase { white-space: normal; }

  /* Der Gantt stapelt: Titel, Lage, Owner/Gate und Plan untereinander, die
     Spur darunter ueber die volle Breite. Versteckt wird nichts — der Balken
     ist der Grund, warum es diese Ansicht gibt. */
  .mi-spalten--gantt { display: none; }
  .mi-gantt__kopf,
  .mi-mgruppe__kopf,
  .mi-gzeile { grid-template-columns: minmax(0, 1fr); row-gap: 6px; }
  .mi-gantt__spanne { grid-column: 1; }
  .mi-mgruppe__kopf { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
  .mi-gzeile { padding-left: 0; }
  .mi-plan { justify-self: start; }
  .mi-spur { width: 100%; }
}

@media (max-width: 720px) {
  .mi-liste { padding: 4px 14px; }
  .mi-liste--gantt { padding: 4px 14px 14px; }
  /* Die zwei Kalenderfelder untereinander: nebeneinander sind sie auf 390px
     zwei halbe Felder, in die kein Datum passt. */
  .mi-planform { flex-direction: column; align-items: stretch; }
  .mi-planform .primary-btn,
  .mi-planform .ghost-btn { width: 100%; }

  /* Der Schritt bleibt zweizeilig: Text oben ueber die volle Breite, darunter
     Person links und Zeitpunkt rechts. Drei gestapelte Zeilen je Schritt
     haetten aus vier Ereignissen eine halbe Bildschirmhoehe gemacht. Die
     Zeitachse rueckt darunter in ihre eigene Zeile — versteckt wird sie nie:
     Mobile ist keine Restgroesse. */
  .mi-schritt {
    grid-template-columns: 20px minmax(0, 1fr) auto;
    row-gap: 2px; padding: 9px 0; min-height: 44px;
  }
  .mi-schritt__text { grid-column: 2 / -1; white-space: normal; }
  .mi-schritt__wer { grid-column: 2; }
  .mi-schritt__zeit { grid-column: 3; min-width: 0; }
  .mi-achse { grid-column: 2 / -1; height: 14px; }
  .mi-achse::after { top: -4px; bottom: -4px; }
  .mi-luecke .primary-btn { width: 100%; }

  /* Fuenf Schritte nebeneinander sind auf 390px fuenf abgeschnittene Woerter.
     Die Leiste kippt darum in die Senkrechte: Kreis links, Name rechts, die
     Verbindungslinie laeuft mit. Versteckt wird sie nie — der Spot-Weg ist
     genau das, was der Mitarbeiter unterwegs wissen muss. */
  .mi-phasen { display: block; margin-left: 2px; }
  .mi-phase {
    flex: none; flex-direction: row; align-items: flex-start;
    gap: 10px; padding: 0 0 10px; text-align: left; flex-wrap: wrap;
  }
  .mi-phase:last-child { padding-bottom: 0; }
  .mi-phase::before {
    top: 22px; bottom: 0; left: 11px; right: auto; width: 1px; height: auto;
  }
  .mi-phase__name { flex: 1 1 auto; min-width: 0; }
  .mi-phase__wer,
  .mi-phase__frist { flex: 0 0 auto; margin-left: 32px; }
}

/* =========================================================================
   DIE HANDY-GESTALT DER FÄLLE — Karte 01.08., Position 12
   =========================================================================
   Gemessen: 5,0 Handy-Bildschirme, und der ERSTE war reine Schalttafel —
   fünf Kacheln (Fortschritt, Offene Fallarbeit, Blocker, Gate, Überfällig)
   und vier Umschalter (Meine/Team, Baum/Gantt, Ansicht sichern/löschen),
   bevor der erste Fall kam. Der Owner-Satz dazu: «Am Handy braucht es die
   Liste, nicht die Schalttafel.»

   DIE LINIE: am Handy trägt der erste Bildschirm den Titel, die Lücke
   («N offene Leads sind in keiner Fallarbeit sichtbar» — eine Handlung, kein
   Zierrat) und die Liste. Zahlen und Umschalter liegen hinter EINEM Knopf,
   ganz oben in Daumenreichweite. Nichts ist gelöscht: ein Tipp öffnet sie
   vollständig, ein zweiter schliesst sie.

   Der Knopf existiert nur hier. Am grossen Bildschirm ist er weg und alles
   steht offen — dieser Block wirkt ausschliesslich in @media.
   ========================================================================= */
.mi-tafel { display: none; }

@media (max-width: 720px) {
  .mi-tafel {
    display: inline-flex; align-items: center; justify-content: center;
    min-height: 44px; margin-left: auto;
  }
  /* Zugeklappt: die Liste beginnt direkt unter dem Titel. */
  .mi-page:not(.mi-page--tafel) .mi-schalter,
  .mi-page:not(.mi-page--tafel) .mi-kacheln { display: none; }
  /* ENTFERNT 04.09.2026 — die vierte Fassung derselben Frage.
     Hier stand `.mi-page--tafel .mi-kacheln { grid-template-columns:
     repeat(2, minmax(0, 1fr)); }` («die Kacheln zwei je Reihe statt fünf
     nebeneinander»). Am selben Tag um 08:19 hat das HAUS die Frage beim
     Bauteil beantwortet (Commit ac0d450f, grund.css Block «DIE EINE ZEILE»):
     unter 640 px ist ein Kennzahlen-Streifen EINE Reihe mit Rollweg und
     120 px Mindestbreite. Drei Flächen-Fassungen (Kundenliste, Offertenliste,
     Rechnungen) wurden dabei entfernt — diese hier wurde übersehen.
     Zurück blieb KEINE der beiden Antworten: die zwei expliziten Spalten
     trafen auf das `grid-auto-flow: column` der Systemregel, der Streifen
     bekam fünf Spuren, und die schmalste Kachel mass 24 px mit
     abgeschnittenen Zahlen («Fortschritt», «Offene Fallarbeit») — gemessen
     390 px, `node scripts/_missionen_ui_test.mjs`. Rückweg: git. */
  .mi-page--tafel .mi-schalter { width: 100%; }
  /* Der Knopf sitzt in der Kopfzeile neben dem Titel. */
  .mi-page .admin-page__head { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }
  .mi-page .admin-page__head h1 { flex: 1 1 auto; min-width: 0; }
  .mi-tafel[aria-expanded="true"] { border-color: var(--accent); color: var(--accent-strong); }
}

/* ============================================================
   Patch-Integration — Namensraum bs-; Quelle: docs/design/patch-buchungsstrecke.css
   Der Block wird bei Integration als GANZES ersetzt, nie editiert. Steht NACH .kp-* und den R1/R2-Patches (Kaskade).
   ============================================================ */
/* ===========================================================================
   Buchungsstrecke (#/k → «Werbung buchen») — Patch zu public/style.css
   Welle «Exakt nach Referenz, Runde 2», Team C3 · 2026-07-29
   Referenz: ZIELBILD-2026-07-28.md §LoopScreens («Buchungsstrecke in Schritten
   mit Schweizer Karte»), Weg der Elemente in PROTOTYP-ANALYSE.md §E.

   EINBAU: diesen Block unverändert ans Ende von `public/style.css` hängen —
   nach dem `.kp-*`-Block (heute style.css:5005-5095) und nach dem Patch der
   Kommandozentrale, damit die Mobile-Regeln NACH ihren Basisregeln stehen
   (Memory project_css_cascade_mobile).
   Es wird keine bestehende Regel geändert und keine überschrieben; alle
   Selektoren tragen den Präfix `bs-` oder hängen darunter.

   Wiederverwendet statt nachgebaut: .panel · .panel__header · .panel__title ·
   .stat-strip--auto · .stat · .kp-row/__name/__ort/__screens/__grenze ·
   .kp-liste · .kp-seg · .kp-preis · .kp-abschluss ·
   .kp-pruefen · .primary-btn · .ghost-btn · .kp-count · .empty-state.
   Neu sind nur: Schritt-Leiste, Gebietskarten, Karte, Auswahl-Spalte,
   Zusammenfassung, Zahlweise, Ablauf.

   09.08.2026 — die Buchung ist EINE Cockpit-Flaeche (4810c35). Mit den
   Blattbauern `schritt1()`/`auswahlPanel()`/`schritt2()` sind hier zehn
   Selektoren ohne Verwender gefallen: .bs-buehne · .bs-auswahl (der sticky
   Rahmen; die __-Kinder leben in `auswahlInhalt()` weiter) · .bs-auswahl__preis ·
   .bs-weiter · .bs-schritt__preis · .bs-stat__sub · .bs-karte__reset ·
   .bs-karte__rand · .kp-cfg · .kp-filter. Die Flaeche nutzt stattdessen
   .kk-wo/.kk-cfg/.kk-filterzeile und die Cockpit-Schale.
   =========================================================================== */

/* Ein Schritt ist entweder da oder nicht. `hidden` bleibt wirksam — deshalb
   steht die Regel VOR jeder Layout-Regel auf .bs-schritt. */
.bs-schritt[hidden] { display: none; }

/* Das Symbol-Quadrat (.gz-ic, style.css:6938) trägt hier den Akzent statt einer
   Bereichsfarbe: die Kundenwelt ist EIN Bereich. Farbe und Feld stehen mit
   zwei Klassen, weil ältere Regeln wie `.bs-zahlweise > span` jedes span in
   ihrer Karte einfärben — ohne diese Zeile stünde das Zeichen grau, solange
   der Vorgängerblock noch in style.css liegt. */
.bs-schritt .gz-ic, .bs-abschluss .gz-ic {
  color: rgb(var(--gz-feld));
  background: rgba(var(--gz-feld), .13);
}

/* --- Schritt-Leiste --------------------------------------------------------
   Drei Punkte, waagrecht, mit Verbindungslinie. Der aktive trägt den Akzent,
   der erledigte einen ruhigen Ton, der gesperrte ist sichtbar gesperrt. */
.bs-schritte {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 8px;
  list-style: none;
  margin: 0 0 18px;
  padding: 0;
}
.bs-schritt-punkt { position: relative; min-width: 0; }
/* Die Linie zum nächsten Punkt liegt HINTER der Nummer, nicht zwischen den
   Wörtern — sonst bricht sie auf schmalen Breiten mitten in die Schrift. */
.bs-schritt-punkt:not(:last-child)::after {
  content: "";
  position: absolute;
  left: calc(50% + 20px); right: calc(-50% + 20px); top: 15px;
  height: 1px;
  background: var(--hairline-strong);
}
.bs-schritt-punkt__tun {
  display: flex; flex-direction: column; align-items: center; gap: 6px;
  width: 100%; padding: 4px 2px 2px;
  background: transparent; border: 0; color: var(--text-tertiary);
  font: inherit; font-size: 12.5px; font-weight: 600; cursor: pointer;
  transition: color var(--transition);
}
.bs-schritt-punkt__tun:disabled { cursor: default; opacity: .55; }
.bs-schritt-punkt__tun:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: var(--radius-card); }
.bs-schritt-punkt__nr {
  display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; border-radius: 999px;
  background: var(--surface-inset); border: 1px solid var(--border);
  color: var(--text-secondary);
  font-size: 13px; font-weight: 650; font-variant-numeric: tabular-nums;
  position: relative; z-index: 1;
  transition: background var(--transition), color var(--transition);
}
.bs-schritt-punkt__wort { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 100%; }
.bs-schritt-punkt__nr svg { width: 15px; height: 15px; }
/* Drei Zustände, drei Formen (EINHEIT 4.5): erledigt = gefüllter Kreis mit
   Häkchen, aktiv = gefüllter Kreis mit Nummer, offen = Umriss-Kreis mit Nummer.
   Erledigt und aktiv sind beide gefüllt — sie unterscheiden sich am Inhalt,
   genau wie in der Referenz `13_21_08 (8)`. */
.bs-schritt-punkt.is-fertig .bs-schritt-punkt__nr { background: var(--accent); color: var(--on-accent); border-color: transparent; }
.bs-schritt-punkt.is-fertig .bs-schritt-punkt__tun { color: var(--text-secondary); }
.bs-schritt-punkt.is-aktiv .bs-schritt-punkt__nr { background: var(--accent); color: var(--on-accent); border-color: transparent; }
.bs-schritt-punkt.is-aktiv .bs-schritt-punkt__tun { color: var(--text-primary); }
/* Die erledigte Strecke ist durchgezogen im Akzent — sie zeigt, wie weit man
   ist, ohne eine zweite Fortschrittsanzeige zu sein. */
.bs-schritt-punkt.is-fertig:not(:last-child)::after { background: var(--accent-line); }

/* Die EINE Zeile je Schritt (EINHEIT 1.6) — was dieser Schritt vom Kunden
   will. Kein zweiter Erklärsatz, keine Überschrift, die das Wort der
   Schrittleiste wiederholt. */
.bs-satz {
  margin: -6px 0 16px;
  font-size: 14px; line-height: 1.5; color: var(--text-secondary);
}

/* --- Gebietswahl -----------------------------------------------------------
   Vier Karten, eine gewählt. Gleiche Sprache wie .kk-karte in der Zentrale —
   bewusst nicht dieselbe Klasse: dort ist eine Karte ein Weg, hier ein
   Zustand, und ein Zustand braucht «gewählt». */
.bs-gebiete {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
  gap: 12px;
  margin-bottom: 16px;
}
.bs-gebiet {
  display: grid;
  grid-template-columns: auto auto minmax(0, 1fr);
  grid-template-areas: "marke ic wort" "marke ic zahl";
  align-items: center; gap: 1px 11px;
  padding: 13px 15px; text-align: left;
  background: var(--surface-2); border: 1px solid var(--border);
  border-radius: var(--radius-card); color: inherit; font: inherit; cursor: pointer;
  --gz-feld: var(--accent-rgb);
  transition: background var(--transition), border-color var(--transition);
}
.bs-gebiet:hover { background: var(--surface-3); }
.bs-gebiet:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.bs-gebiet .gz-ic { grid-area: ic; }
.bs-gebiet > b { grid-area: wort; font-size: 14px; font-weight: 600; color: var(--text-primary); align-self: end; }
.bs-gebiet__zahl { grid-area: zahl; font-size: 12px; color: var(--text-tertiary);
  font-variant-numeric: tabular-nums; align-self: start; }
/* Die Auswahl-Marke der EINFACHwahl (EINHEIT 4.4): Radio-Kreis links. Sie ist
   der Unterschied zur Standortliste darunter, die Kästchen trägt — der Rahmen
   allein sagt nicht, ob man eines oder mehrere wählen darf. */
.bs-gebiet__marke {
  grid-area: marke;
  width: 17px; height: 17px; border-radius: 50%;
  border: 1.5px solid var(--hairline-strong);
  transition: border-color var(--transition), box-shadow var(--transition);
}
/* Gewählt = Marke + Inset-Balken + Tint, nie Vollborder (DESIGN.md §Verbote,
   wie .kp-row.is-on). */
.bs-gebiet.is-aktiv { background: var(--accent-soft); box-shadow: inset 2.5px 0 0 var(--accent); }
.bs-gebiet.is-aktiv > b { color: var(--text-primary); }
/* Der gefüllte Punkt als Verlauf statt als Innenschatten: so bleibt der Ring
   zwischen Rand und Punkt in der Farbe der Karte, egal ob sie getönt ist. */
.bs-gebiet.is-aktiv .bs-gebiet__marke {
  border-color: var(--accent);
  background: radial-gradient(circle at center, var(--accent) 0 4px, transparent 4px);
}

/* --- Spalte: gestapelte Panels (Prüfschritt) ------------------------------- */
.bs-spalte { display: flex; flex-direction: column; gap: 16px; min-width: 0; }

/* --- Schweizer Karte -------------------------------------------------------
   Skaliert über viewBox; die Höhe folgt der Breite. Kein fixes px-Mass, damit
   sie von 320px bis 1400px dasselbe Bild ist. Die Deckelung ist kein
   Geschmack: ohne sie ist die Karte auf 1400px 730px hoch und schiebt die
   Standortliste unter die Falz — der Kunde sähe die Auswahl gar nicht. 780px
   ⇒ 500px Höhe: die Karte füllt das Panel bis auf einen ruhigen Rand, und die
   erste Zeile der Standortliste steht noch im Bild. */
.bs-karte { display: block; width: 100%; max-width: 780px; height: auto; margin: 4px auto 2px; }
.bs-kanton {
  fill: var(--surface-inset);
  stroke: var(--border);
  stroke-width: 1.5;
  transition: fill var(--transition);
}
/* Kanton mit buchbaren Standorten: Akzentfläche. Ohne Standorte bleibt er
   stumm — keine Hand, kein Fokus, kein Klick (project_sichtbar_ist_nicht_bedienbar). */
.bs-kanton.is-frei { fill: rgba(var(--accent-rgb), .22); cursor: pointer; }
/* Zeigerfarbe NUR, wo es einen Zeiger gibt. Auf dem Handy bleibt ein :hover
   nach dem Antippen am zuletzt berührten Element kleben — der Kanton, den man
   gerade gewählt hat, trüge dann dauerhaft die Hover-Farbe statt der
   Auswahl-Farbe. */
@media (hover: hover) and (pointer: fine) {
  .bs-kanton.is-frei:hover { fill: rgba(var(--accent-rgb), .38); }
}
.bs-kanton.is-frei:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

/* WAS IM KORB LIEGT, MUSS MAN SEHEN.
   Owner-Befund 08.08. am Bild: «auf beiden Karten-Bildern sehen alle Kantone
   gleich aus, ob im Korb oder nicht» — die wichtigste Rückmeldung der Fläche
   fehlte. Am Pixel nachgemessen: der gewählte Kanton rendert als rgb(8,83,86)
   gegen rgb(5,53,58) der übrigen, eine Helligkeitsstufe im Dunkeln.
   Ursache war NICHT ein zu schwacher Entwurf, sondern eine Spezifitäts-Falle:
   `.bs-kanton.is-frei:hover` (0,3,0) schlug `.bs-kanton.is-aktiv` (0,2,0) —
   wer einen gewählten Kanton berührte, machte ihn dadurch wieder
   ungewählt-aussehend. Die Auswahl schlägt ab jetzt jede Zwischenfarbe, und
   sie trägt zusätzlich eine helle Kontur: Farbe allein ist eine Nuance,
   Kontur plus Farbe ist eine Aussage — auch auf 390 px und auch für Augen,
   die Türkis-Abstufungen nicht trennen. */
.bs-kanton.is-aktiv {
  fill: var(--accent);
  stroke: var(--text);
  stroke-width: 2.25;
}
.bs-kanton.is-frei.is-aktiv,
.bs-kanton.is-frei.is-aktiv:hover { fill: var(--accent); }

/* ---- Geo-Drill: Netz → Region → Kanton → Ort (Owner-Auftrag 05.08.) -------- */
/* Regionen-Ebene: die Kantone einer Region tragen dieselbe Farbe, ihre
   Innengrenzen treten zurück. So entsteht eine Regionsfläche, ohne dass
   Geometrie verschmolzen werden muss. */
.bs-kanton--region { stroke: rgba(var(--accent-rgb), .16); stroke-width: .8; }
.bs-kanton--region.is-frei { stroke: rgba(var(--accent-rgb), .3); }
.bs-kanton--region.is-aktiv { stroke: var(--accent); stroke-width: 1.2; }
/* Ort-Ebene: die Flächen sind nur noch Kulisse — die Punkte tragen die Auswahl. */
.bs-kanton--ruhig { fill: var(--surface-inset); stroke: rgba(140, 168, 196, .1); cursor: default; }
.bs-kanton--ruhig.is-frei { fill: rgba(var(--accent-rgb), .07); cursor: default; }

.bs-ort { cursor: pointer; }
.bs-ort__flaeche {
  fill: rgba(var(--accent-rgb), .30);
  stroke: var(--accent); stroke-width: 1.6;
  transition: fill var(--transition);
}
.bs-ort:hover .bs-ort__flaeche { fill: rgba(var(--accent-rgb), .5); }
.bs-ort.is-gewaehlt .bs-ort__flaeche { fill: var(--accent); stroke: var(--accent-bright); stroke-width: 2.4; }
.bs-ort:focus-visible { outline: none; }
.bs-ort:focus-visible .bs-ort__flaeche { stroke: #fff; stroke-width: 3; }
.bs-ort__zahl {
  fill: var(--text-primary);
  font-size: 15px; font-weight: 700; font-variant-numeric: tabular-nums;
  pointer-events: none;
}
.bs-ort.is-gewaehlt .bs-ort__zahl { fill: var(--on-accent); }
.bs-ort__wort {
  fill: var(--text-secondary);
  font-size: 15px; font-weight: 600;
  paint-order: stroke; stroke: var(--surface-1); stroke-width: 3.5px; stroke-linejoin: round;
  pointer-events: none;
}
.bs-ort.is-gewaehlt .bs-ort__wort { fill: var(--text-primary); }
/* Kein Landesumriss mehr: seit die Flächen die amtliche Geometrie tragen
   (swisstopo, 2026-08-05), IST die Aussenkante der Kantone die Landesgrenze.
   Die alte Akzentlinie stammte vom handgesetzten Umriss der Näherung und läge
   heute daneben. Die Regel dafür (`.bs-karte__rand`) ist am 09.08. gefallen —
   sie stand nur noch «für den Fall, dass jemand sie wieder zeichnet», und eine
   Regel ohne Verwender ist Ballast, kein Vorrat. */

/* Neun Städte als stille Orientierung — nur wo ausdrücklich verlangt
   (schweizKarte({ staedte: true })). Sie sind Landmarke, nicht Inhalt: eine
   Stufe leiser als die eigenen Ortspunkte, nie anklickbar.
   Schriftgrössen sind viewBox-Einheiten — bei 1000 breit und ≥820px Anzeige
   bleibt 17px über dem 11px-Floor (§2 DESIGN.md). Schmaler wird gestaffelt. */
.bs-stadt__punkt { fill: var(--text-tertiary); opacity: .55; }
.bs-stadt__wort {
  fill: var(--text-secondary);
  font-size: 17px; font-weight: 560; letter-spacing: .01em;
  paint-order: stroke;
  stroke: var(--surface-1); stroke-width: 3.5px; stroke-linejoin: round;
}
.bs-kanton__zahl {
  fill: var(--text-primary);
  font-size: 21px; font-weight: 650; font-variant-numeric: tabular-nums;
  pointer-events: none;
}

/* --- Auswahl-Zone (Cockpit-Fläche, `auswahlInhalt()`) ---------------------- */
.bs-auswahl__zahlen { margin-bottom: 12px; }
.bs-auswahl__liste {
  list-style: none; margin: 0 0 12px; padding: 0;
  max-height: 240px; overflow-y: auto;
}
.bs-auswahl__row {
  display: grid; align-items: center; gap: 2px 10px;
  grid-template-columns: minmax(0, 1fr) auto 32px;
  grid-template-areas: "name screens weg" "ort screens weg";
  padding: 8px 0; border-bottom: 1px solid var(--hairline);
}
.bs-auswahl__row:last-child { border-bottom: 0; }
.bs-auswahl__row .kp-row__name { grid-area: name; }
.bs-auswahl__row .kp-row__ort { grid-area: ort; }
.bs-auswahl__row .kp-row__screens { grid-area: screens; }
.bs-auswahl__weg {
  grid-area: weg;
  width: 30px; height: 30px; border-radius: var(--radius-card);
  background: transparent; border: 0; color: var(--text-tertiary);
  font-size: 17px; line-height: 1; cursor: pointer;
  transition: background var(--transition), color var(--transition);
}
.bs-auswahl__weg:hover { background: var(--surface-3); color: var(--text-primary); }
.bs-auswahl__weg:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* Nur noch PLATZIERUNG. Bis zum 22.08.2026 stand hier zusaetzlich
   `padding: 18px 12px` — eine Marke am Kanon, die seine Polsterung umschrieb
   (34px 0). Damit sah der Leerzustand in dieser Spalte anders aus als
   ueberall sonst, und weil die Klasse `__leer` heisst und nicht `-leer`, hat
   sie keine der bisherigen Zaehlungen je gesehen. Das knappe Mass ist
   richtig — es heisst im Haus `.empty-state--compact` und steht jetzt im
   Markup (views/kunde-portal.js). Wo der Absatz sitzt, bleibt hier. */
.bs-auswahl__leer { margin: 0 0 12px; }
.bs-auswahl__leeren { width: 100%; margin-bottom: 10px; }

/* Teilweise gewähltes Bündel (3 von 8 Salons im Kanton): sichtbar dazwischen. */
.kp-row.is-teil { box-shadow: inset 2.5px 0 0 var(--accent-line); }

/* --- Schritt 2 + 3 --------------------------------------------------------- */
/* Die gewählte Laufzeit ist ein aktiver Zustand — und der trägt aussen wie
   innen den EINEN Akzent (EINHEIT 1.3). `.seg__btn.is-active` ist im Fundament
   grau; hier bekommt nur die Laufzeit-Reihe der Kundenwelt den Türkis-Ton,
   damit kein fremdes Segment mitkippt. `.kp-seg` gibt es genau einmal
   (kunde-portal.js:968). */
.kp-seg .seg__btn.is-active { background: var(--accent-soft); color: var(--text-primary); }
.bs-panel { margin-top: 16px; }
.bs-nav { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; margin-top: 16px; }

/* Prüfschritt: drei Spalten wie die Referenz `13_21_08 (8)` — Buchung ·
   Preis + Zahlweise · Ablauf + Vertrauen. Untereinander wäre derselbe Inhalt
   auf 1400px zweieinhalb Bildhöhen, und der Abschluss stünde unter der Falz. */
/* KAESTEN IN EINER REIHE TEILEN IHRE UNTERKANTE (Hausregel 06.09.2026).
   Hier stand `align-items: start`; damit war jeder Kasten nur so hoch wie sein
   Inhalt und die Unterkanten flatterten. Anlass ist die Betreiber-Akte
   («so viele Bereiche versetzt und nicht schoen geordnet», 06.09.), aber der
   Fehler steckte in vier Blaettern zugleich — er wird darum an jeder Quelle
   entfernt, nicht an einer Stelle ueberschrieben. `stretch` ist die Vorgabe
   von Grid; die Zeile faellt ersatzlos weg. Waechter:
   `npm run test:kastenkanten`. */
.bs-pruefen {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 16px;
}

.bs-zusammen {
  display: grid; grid-template-columns: minmax(0, auto) minmax(0, 1fr);
  gap: 0; margin: 4px 0 0;
  --gz-feld: var(--accent-rgb);
}
.bs-zusammen dt, .bs-zusammen dd {
  padding: 10px 0; margin: 0; border-bottom: 1px solid var(--hairline);
}
/* Zeichen + Label in gemischter Schreibung (EINHEIT 1.5: gesperrte Versalien
   tragen genau eine Aufgabe, den Spaltenkopf — und das hier ist keine Tabelle). */
.bs-zusammen dt {
  display: flex; align-items: center; gap: 10px; white-space: nowrap;
  color: var(--text-secondary); font-size: 12.5px; font-weight: 500;
  text-transform: none; letter-spacing: 0;
}
.bs-zusammen dt .gz-ic { --gz-ic-gr: 26px; }
.bs-zusammen dd { font-size: 14px; color: var(--text-primary); text-align: right;
  align-self: center; padding-left: 14px; }
.bs-zusammen dt:last-of-type, .bs-zusammen dd:last-of-type { border-bottom: 0; }

/* Preisübersicht — eine Bauart, überall dieselbe (EINHEIT 5.7): Zeilen statt
   Kachelreihe, Total in Türkis und grösser. Die .stat-Bausteine bleiben, nur
   ihre Anordnung wechselt: dieselben Klassen tragen dieselben Zahlen. */
.bs-preis { display: grid; gap: 0; }
.bs-preis .stat {
  display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: baseline;
  gap: 12px; padding: 10px 0; background: none; border: 0; border-radius: 0;
  border-bottom: 1px solid var(--hairline);
}
.bs-preis .stat:hover { background: none; }
.bs-preis .stat:last-child { border-bottom: 0; }
.bs-preis .stat__label { font-size: 13px; white-space: normal; }
.bs-preis .stat__value { font-size: 14px; font-weight: 600; letter-spacing: 0; text-align: right; }
.bs-preis__total { padding-top: 12px !important; margin-top: 2px; border-top: 1px solid var(--hairline-strong); }
.bs-preis__total .stat__label { color: var(--text-primary); font-size: 14px; font-weight: 600; }
.bs-preis__total .stat__value { font-size: 20px; font-weight: 650; letter-spacing: -.4px; color: var(--accent); }

/* Zahlweise: EIN Weg, weil es genau einen gibt (EINHEIT 5.10, Owner-Veto V2 —
   für Karte und TWINT existiert kein Anbieter). Deshalb kein Radio-Feld und
   kein gesperrter Knopf, sondern die Ansage, was passiert. */
.bs-zahlweise {
  display: grid; grid-template-columns: auto minmax(0, 1fr);
  grid-template-areas: "ic kopf" "ic satz";
  align-items: center; gap: 2px 12px;
  padding: 14px 16px; margin-top: 4px;
  background: var(--surface-2); border-radius: var(--radius-card);
  box-shadow: inset 2.5px 0 0 var(--accent);
  --gz-feld: var(--accent-rgb);
}
.bs-zahlweise .gz-ic { grid-area: ic; }
.bs-zahlweise > b { grid-area: kopf; font-size: 14px; font-weight: 600; color: var(--text-primary); align-self: end; }
.bs-zahlweise > span:not(.gz-ic) { grid-area: satz; font-size: 12.5px; line-height: 1.45; color: var(--text-secondary); align-self: start; }

/* Vertrauensstreifen — genau drei Punkte, nur im letzten Schritt
   (EINHEIT 4.14). Jeder Punkt ist eine Aussage über dieses System, kein
   Siegel: was hier steht, lässt sich am Code nachlesen. */
.bs-vertrauen { list-style: none; margin: 0; padding: 0; display: grid; gap: 14px;
  --gz-feld: var(--accent-rgb); }
.bs-vertrauen__punkt {
  display: grid; grid-template-columns: auto minmax(0, 1fr);
  grid-template-areas: "ic kopf" "ic satz"; align-items: center; gap: 1px 12px;
}
.bs-vertrauen__punkt .gz-ic { grid-area: ic; }
.bs-vertrauen__punkt > b { grid-area: kopf; font-size: 13.5px; font-weight: 600; align-self: end; }
.bs-vertrauen__punkt > span { grid-area: satz; font-size: 12px; line-height: 1.4;
  color: var(--text-secondary); align-self: start; }

/* Abschluss: ein voller Knopf über die ganze Breite mit Schloss, darunter der
   AGB-Satz (EINHEIT 3.6/5.11 und Referenz `13_21_08 (8)`). Er steht UNTER den
   Panels, nicht in einer Spalte — die Buchung ist die Handlung der ganzen
   Fläche, nicht die einer Karte. */
.bs-abschluss { margin-top: 16px; }
.bs-abschluss .kp-abschluss, .bs-abschluss .kp-pruefen { margin-top: 0; }
.bs-abschluss .kp-pruefen { padding-top: 0; border-top: 0; }
.bs-abschluss .kp-pruefen__satz { font-size: 15px; text-align: center; }
.bs-abschluss .kp-abschluss { flex-direction: column; align-items: stretch; gap: 10px; }
.bs-buchen {
  display: inline-flex; align-items: center; justify-content: center; gap: 9px;
  width: 100%; min-height: 48px; font-size: 15px;
}
.bs-buchen svg { width: 17px; height: 17px; }
.bs-agb {
  margin: 10px 0 0; text-align: center;
  font-size: 12px; line-height: 1.45; color: var(--text-tertiary);
}

.bs-ablauf { list-style: none; margin: 4px 0 0; padding: 0; display: grid; gap: 2px; }
.bs-ablauf__punkt {
  display: grid; grid-template-columns: 26px minmax(0, 1fr); gap: 2px 12px;
  grid-template-areas: "nr wort" ". satz";
  padding: 10px 0; border-bottom: 1px solid var(--hairline);
}
.bs-ablauf__punkt:last-child { border-bottom: 0; }
.bs-ablauf__nr {
  grid-area: nr;
  display: inline-flex; align-items: center; justify-content: center;
  width: 24px; height: 24px; border-radius: 999px;
  background: var(--surface-inset); color: var(--text-secondary);
  font-size: 12px; font-weight: 650; font-variant-numeric: tabular-nums;
}
.bs-ablauf__punkt > b { grid-area: wort; font-size: 14px; font-weight: 600; align-self: center; }
.bs-ablauf__satz { grid-area: satz; font-size: 12.5px; line-height: 1.45; color: var(--text-secondary); }

/* --- Touch + Tablet --------------------------------------------------------
   Der Touch-Boden greift auch in der Tablet-Bruchzone 768/1024
   (Memory project_tablet_touch_breakpoint) — 720px allein deckt sie nicht ab. */
@media (max-width: 1024px), (pointer: coarse) {
  .bs-gebiet { min-height: 60px; }
  .bs-schritt-punkt__tun { min-height: 52px; }
  .bs-nav .ghost-btn, .bs-auswahl__leeren,
  .bs-abschluss .ghost-btn { min-height: 44px; }
  .bs-auswahl__weg { width: 44px; height: 44px; }
  .bs-auswahl__row { grid-template-columns: minmax(0, 1fr) auto 44px; }
  /* Auf dem Touchgerät ist ein Kanton oft kleiner als eine Fingerkuppe. Die
     Karte bleibt der Überblick, gewählt wird über Liste und Kantonsfeld —
     beide bleiben sichtbar, kein Weg hängt allein an der Karte. */
  .bs-kanton__zahl { font-size: 26px; }
}

/* --- Handy ---------------------------------------------------------------- */
/* Drei Spalten tragen ab ~1080px: darunter fällt die Preiszeile «MwSt 8,1 %»
   mit ihrem Betrag auf zwei Zeilen, und die Zusammenfassung bricht den
   Standortnamen mitten im Wort. */
@media (max-width: 1080px) {
  .bs-pruefen { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .bs-pruefen > .panel:first-child { grid-column: 1 / -1; }
}

@media (max-width: 900px) {
  .bs-pruefen { grid-template-columns: minmax(0, 1fr); }
}

@media (max-width: 720px) {
  /* Die Schritte stehen untereinander: drei Wörter nebeneinander fallen auf
     390px unter den Schrift-Floor (DESIGN.md §2: nichts unter 11px). */
  .bs-schritte { grid-template-columns: minmax(0, 1fr); gap: 2px; }
  .bs-schritt-punkt:not(:last-child)::after { display: none; }
  .bs-schritt-punkt__tun {
    flex-direction: row; justify-content: flex-start; gap: 12px;
    padding: 8px 4px; font-size: 13.5px;
  }
  .bs-schritt-punkt__wort { white-space: normal; }
  .bs-gebiete { grid-template-columns: minmax(0, 1fr); gap: 8px; }
  .bs-nav { flex-direction: column-reverse; align-items: stretch; }
  .bs-nav > .ghost-btn { width: 100%; }
  /* Auf 390px steht der Wert unter seinem Label: nebeneinander bliebe für
     «Salon Nord, Salon Pause» keine lesbare Breite. */
  .bs-zusammen { grid-template-columns: minmax(0, 1fr); }
  .bs-zusammen dt { padding-bottom: 0; border-bottom: 0; }
  .bs-zusammen dd { padding-top: 2px; padding-left: 0; text-align: left; }
  .bs-auswahl__liste { max-height: none; }
  .bs-satz { font-size: 13.5px; margin-bottom: 14px; }
}

/* ===========================================================================
   W-E/E3 · Freigabe-Check vor dem Abschluss + Status-Zeitstrahl
   Referenz: `13_21_27 (9)` (Prüfliste + verbotene Kategorien),
             `13_21_07 (7)` (gesperrter Abschluss mit Grund),
             `13_21_29 (11)` (senkrechter Status-Zeitstrahl).
   Wiederverwendet statt nachgebaut: .panel · .panel__header · .panel__title ·
   .sl-badge · .gz-ic · .kp-abschluss · .primary-btn.
   =========================================================================== */

/* Die Prüfliste steht als volle Breite zwischen Panels und Abschluss — dort,
   wo sie beisst. Der Abstand nach unten ist der der Panels, damit sie nicht
   wie ein angehängter Kasten wirkt. */
.bs-freigabe { margin-top: 16px; }
.bs-freigabe__zaehler {
  font-size: 12px; font-weight: 600; color: var(--text-tertiary);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.bs-freigabe__liste { list-style: none; margin: 4px 0 0; padding: 0; }
.bs-freigabe__punkt + .bs-freigabe__punkt { border-top: 1px solid var(--hairline); }
/* Ein Punkt ist EIN Tap über die ganze Zeile — nicht ein Kästchen von 14px.
   Zeile statt Kachel, weil die Liste in der Referenz eine Liste ist. */
.bs-freigabe__tun {
  display: grid;
  grid-template-columns: 30px minmax(0, 1fr) auto;
  grid-template-areas: "marke kopf stand" "marke satz stand";
  align-items: center;
  gap: 2px 12px;
  width: 100%; min-height: 56px; padding: 10px 2px;
  background: transparent; border: 0; color: var(--text-primary);
  font: inherit; text-align: left; cursor: pointer;
}
.bs-freigabe__tun:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: var(--radius-card); }
/* Zwei Zustände, zwei Formen (EINHEIT 4.4/4.5): bestätigt = Häkchen im
   gefüllten Türkis-Kreis, offen = leerer Umriss-Kreis. Nie ein nacktes
   Häkchen, nie ein Rahmen ohne Marke. */
.bs-freigabe__marke {
  grid-area: marke;
  display: inline-flex; align-items: center; justify-content: center;
  width: 26px; height: 26px; border-radius: var(--radius-badge);
  background: var(--surface-inset); border: 1px solid var(--border);
  color: var(--on-accent);
  transition: background var(--transition), border-color var(--transition);
}
.bs-freigabe__marke svg { width: 14px; height: 14px; }
.bs-freigabe__punkt.is-an .bs-freigabe__marke { background: var(--accent); border-color: transparent; }
.bs-freigabe__tun > b { grid-area: kopf; font-size: 14px; font-weight: 600; align-self: end; }
.bs-freigabe__satz {
  grid-area: satz; font-size: 12px; line-height: 1.4;
  color: var(--text-tertiary); align-self: start;
}
.bs-freigabe__stand { grid-area: stand; align-self: center; }

/* Die verbotenen Kategorien: eine Aussage über die REGEL, nicht über den Spot.
   Deshalb Verbots-Zeichen statt Häkchen — ein grünes Häkchen behauptete, wir
   hätten geprüft, dass die Werbung keiner Kategorie angehört. Das kann heute
   niemand: das Material kommt erst nach der Buchung. */
.bs-verboten { margin-top: 14px; padding-top: 14px; border-top: 1px solid var(--hairline); }
.bs-verboten__kopf { display: block; font-size: 13px; font-weight: 650; }
.bs-verboten__satz { margin: 2px 0 10px; font-size: 12px; color: var(--text-tertiary); }
.bs-verboten__liste {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: 8px 16px;
}
.bs-verboten__punkt {
  display: flex; align-items: center; gap: 8px;
  font-size: 13px; color: var(--text-secondary);
}
.bs-verboten__punkt .gz-ic { --gz-ic-gr: 22px; color: var(--text-tertiary); }

/* Der Grund unter dem gesperrten Knopf. Er steht IMMER da, wenn der Knopf zu
   ist — ein gesperrter Knopf ohne Grund ist die Sackgasse, die EINHEIT 3.6
   verbietet. */
.bs-warum {
  margin: 8px 0 0; text-align: center;
  font-size: 12.5px; line-height: 1.5; color: var(--warn-strong);
}

/* Status-Zeitstrahl auf der Bestätigung — senkrecht, mit durchgehender Linie
   HINTER den Marken (dieselbe Bauart wie die waagerechte Schrittleiste). */
.bs-strahl { list-style: none; margin: 4px 0 0; padding: 0; }
.bs-strahl__stufe {
  position: relative;
  display: grid;
  grid-template-columns: 28px minmax(0, 1fr);
  grid-template-areas: "marke kopf" "marke satz";
  gap: 2px 12px;
  padding: 0 0 18px;
}
.bs-strahl__stufe:last-child { padding-bottom: 0; }
.bs-strahl__stufe:not(:last-child)::after {
  content: "";
  position: absolute; left: 13px; top: 28px; bottom: 4px;
  width: 1px; background: var(--hairline-strong);
}
.bs-strahl__stufe.is-fertig:not(:last-child)::after { background: var(--accent-line); }
.bs-strahl__marke {
  grid-area: marke;
  display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px; border-radius: var(--radius-badge);
  background: var(--surface-inset); border: 1px solid var(--border);
  color: var(--text-secondary);
  font-size: 12.5px; font-weight: 650; font-variant-numeric: tabular-nums;
  position: relative; z-index: 1;
}
.bs-strahl__marke svg { width: 14px; height: 14px; }
.bs-strahl__stufe > b { grid-area: kopf; font-size: 14px; font-weight: 600; align-self: end; }
.bs-strahl__satz {
  grid-area: satz; font-size: 12px; line-height: 1.45;
  color: var(--text-tertiary); align-self: start;
}
/* Drei Zustände, drei Formen — wortgleich zur Schrittleiste (EINHEIT 4.5). */
.bs-strahl__stufe.is-fertig .bs-strahl__marke { background: var(--accent); color: var(--on-accent); border-color: transparent; }
.bs-strahl__stufe.is-laeuft .bs-strahl__marke { background: var(--accent); color: var(--on-accent); border-color: transparent; }
.bs-strahl__stufe.is-laeuft > b { color: var(--text-primary); }
.bs-strahl__stufe.is-offen > b { color: var(--text-secondary); }

@media (max-width: 720px) {
  /* Der Zustands-Chip rutscht unter den Titel: neben «Ich habe die Rechte am
     Material» bleibt auf 390px keine lesbare Breite für beides. */
  .bs-freigabe__tun {
    grid-template-columns: 30px minmax(0, 1fr);
    grid-template-areas: "marke kopf" "marke satz" "marke stand";
    gap: 4px 12px;
  }
  .bs-freigabe__stand { justify-self: start; }
  .bs-verboten__liste { grid-template-columns: minmax(0, 1fr); gap: 6px; }
}

/* ============================================================
   Patch-Integration — Namensraum ar-; Quelle: docs/design/patch-abrechnungslauf.css
   Der Block wird bei Integration als GANZES ersetzt, nie editiert. Neu in W-B (B3).
   ============================================================ */
/* =========================================================================
   Patch «Abrechnungslauf exakt nach Referenz» — Welle W-B, Team B3.
   Referenzbild: docs/design/referenzen/Portaluikomplett/
                 «ChatGPT Image 29. Juli 2026, 13_25_57 (6).png»

   EINSETZEN: Diesen Block unveraendert ans ENDE von public/style.css HAENGEN
   (nicht ersetzen — die Datei ist neu in dieser Welle und tritt neben
   patch-partnerliste.css und patch-partnerdetail.css). Er gehoert NACH die
   Basis-Regeln, sonst wirkt kein Mobile-Override (Memory
   project_css_cascade_mobile). Danach die Service-Worker-VERSION in
   public/sw.js hochzaehlen und ueber ./scripts/jetzt-ausliefern.sh ausliefern.

   Praefix ar-, damit kein bestehender Klassenvertrag beruehrt wird. Farben,
   Radien und Abstaende kommen ausschliesslich aus den Fundament-Tokens
   (style.css:21 ff.) plus dem gemeinsamen Symbol-Quadrat .gz-ic aus
   patch-zentrale.css — hier steht kein einziger roher Hex.

   Wiederverwendet (kein Nachbau): .panel, .stat-strip/.stat/.stat__label/
   .stat__value/.stat__sub, .gz-kachel/.gz-ic/.gz-panel__titel, .field,
   .table-wrap/.team-table, .sl-badge*, .primary-btn/.ghost-btn, .empty-state.
   Neu ist nur, was es noch nirgends gibt: die Schrittleiste, die Startkarte,
   das Aktivitaetsprotokoll und die Sperrzeile der Auszahlung.
   ========================================================================= */

/* --- Kopf ---------------------------------------------------------------- */
.ar-kopf { margin-bottom: 16px; }
/* Der eigene Brotkrumen-Pfad dieser Flaeche ist am 17.08. ERSETZT worden:
   das Ortsschild zeichnet die Schale seither zentral fuer JEDE Flaeche
   (`components/ortsschild.js`, Tabelle `config/bereiche.js`, Gesetz
   docs/BEREICHE.md §3). Die Klassen `.ar-krume` standen danach noch hier und
   trugen nichts mehr — «Ersetzen statt daneben»; entfernt 18.08. */
/* Die Kopf-Hülle dieser Fläche ist am 19.08.2026 gefallen — sie trägt jetzt
   den EINEN Seitenkopf (components/seiten-kopf.js), und dessen eigene Reihe
   («Titel + Beiwerk daneben») ersetzt die Reihe, die sich hier sieben Flächen
   je selbst gebaut hatten. «Ersetzen statt daneben»: die Regel ist entfernt,
   nicht stehen gelassen. Was BLEIBT, ist die Zahl daneben — sie wird dem
   Bauteil als `neben` hereingereicht und behält ihre Klasse. */
.ar-btn-ic { display: inline-flex; align-items: center; gap: 7px; }
.ar-btn-ic svg { width: 16px; height: 16px; flex: 0 0 auto; }
/* Der Weg zurueck zeigt nach links — dasselbe Zeichen, gedreht, statt eines
   zweiten Pfeil-Icons im Set.
   Welle 8 «Muster», 18.08.2026: der Anker war `.ar-kopf__zeile`, die eigene
   Kopf-Hülle. Zwei der drei Flächen (`partner-run.js`, `team-provision.js`)
   ziehen ihren Kopf jetzt aus `components/seiten-kopf.js` und haben diese Hülle
   nicht mehr — der Pfeil hätte dort nach RECHTS gezeigt, obwohl er zurückführt.
   Der Anker ist deshalb die Marke des Kopfes selbst; sie trägt jede der drei. */
.ar-kopf .ar-btn-ic svg { transform: rotate(180deg); }

/* --- Schrittleiste (EINHEIT 4.5 + 5.3) -----------------------------------
   Nummerierte Kreise mit Namen, duenne Verbindungslinie dazwischen.
   Drei Zustaende, drei Formen — erledigt (gefuellt + Haekchen), aktiv
   (gefuellt + Nummer), offen (Umriss + Nummer). Keine Balkensegmente. */
.ar-stepper {
  display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr);
  gap: 0; list-style: none; margin: 0 0 16px; padding: 18px 20px;
}
.ar-schritt { position: relative; display: flex; align-items: center; gap: 12px; min-width: 0; }
/* Die Linie laeuft vom Kreis zum naechsten Kreis, nicht ueber die Namen. */
.ar-schritt:not(:last-child)::after {
  content: ''; position: absolute; right: 6px; top: 17px; left: calc(100% - 6px);
  width: auto; height: 1px; background: var(--border);
}
.ar-schritt__kreis {
  display: grid; place-items: center; flex: 0 0 auto;
  width: 34px; height: 34px; border-radius: 50%;
  font-size: 13px; font-weight: 650; font-variant-numeric: tabular-nums;
  border: 1px solid var(--border); background: transparent; color: var(--text-tertiary);
}
.ar-schritt__kreis svg { width: 17px; height: 17px; }
.ar-schritt.is-aktiv .ar-schritt__kreis { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
.ar-schritt.is-fertig .ar-schritt__kreis { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
.ar-schritt__text { display: grid; gap: 1px; min-width: 0; }
.ar-schritt__name {
  font-size: 13px; font-weight: 600; color: var(--text-tertiary);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ar-schritt.is-aktiv .ar-schritt__name { color: var(--accent-strong); }
.ar-schritt.is-fertig .ar-schritt__name { color: var(--text-primary); }
.ar-schritt__sub {
  font-size: 11.5px; color: var(--text-tertiary);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* --- Raster: Arbeit links, Pruefung und Protokoll rechts ------------------ */
.ar-raster { display: grid; grid-template-columns: minmax(0, 1fr) minmax(300px, 380px); gap: 16px; align-items: start; }
/* minmax(0,1fr) statt der voreingestellten auto-Spalte: sonst zieht die
   Auszahlungstabelle (.team-table hat min-width:640px und scrollt selbst) die
   ganze Spalte auf 640px und die Seite laeuft auf 390px quer. */
.ar-links, .ar-rechts { display: grid; grid-template-columns: minmax(0, 1fr); gap: 16px; min-width: 0; }

/* --- Startkarte ---------------------------------------------------------- */
.ar-start { padding: 16px 20px; }
.ar-start__kopf { margin-bottom: 12px; }
.ar-start__kopf h2 { font-size: 15px; font-weight: 600; margin: 0; }
.ar-start__zeile { display: flex; gap: 12px; align-items: stretch; flex-wrap: wrap; }
.ar-start__zeile .field { flex: 0 1 200px; }
.ar-start__knoepfe { display: flex; gap: 8px; align-items: flex-end; flex-wrap: wrap; margin-left: auto; }
.ar-laufid {
  display: flex; align-items: center; min-height: 40px; padding: 0 12px;
  background: var(--surface-inset); border: 1px solid var(--border);
  border-radius: var(--radius-button);
  font-size: 12px; color: var(--text-tertiary); font-variant-numeric: tabular-nums;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Der Idempotenz-Hinweis ist die eine Zusicherung, die diese Flaeche gibt —
   sie steht darum als eigene Karte im Akzent-Soft-Feld, nicht als Fussnote. */
.ar-sicher {
  display: flex; gap: 10px; align-items: center; flex: 1 1 280px; min-width: 0;
  padding: 10px 12px; border-radius: var(--radius-button);
  background: var(--accent-soft); border: 1px solid var(--accent-line);
}
.ar-sicher > span { display: grid; gap: 2px; min-width: 0; }
.ar-sicher b { font-size: 12.5px; color: var(--text-primary); }
.ar-sicher span span, .ar-sicher > span > :not(b) { font-size: 11.5px; color: var(--text-secondary); line-height: 1.4; }
.ar-note { margin: 12px 0 0; font-size: 12px; line-height: 1.5; color: var(--text-tertiary); }

/* --- Kachelzeile --------------------------------------------------------- */
.ar-kacheln { margin-bottom: 0; }
.ar-kacheln .stat { padding: 14px 16px; }
.ar-kacheln .stat__value { font-size: 22px; }
.ar-kacheln .gz-ic { --gz-ic-gr: 28px; margin-bottom: 8px; }

/* --- Pruefung & Validierung ---------------------------------------------- */
.ar-pruef { padding: 16px 18px; }
.ar-pruef__kopf { display: grid; gap: 10px; }
.ar-pruef__kopf h2 { font-size: 14px; font-weight: 600; margin: 0; }
.ar-pruef__chips { display: flex; gap: 6px; flex-wrap: wrap; }
.ar-chip {
  display: inline-flex; gap: 6px; align-items: baseline;
  padding: 4px 10px; border-radius: var(--radius-badge); background: var(--surface-2);
  font-size: 12.5px; font-variant-numeric: tabular-nums; color: var(--text-secondary);
}
.ar-chip.is-bad { color: var(--bad-strong); background: rgba(var(--bad-rgb), .12); }

/* --- Aktivitaetsprotokoll ------------------------------------------------ */
.ar-prot { padding: 16px 18px; }
.ar-prot h2 { font-size: 14px; font-weight: 600; margin: 0; }
.ar-prot__h {
  margin: 16px 0 0; font-size: 11px; font-weight: 600; letter-spacing: .06em;
  text-transform: uppercase; color: var(--text-tertiary);
}
.ar-prot__liste { list-style: none; margin: 10px 0 0; padding: 0; display: grid; gap: 10px; }
.ar-prot__zeile { display: flex; gap: 10px; align-items: flex-start; }
.ar-prot__punkt {
  display: grid; place-items: center; flex: 0 0 auto;
  width: 22px; height: 22px; border-radius: 50%;
  background: var(--accent-soft); color: var(--accent);
}
.ar-prot__punkt svg { width: 13px; height: 13px; }
.ar-prot__punkt.is-server { background: rgba(var(--tint-rgb), .10); color: var(--text-tertiary); }
.ar-prot__text { display: grid; gap: 1px; min-width: 0; }
.ar-prot__text b { font-size: 12.5px; font-weight: 600; color: var(--text-primary); }
.ar-prot__text span { font-size: 11.5px; color: var(--text-secondary); }
.ar-prot__text i { font-style: normal; font-size: 11px; color: var(--text-tertiary); font-variant-numeric: tabular-nums; }

/* --- Freigeben & auszahlen ----------------------------------------------- */
.ar-zahlen { padding: 16px 20px; }
.ar-zahlen__kopf { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.ar-zahlen__kopf h2 { font-size: 15px; font-weight: 600; margin: 0; }
.ar-zahlen__summe { font-size: 12.5px; color: var(--text-secondary); font-variant-numeric: tabular-nums; }
.ar-zahlen__summe b { color: var(--text-primary); font-size: 15px; margin-left: 6px; }
/* Die Sperre nennt ihren Grund — ein deaktivierter Knopf ohne Satz daneben ist
   eine tote Tuer. */
.ar-sperre {
  display: flex; gap: 8px; align-items: center; margin: 10px 0 0;
  padding: 9px 12px; border-radius: var(--radius-button);
  background: rgba(var(--bad-rgb), .10); border: 1px solid rgba(var(--bad-rgb), .28);
  font-size: 12.5px; color: var(--bad-strong);
}
.ar-sperre svg { width: 16px; height: 16px; flex: 0 0 auto; }
.ar-tab__haupt .ar-tab__id {
  display: block; font-size: 11.5px; color: var(--text-tertiary);
  font-variant-numeric: tabular-nums; letter-spacing: .02em;
}
.ar-tab__haupt strong { font-size: 13.5px; font-weight: 600; }
/* Der GRUND steht an der gesperrten Zeile, nicht nur oben in der Fehlerliste
   (Owner-Befund 20.08.2026). Bis dahin sperrte EIN Konflikt alle Zeilen; jetzt
   sperrt er seine eigene — und sagt daneben, warum. */
.ar-tab__grund {
  display: block; margin-top: 4px; font-size: 11.5px; line-height: 1.45;
  color: var(--bad-strong); font-variant-numeric: tabular-nums;
}
.ar-tab tr.is-gesperrt { background: rgba(var(--bad-rgb), .05); }

/* --- Entscheid je Monat (23.08.2026, Owner-Blatt 08_PAYROLL 08:24) --------
   Die Zeile sagt nicht mehr nur «bereit» oder «gesperrt». Sie sagt, WAS mit
   welchem Monat geschieht — und der Kasten darunter setzt es. Beides bleibt in
   der bestehenden Tabelle: eine zweite Flaeche fuer denselben Handgriff waere
   ein zweiter Ort, an dem derselbe Fehler repariert werden muesste.
   Neu ist nur, was es noch nicht gibt; Felder, Knoepfe und Marken kommen
   unveraendert aus .field, .primary-btn/.ghost-btn und .sl-badge*. */
.ar-tab__monat {
  display: block; margin-top: 3px; font-size: 11.5px; line-height: 1.45;
  color: var(--text-secondary); font-variant-numeric: tabular-nums;
}
.ar-tab__unter {
  display: block; margin-top: 2px; font-size: 11.5px; line-height: 1.4;
  color: var(--text-tertiary); font-variant-numeric: tabular-nums;
  font-weight: 400;
}
.ar-tab__knopf { margin-left: 8px; padding: 4px 10px; font-size: 12px; }
.ar-entscheid > td { padding: 0 0 12px; border-top: 0; }
.ar-entscheid__box {
  display: flex; flex-wrap: wrap; gap: 12px; align-items: flex-end;
  padding: 12px 14px; border-radius: var(--radius-button);
  background: rgba(var(--tint-rgb), .05); border: 1px solid var(--border);
}
.ar-entscheid__box .field { margin: 0; }
.ar-entscheid__satz {
  flex: 1 1 100%; margin: 0; font-size: 12px; color: var(--text-tertiary);
}

/* =========================================================================
   Schmale Geraete — eigener Block NACH den Basis-Regeln, bis 1024px/coarse,
   damit Tablets nicht in die Bruchzone fallen (Memory
   project_tablet_touch_breakpoint).
   ========================================================================= */
@media (max-width: 1200px) {
  .ar-raster { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 900px) {
  /* Vier Schritte nebeneinander sind auf dem Handy vier abgeschnittene
     Woerter. Untereinander bleibt jeder Schritt lesbar; die Verbindungslinie
     laeuft dann senkrecht vom Kreis zum naechsten. */
  .ar-stepper { grid-auto-flow: row; grid-auto-columns: auto; gap: 8px; padding: 14px 16px; }
  .ar-schritt { padding: 4px 0; }
  .ar-schritt:not(:last-child)::after {
    left: 17px; right: auto; top: 38px; bottom: -12px;
    width: 1px; height: auto;
  }
  /* Zwei Knoepfe nebeneinander lassen «Abrechnungslauf starten» abschneiden —
     das Wort ist der Zweck der Flaeche. Also je eine volle Zeile. */
  .ar-start__knoepfe { margin-left: 0; width: 100%; display: grid; grid-template-columns: minmax(0, 1fr); gap: 8px; }
  .ar-start__knoepfe button { width: 100%; justify-content: center; }
  .ar-start__zeile .field { flex: 1 1 100%; }
}
@media (max-width: 1024px), (pointer: coarse) {
  .ar-start__knoepfe button { min-height: 44px; }
  .ar-zahlen [data-payout-check] { width: 24px; height: 24px; accent-color: var(--accent); }
  /* Der Griff, der den Entscheid-Kasten oeffnet, ist ein Griff — also
     Daumenboden wie jeder andere (project_tablet_touch_breakpoint). */
  .ar-tab__knopf { min-height: 44px; }
}

/* Auf 390 px wird die Tabelle zur Karte (Haus-Regel
   `.table-wrap table:has(td[data-label])`, style.css). Der Entscheid-Kasten
   ist dann eine eigene Karte unter dem Betreiber. Zwei Dinge muss er dort
   ablegen: die Namens-Behandlung der ERSTEN Zelle (Trennlinie + 14px — er ist
   kein Name) und die Zweispaltigkeit seiner Felder. */
@media (max-width: 640px) {
  .table-wrap .ar-tab tr.ar-entscheid { padding: 8px; }
  .table-wrap .ar-tab tr.ar-entscheid > td:first-child {
    padding-bottom: 0; margin-bottom: 0; border-bottom: 0; font-size: inherit;
  }
  .ar-entscheid__box { flex-direction: column; align-items: stretch; gap: 10px; }
  /* ⚠️ `.field--wide` traegt `flex: 1 1 320px` (Grundstock, Feld-Bauteil). In
     einem Spalten-Flex ist die Basis die HOEHE — das Grund-Feld stand 320 px
     hoch und schob den Knopf aus dem Bild. Dieselbe Wurzel wie in patch-*.css
     bei den Filterzeilen; hier steht sie mit ihrem Grund. AM BILD GESEHEN
     (23.08.2026, 390 px, scripts/_auszahlung_entscheid_ui_test.mjs).
     Beide Regeln stehen EINMAL je Selektor — zwei Faelle desselben Selektors
     im selben Geraete-Block waeren eine Doppelung ohne Not
     (scripts/_stil_einmalig_test.mjs, Pruefung 23.08.2026). */
  .ar-entscheid__box .field { width: 100%; flex: 0 0 auto; }
  .ar-entscheid__box .primary-btn { width: 100%; min-height: 44px; }
  /* Wert und Nachsatz gehoeren in EINE Zelle, aber nicht in EINE Zeile: die
     Karten-Regel des Hauses stellt beide mit `space-between` nebeneinander,
     und auf 390 px wird daraus eine Spalte aus einzelnen Woertern. Der
     Nachsatz nimmt darum die ganze Breite unter dem Wert; der Griff neben der
     Marke rutscht auf seine eigene Zeile, rechts, wo der Daumen ihn sucht. */
  .table-wrap .ar-tab td[data-label="Nettoauszahlung"],
  .table-wrap .ar-tab td[data-label="Status"] { flex-wrap: wrap; }
  .ar-tab__unter { flex: 1 1 100%; text-align: right; }
  .ar-tab__knopf { flex: 0 0 auto; margin-left: auto; }
}

/* ============================================================
   Patch-Integration — Namensraum vt2-; Quelle: docs/design/patch-vertriebe.css
   Der Block wird bei Integration als GANZES ersetzt, nie editiert. Neu in W-B (B4).
   ============================================================ */
/* =========================================================================
   Vertriebe (#/p/vertriebe) + Vermittlungen (#/p/vermittlungen)
   Bild gegen Bild: docs/design/referenzen/Portaluikomplett/
   «ChatGPT Image 29. Juli 2026, 13_25_57 (5).png».

   EINSETZEN: Diesen Block unveraendert an das ENDE von public/style.css
   haengen — nach allen bestehenden Mobile-Bloecken (Projekt-Cascade-Regel,
   Memory project_css_cascade_mobile: ein eigener @media-Block gehoert NACH
   die Basisregeln, sonst wirkt er nicht). Danach die Service-Worker-VERSION
   in public/sw.js hochzaehlen und ueber ./scripts/jetzt-ausliefern.sh
   ausliefern.

   Warum Patch-Datei statt direkt in style.css: diese Etappe lief in einer
   Welle mit vier parallelen Teams. Vier Haende in derselben 6'000-Zeilen-
   Datei sind ein Konflikt mit Ansage; der Wellen-Integrator haengt die
   Bloecke in einem Zug an.

   Praefix vt2-. Das kurze vt- ist vergeben: .vt-row/.vt-agree/.vt-history/
   .vt-warns stehen seit Iter 47 in style.css und werden von
   public/src/views/vertrieb-portal.js weiterbenutzt — sie bleiben
   unangetastet.

   WIEDERVERWENDET, nicht nachgebaut: .admin-page, .panel, .stat/.stat__label/
   .stat__value/.stat__sub/.stat__bar, .sl-filters/.field, .sl-count,
   .table-wrap/.team-table/.sl-table samt Mobile-Stapelung, .sl-badge
   (--aktiv/--pipeline/--storniert), .pagination/.page-btn, .panel-row,
   .icon-btn, .primary-btn/.ghost-btn, .empty-state, .load-error.
   Neu ist nur, was es noch nirgends gibt: die Kachelzeile mit Symbol-Quadrat
   auf dieser Flaeche, das rechte Detail-Panel, die Tabellen-Sortierkoepfe
   und die Fusszeile mit Seitengroesse.

   EINHEIT.md, woertlich umgesetzt:
     1.3  EIN Akzent Tuerkis — der «blaue Wert» der Referenz wird Tuerkis
     1.5  Seitentitel 26px/650/-.02em, gemischte Schreibung, OHNE Icon
          (die Referenz setzt hier ein Icon davor — P18, entschieden dagegen)
     1.6  kein Erklaertext unter dem Seitentitel (Referenz hat zwei Zeilen)
     1.8  Avatare: Initialen im neutralen Kreis, EINE Farbe — nie eine Farbe
          je Person (die Referenz faerbt jeden Avatar anders, P27)
     4.1  Kachel: Symbol-Quadrat oben, Label klein, Zahl 26px, EINE Zusatzzeile
     4.7  Status als gerahmter Wort-Chip in gemischter Schreibung
     4.9  Tabellenkopf in gesperrten Versalien, Zahlen rechtsbuendig mit
          Tabellenziffern, Status-Chip in der vorletzten Spalte
     4.10 Fusszeile: links «Zeige 1 bis N von M», rechts Seitengroesse + Pager
     4.11 Leerzustand einzeilig und NUR wenn wirklich leer — die vollbreite
          Leerzustands-Karte unter der gefuellten Tabelle der Referenz ist
          ein Prototyp-Fehler (EINHEIT §7 Nr. 31, P41) und entfaellt
   ========================================================================= */

/* --- 0. Symbol-Quadrat und Initialen ------------------------------------ */
/* Zwei Bereichstoene, identisch zu patch-zentrale.css §0 — dieselbe Zahl,
   damit Kachel, Tuer und Detailflaeche eines Bereichs gleich aussehen
   (FINISH-STANDARD 3). Sie tragen NUR Soft-Felder hinter Zeichen, nie Text,
   nie Flaeche, nie einen Knopf: Tuerkis bleibt der EINE Akzent. */
.vt2 {
  --vt2-vertriebe: 240, 138, 186;   /* Rosa  — externe Vertriebe        */
  --vt2-partner:   112, 208, 154;   /* Gruen — Standortbetreiber        */
  --vt2-geld:      236, 190, 112;   /* Gold  — Provision, Auszahlung    */
  --vt2-zeit:      168, 190, 205;   /* Stahl — Wartendes, Fristen       */
  --vt2-feld: var(--tint-rgb);      /* Rueckfall: nie eine tote var()   */
}
.vt2 .vt2-ic--vertriebe { --vt2-feld: var(--vt2-vertriebe); }
.vt2 .vt2-ic--partner   { --vt2-feld: var(--vt2-partner); }
.vt2 .vt2-ic--geld      { --vt2-feld: var(--vt2-geld); }
.vt2 .vt2-ic--zeit      { --vt2-feld: var(--vt2-zeit); }

.vt2-ic {
  display: grid; place-items: center; flex: 0 0 auto;
  width: var(--vt2-ic-gr, 32px); height: var(--vt2-ic-gr, 32px);
  border-radius: calc(var(--vt2-ic-gr, 32px) * .3);
  background: rgba(var(--vt2-feld), .13);
  color: rgb(var(--vt2-feld));
}
.vt2-ic svg { width: calc(var(--vt2-ic-gr, 32px) * .56); height: calc(var(--vt2-ic-gr, 32px) * .56); }

/* Initialen im neutralen Kreis (EINHEIT 1.8). Die Referenz gibt jeder Firma
   eine eigene Avatarfarbe — in einem System, in dem jede Farbe einen Bereich
   meint, taeuscht das eine Bedeutung vor, die es nicht gibt. */
.vt2-avatar {
  display: grid; place-items: center; flex: 0 0 auto;
  width: 28px; height: 28px; border-radius: 50%;
  background: rgba(var(--tint-rgb), .09); border: 1px solid var(--border);
  color: var(--text-secondary); font-size: 11px; font-weight: 650; letter-spacing: .02em;
}

/* --- 1. Kopfzeile ------------------------------------------------------- */
/* Die Kopf-Hülle dieser Fläche ist am 19.08.2026 gefallen — sie trägt jetzt
   den EINEN Seitenkopf (components/seiten-kopf.js), und dessen eigene Reihe
   («Titel + Beiwerk daneben») ersetzt die Reihe, die sich hier sieben Flächen
   je selbst gebaut hatten. «Ersetzen statt daneben»: die Regel ist entfernt,
   nicht stehen gelassen. Was BLEIBT, ist die Zahl daneben — sie wird dem
   Bauteil als `neben` hereingereicht und behält ihre Klasse. */

/* --- 2. Kachelzeile ----------------------------------------------------- */
/* Spalten-Autofluss: drei oder vier Kacheln fuellen dieselbe eine Reihe. */
.vt2-kacheln {
  display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr);
  gap: 14px; margin-bottom: 18px;
}
/* Zeichen OBEN, Label darunter, dann die Zahl — nicht Zeichen NEBEN Label:
   in der 2er-Reihe am Handy blieben sonst keine 110px fuer «Ausstehende
   Provisionen», und ein abgeschnittenes Label ist genau das Billige, das hier
   verschwinden soll. */
.vt2-kachel { justify-content: flex-start; padding: 18px 20px; gap: 3px; }
.vt2-kachel .vt2-ic { margin-bottom: 10px; }
.vt2-kachel .stat__value { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.vt2-kachel .stat__label { white-space: normal; }
.vt2-kachel .stat__bar { margin-top: auto; }
/* Ein Balken, der einen Rueckstand misst, traegt die Warnfarbe. */
.vt2-kachel .stat__bar.is-warn > i { background: var(--warn); }
/* Solange die Sammelzahl laedt, steht ein ruhiges Zeichen — keine 0, die
   gleich springt (FINISH-STANDARD 7: kein Wert ohne Quelle). */
.vt2-laedt { color: var(--text-tertiary); }

/* --- 3. Arbeitsflaeche (W5-E4b: das Detail-Panel wurde das Dossier
   #/p/vertrieb/:id — die [data-panel="1"]-Verdichtung ging mit ihm) -------- */
.vt2-arbeit { display: grid; gap: 16px; align-items: start; }
.vt2-liste { min-width: 0; }

/* --- 4. Tabelle --------------------------------------------------------- */
.vt2-table tr[data-vid], .vt2-table tr[data-rid] { cursor: pointer; transition: background var(--transition); }
.vt2-table tr[data-vid]:hover td, .vt2-table tr[data-rid]:hover td { background: rgba(var(--accent-rgb), .06); }
.vt2-table tr.is-offen td { background: rgba(var(--accent-rgb), .09); }
.vt2-table tr.is-inactive td { opacity: .6; }
/* Sortierkopf: Pfeil nur an der sortierten Spalte (EINHEIT 4.9). */
.vt2-table th.vt2-sort { cursor: pointer; user-select: none; white-space: nowrap; }
.vt2-table th.vt2-sort:hover { color: var(--text-secondary); }
.vt2-table th.vt2-sort:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.vt2-table th.vt2-sort[aria-sort]::after { content: ' ↑'; color: var(--accent-strong); }
.vt2-table th.vt2-sort[aria-sort="descending"]::after { content: ' ↓'; }
.vt2-table th.num, .vt2-table td.num { text-align: right; }
.vt2-table td.num { font-variant-numeric: tabular-nums lining-nums; white-space: nowrap; }
/* Zweizeilen-Hauptspalte: Firma oben, Ansprechpartner klein darunter.
   Der Name darf NIE abgeschnitten werden — «Digital …» statt «Digital Growth
   GmbH» ist genau das Billige, das hier verschwinden soll. Alle Zahlenspalten
   sind umbruchfrei und nehmen sich ihre Breite; die Hauptspalte ist die
   einzige, die schrumpfen kann, und bekommt darum einen Boden. Reicht der
   Platz nicht, scrollt .table-wrap waagerecht (so gebaut, docs/design/grund.css). */
.vt2-table th:first-child, .vt2-table td.vt2-haupt-cell { min-width: 260px; }
.vt2-haupt { display: flex; align-items: center; gap: 10px; min-width: 0; }
.vt2-haupt__text { display: grid; gap: 1px; min-width: 0; }
.vt2-haupt__name {
  font-size: 13.5px; font-weight: 600; color: var(--text-primary);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.vt2-haupt__sub {
  font-size: 11.5px; color: var(--text-tertiary);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Der «blaue Wert» der Referenz ist bei uns Tuerkis (EINHEIT 1.3) — und er
   steht nur dort, wo wirklich etwas offen ist. */
.vt2-offen { color: var(--accent-strong); font-weight: 600; }
.vt2-tuer {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 12.5px; font-weight: 600; color: var(--accent-strong);
  background: none; border: 0; padding: 6px 2px; cursor: pointer;
}
.vt2-tuer svg { width: 14px; height: 14px; }
.vt2-tuer:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: var(--radius-card); }

/* --- 5. Fusszeile: links die Spanne, rechts Groesse + Blaettern --------- */
.vt2-fuss {
  display: flex; justify-content: space-between; align-items: center;
  gap: 12px; flex-wrap: wrap; margin-top: 6px;
}
/* nowrap: sonst faellt die Blaetterung im engen Rest neben dem Groessen-Waehler
   auf zwei Zeilen und «‹ 1» steht ueber «2 ›». */
.vt2-fuss .pagination { margin: 0; flex-wrap: nowrap; }
.vt2-spanne { color: var(--text-secondary); font-size: 12.5px; font-variant-numeric: tabular-nums; margin: 0; }
.vt2-groesse { display: flex; align-items: center; gap: 8px; color: var(--text-secondary); font-size: 12.5px; }
.vt2-groesse select { min-height: 34px; }

/* --- 6. Dossier-Bausteine (W5-E4b: die Panel-Huelle .vt2-panel/__kopf/
   __titel ging mit dem Detail-Panel; Bloecke, Paare, Zeilen, Formulare und
   __aktionen leben in vertrieb-detail.js weiter) ------------------------- */
.vt2-block { display: grid; gap: 8px; padding-top: 12px; border-top: 1px solid var(--border); }
.vt2-block:first-of-type { padding-top: 0; border-top: 0; }
.vt2-block__kopf { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
/* Panel-Titel: 13px, gemischte Schreibung — Versalien tragen genau eine
   Aufgabe (Spaltenkopf), sonst waere die Tabelle nicht mehr unterscheidbar
   (EINHEIT 1.5). */
.vt2-block__kopf h3 { margin: 0; font-size: 13px; font-weight: 650; color: var(--text-primary); }
.vt2-block__mehr {
  background: none; border: 0; padding: 0; cursor: pointer;
  font-size: 12px; font-weight: 600; color: var(--accent-strong);
}
.vt2-block__mehr:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: var(--radius-card); }
/* margin:0 — die Vorgabe des Browsers fuer <dl> ist 1em oben und unten und
   riss die vier Wertepaare des Panels auseinander. */
.vt2-paar { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; margin: 0; font-size: 12.5px; }
.vt2-paar dt { color: var(--text-secondary); margin: 0; }
.vt2-paar dd { margin: 0; color: var(--text-primary); font-variant-numeric: tabular-nums; text-align: right; }
/* Im schmalen Panel wird umgebrochen, nie abgeschnitten: eine halbe E-Mail-
   Adresse ist keine Adresse. */
.vt2-zeile {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 8px; min-width: 0; font-size: 12.5px; padding: 5px 0;
}
.vt2-zeile + .vt2-zeile { border-top: 1px solid var(--border); }
.vt2-zeile__text { display: grid; gap: 1px; min-width: 0; }
.vt2-zeile__text b { font-weight: 600; color: var(--text-primary); overflow-wrap: anywhere; }
.vt2-zeile__text span { color: var(--text-tertiary); font-size: 11.5px; overflow-wrap: anywhere; }
.vt2-zeile__wert { flex: 0 0 auto; color: var(--text-secondary); font-variant-numeric: tabular-nums; white-space: nowrap; text-align: right; }
.vt2-panel__aktionen { display: grid; gap: 8px; }
.vt2-panel__aktionen button { width: 100%; min-height: 40px; }
/* Destruktiv: Rand und Text in Rot, nie gefuellt (EINHEIT 1.4). */
.vt2-gefahr { color: var(--bad-strong); border-color: rgba(var(--bad-rgb), .42); }
.vt2-gefahr:hover { background: rgba(var(--bad-rgb), .09); border-color: var(--bad-strong); }

/* Formulare im Panel: eine Spalte, Knoepfe unten nebeneinander. */
.vt2-form { display: grid; gap: 8px; padding-top: 4px; }
.vt2-form .field { width: 100%; }
.vt2-form__satz { font-size: 12.5px; color: var(--text-secondary); line-height: 1.6; }
.vt2-form__knoepfe { display: flex; gap: 8px; }
.vt2-form__knoepfe button { flex: 1 1 0; min-height: 40px; }

/* Anlege-Formular ueber der Liste (der Knopf oben rechts klappt es auf). */
.vt2-neu { display: flex; gap: 10px; align-items: flex-end; flex-wrap: wrap; margin-bottom: 16px; }
.vt2-neu .field { flex: 1 1 280px; min-width: 0; }

/* Lauf-Quittung: dieselbe Sprache wie die Warnliste in vertrieb-portal.js. */
.vt2-quittung { margin-bottom: 16px; }
.vt2-quittung p { margin: 0 0 8px; }
.vt2-quittung ul { margin: 8px 0 0; padding-left: 18px; color: var(--warn-strong); font-size: 12.5px; line-height: 1.6; }

/* --- 7. Tablet: Kacheln umbrechen, Panel unter die Liste ---------------- */
@media (max-width: 1240px) {
  .vt2-kacheln { grid-auto-flow: row; grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
/* --- 8. Handy: Kacheln 2 je Reihe, Tabelle gestapelt -------------------- */
@media (max-width: 720px) {
  .vt2-kopf h1 { font-size: 22px; }
  .vt2-kopf__aktionen { width: 100%; }
  .vt2-kopf__aktionen button { flex: 1 1 0; min-width: 0; }
  .vt2-kacheln { gap: 10px; }
  .vt2-kachel { padding: 14px 16px; }
  .vt2-kachel .vt2-ic { --vt2-ic-gr: 28px; margin-bottom: 8px; }
  .vt2-kachel .stat__value { font-size: 22px; }
  /* Die geerbte Stapelung (.sl-table) gibt jeder Zelle eine eigene Zeile — bei
     zehn Spalten waere ein Vertrieb eine halbe Bildschirmhoehe hoch. Darum
     hier zwei Spalten: Firma und Tuer teilen die Kopfzeile, die Zahlen stehen
     paarweise darunter. Nichts wird versteckt. */
  .vt2-table tbody tr { display: grid; grid-template-columns: 1fr 1fr; align-items: center; }
  .vt2-table tbody td { padding: 6px 12px; min-width: 0; }
  .vt2-table th:first-child, .vt2-table tbody td.vt2-haupt-cell { min-width: 0; }
  .vt2-table tbody td.vt2-haupt-cell {
    grid-column: 1 / -1; display: block; text-align: left; padding-top: 8px;
  }
  .vt2-table tbody td.vt2-haupt-cell::before { display: none; }
  .vt2-table tbody td.vt2-tuer-cell { grid-column: 1 / -1; justify-content: flex-end; }
  .vt2-table tbody td.vt2-tuer-cell::before { display: none; }
  /* Zellen mit einem langen Namen bekommen die ganze Zeile — «All in One
     Barber» bricht in einer halben Spalte dreizeilig um und schiebt sich
     optisch in die Nachbarspalte. */
  .vt2-table tbody td.vt2-weit { grid-column: 1 / -1; }
  .vt2-fuss { justify-content: center; }
  .vt2-neu .field { flex: 1 1 100%; }
  .vt2-form__knoepfe { flex-wrap: wrap; }
}

/* Tapflaechen-Boden auf jedem Touch-Geraet, nicht nur unter 720px
   (Memory project_tablet_touch_breakpoint: 768/1024px sind die Bruchzone). */
@media (max-width: 1024px), (pointer: coarse) {
  .vt2-kopf__aktionen button,
  .vt2-panel__aktionen button,
  .vt2-form__knoepfe button,
  .vt2-block__mehr,
  .vt2-tuer { min-height: 44px; }
  .vt2-block__mehr { display: inline-flex; align-items: center; }
  .vt2-table tbody tr { min-height: 44px; }
  /* Die KOPFZEILE ist hier ein Griff: jede Spalte sortiert (th.vt2-sort,
     oben). Sie stand auf 41 px — der Block darunter hielt die Datenzeilen auf
     44, die Kopfzeile nie. `height` statt `min-height`, weil eine Tabellen-
     zelle `min-height` ignoriert (display: table-cell) und `height` dort als
     Mindestmass wirkt. Gemessen 28.08.2026 auf /p/vertriebe @1024: acht
     Sortier-Koepfe, jeder 41 px hoch. */
  .vt2-table thead th { height: 44px; }
  .vt2-groesse select { min-height: 44px; }
}

/* ============================================================
   Patch-Integration — Namensraum bf-; Quelle: docs/design/patch-briefing.css
   Der Block wird bei Integration als GANZES ersetzt, nie editiert. Neu in W-C (C2).
   ============================================================ */
/* ===========================================================================
   Briefing & Freigabe im Kundenportal (#/k) — Patch zu public/style.css
   Welle W-C «Der Spot-Weg», Team C2 · 2026-07-29
   Referenz: docs/design/referenzen/Kundenansichtenportal/
             «ChatGPT Image 29. Juli 2026, 13_21_26 (7).png»
   Gesetz:   docs/design/EINHEIT.md (4.3 · 4.4 · 4.5 · 1.5 · 1.6 · 2.5)

   EINBAU: diesen Block unverändert ans Ende von `public/style.css` hängen —
   nach dem `.kk-*`-Block der Kundenzentrale, damit die Mobile-Regeln NACH
   ihren Basisregeln stehen (Memory project_css_cascade_mobile).
   Es wird keine bestehende Regel geändert und keine überschrieben; alle
   Selektoren tragen den neuen Präfix `bf-`. Die einzige Ausnahme sind zwei
   Regeln auf `.bf-wahl .tap-btn` — sie ERGÄNZEN das bestehende Tap-Vokabular
   um die Auswahl-Marke, ohne es umzudefinieren.

   Was benutzt statt nachgebaut wird:
   .panel · .panel__header · .panel__title · .kp-count · .stat__bar ·
   .tap-group/.tap-btn (docs/design/grund.css, das Tap-only-Vokabular des Hauses) ·
   .primary-btn · .ghost-btn · .gz-ic · .bs-zusammen · .empty-state · .kk-zurueck.
   Neu sind nur: das 3×3-Kartenraster, der Kartenkopf mit Nummer/Häkchen,
   die Auswahl-Marke im Chip, das freiwillige Textfeld mit Zähler, der
   Fortschrittsstreifen und die Entwurfs-Vorschau.
   =========================================================================== */

/* Die EINE Zeile über der Fläche (EINHEIT 1.6): was dieser Schritt will —
   und zugleich die Zusicherung, dass nichts erzwungen wird. */
.bf-satz {
  margin: -4px 0 16px;
  font-size: 15px;
  line-height: 1.5;
  color: var(--text-secondary);
}

/* --- Fortschritt: gemessen, nicht versprochen ------------------------------
   Die Referenz setzt hier «Die meisten Kund:innen sind in unter 8 Minuten
   fertig» und «Noch ca. 2–3 Minuten» — zwei Zahlen ohne Quelle. Dieselbe
   Anatomie (Zeichen · Kopf · Zeile · Balken · Chip rechts) trägt hier die
   einzige Zahl, die es wirklich gibt: wie viele der neun Karten beantwortet
   sind. */
.bf-fortschritt {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) minmax(120px, 260px) auto;
  grid-template-areas: "ic kopf balken frist" "ic satz balken frist";
  align-items: center;
  gap: 2px 14px;
  margin-bottom: 16px;
  --gz-feld: var(--accent-rgb);
}
.bf-fortschritt .gz-ic {
  grid-area: ic;
  color: rgb(var(--gz-feld));
  background: rgba(var(--gz-feld), .13);
}
.bf-fortschritt > b {
  grid-area: kopf; align-self: end;
  font-size: 14px; font-weight: 600; color: var(--text-primary);
  font-variant-numeric: tabular-nums;
}
.bf-fortschritt__satz {
  grid-area: satz; align-self: start;
  font-size: 12.5px; line-height: 1.45; color: var(--text-secondary);
}
.bf-fortschritt .stat__bar { grid-area: balken; }
/* Die Frist steht als Wert, nicht als Status-Chip: sie sagt kein «Aktiv»,
   sondern ein Datum (EINHEIT 4.7 gilt für Zustände, nicht für Termine). Die
   Zahl kommt vom Fall, nie aus dem Text — die 5/14 Tage der Referenzen sind
   ein offenes Owner-Gate (FERTIG-KARTE §10). */
.bf-frist {
  grid-area: frist;
  font-size: 12px; font-weight: 600; color: var(--text-secondary);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}

/* --- Das 3×3-Raster der Referenz -------------------------------------------
   Ohne `stretch` (der Vorgabe des Rasters) stünden die Karten einer Zeile
   unterschiedlich hoch und rissen Löcher zwischen die Reihen — die Referenz
   zeigt drei gleich hohe Karten je Zeile, auch wenn eine davon kürzer ist. */
.bf-karten {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 16px;
}

/* --- Die Erfassungskarte ---------------------------------------------------
   Kopf: Nummer im Umriss-Kreis, daneben der Titel. Ist die Karte beantwortet,
   wird aus der Nummer das Häkchen im gefüllten Türkis-Kreis — die Erledigt-
   Marke des Hauses (EINHEIT 4.5). Zwei Zustände, zwei Formen, keine
   Doppelbelegung. */
.bf-karte { display: flex; flex-direction: column; gap: 10px; }
.bf-karte__kopf { display: flex; align-items: center; gap: 10px; }
.bf-karte__nr {
  flex: 0 0 auto;
  display: inline-flex; align-items: center; justify-content: center;
  width: 24px; height: 24px; border-radius: 50%;
  border: 1.5px solid var(--hairline-strong);
  color: var(--text-tertiary);
  font-size: 12px; font-weight: 700; font-variant-numeric: tabular-nums;
  transition: background var(--transition), border-color var(--transition), color var(--transition);
}
.bf-karte__nr svg { width: 14px; height: 14px; }
.bf-karte.is-fertig .bf-karte__nr {
  background: var(--accent); border-color: var(--accent); color: var(--on-accent);
}
.bf-karte .panel__title { margin: 0; }
.bf-karte__frage {
  margin: 0;
  font-size: 13px; line-height: 1.5; color: var(--text-secondary);
}

/* --- Die Wahl: bestehendes Tap-Vokabular plus Auswahl-Marke ----------------
   EINHEIT 4.4 verlangt, dass die Marke sagt, ob EINE oder MEHRERE Antworten
   gemeint sind — ein getönter Rahmen allein beantwortet genau diese Frage
   nicht. Einfachwahl trägt den Radio-Kreis (gefüllter Punkt), Mehrfachwahl den
   Häkchen-Kreis. Beide sitzen links im Chip, weil die Antwort hier ein Wort
   ist und keine Kachel mit freier Ecke. */
.bf-wahl .tap-btn {
  display: inline-flex; align-items: center; gap: 10px;
  text-align: left;
}
.bf-marke {
  flex: 0 0 auto;
  display: inline-flex; align-items: center; justify-content: center;
  width: 17px; height: 17px; border-radius: 50%;
  border: 1.5px solid var(--hairline-strong);
  transition: border-color var(--transition), background var(--transition);
}
.bf-marke svg { width: 11px; height: 11px; opacity: 0; color: var(--on-accent); }
/* Einfachwahl: derselbe Verlauf-Punkt wie an der Gebietskarte der
   Buchungsstrecke (.bs-gebiet__marke) — der Ring bleibt in der Kachelfarbe. */
.bf-wahl[data-art="einfach"] .tap-btn.is-active .bf-marke {
  border-color: var(--accent);
  background: radial-gradient(circle at center, var(--accent) 0 4px, transparent 4px);
}
/* Mehrfachwahl: Häkchen im gefüllten Türkis-Kreis. */
.bf-wahl[data-art="mehrfach"] .tap-btn.is-active .bf-marke {
  border-color: var(--accent); background: var(--accent);
}
.bf-wahl[data-art="mehrfach"] .tap-btn.is-active .bf-marke svg { opacity: 1; }

/* --- Das freiwillige Textfeld ---------------------------------------------
   Es steht IMMER unter einer Wahl, nie allein: dadurch ist auf jeder Karte
   ohne Lesen erkennbar, dass Tippen die Zugabe ist und nicht der Weg.
   Der Zeichenzähler der Referenz (0/200 bzw. 0/60) bleibt — er zählt hier
   eine freiwillige Länge, keine Pflicht. */
.bf-text { display: flex; flex-direction: column; gap: 6px; margin-top: 2px; }
.bf-text > span {
  color: var(--text-tertiary); font-size: 11px;
  text-transform: uppercase; letter-spacing: .07em; font-weight: 600;
}
.bf-text textarea {
  width: 100%; min-height: 62px; resize: vertical;
  padding: 10px 12px;
  background: var(--surface-inset);
  border: 1px solid var(--border); border-radius: var(--radius-button);
  color: var(--text-primary); font: inherit; font-size: 13px; line-height: 1.45;
}
.bf-text textarea::placeholder { color: var(--text-tertiary); }
.bf-text textarea:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.bf-zaehler {
  align-self: flex-end;
  font-size: 11px; color: var(--text-tertiary); font-variant-numeric: tabular-nums;
}

/* --- Fuss: Zurück links, Abschluss rechts und breit ------------------------
   Die Referenz stellt hier drei Knöpfe (Zurück · Weiter · Als Entwurf
   speichern). «Als Entwurf speichern» hat heute keinen Serverweg
   (FERTIG-KARTE §9, W-E/E2) — ein Knopf ohne Weg ist eine tote Tür und fehlt
   deshalb, statt zu enttäuschen. */
.bf-fuss {
  display: flex; align-items: center; gap: 12px;
  margin-top: 18px;
}
.bf-senden { flex: 1 1 auto; justify-content: center; }
.bf-hinweis {
  margin: 8px 0 0;
  font-size: 12.5px; color: var(--text-tertiary);
}

/* --- Freigabe: der gelieferte Entwurf --------------------------------------
   Die Vorschau bekommt eine feste Bühne mit dem Seitenverhältnis des Spots
   (16:9, EINHEIT 5.13). Damit springt die Fläche nicht, während das Video
   lädt — und ein Hochkant-Entwurf fällt sofort auf, statt die Seite zu
   verziehen. */
.bf-freigabe {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(280px, 380px);
  gap: 16px;
  align-items: start;
}
.bf-vorschau {
  display: grid; place-items: center;
  aspect-ratio: 16 / 9;
  margin: 12px 0 14px;
  padding: 16px;
  background: var(--surface-inset);
  border: 1px solid var(--border); border-radius: var(--radius-card);
  overflow: hidden;
}
.bf-vorschau__medium { max-width: 100%; max-height: 100%; border-radius: var(--radius-card); }
.bf-eckwerte { margin: 0; }
/* Der Verlauf des Falls — echte Ereignisse, dieselbe Zeilenbauart wie in der
   Zentrale (.panel-row). Kein erfundener Zeitstrahl: was nicht passiert ist,
   steht nicht da. */
.bf-verlauf__zeile { align-items: center; gap: 8px 14px; }
.bf-verlauf__zeile .kk-rest { margin-left: auto; }
/* Im Entscheid-Panel folgt auf die Chip-Reihe direkt das freiwillige Feld —
   ohne diesen Abstand klebte sein Label an der letzten Antwort. */
.bf-entscheid .bf-wahl { margin: 12px 0 16px; }
.bf-entscheid .bf-karte__frage { margin-top: 4px; }

/* --- Touch + Handy ---------------------------------------------------------
   Eigener Block NACH den Basisregeln (Memory project_css_cascade_mobile); der
   Touch-Boden greift auch auf Tablets (Memory project_tablet_touch_breakpoint)
   — 720px allein deckt die Bruchzone 768/1024 nicht ab. */
@media (max-width: 1024px), (pointer: coarse) {
  .bf-fuss .primary-btn, .bf-fuss .ghost-btn { min-height: 44px; }
  .bf-text textarea { min-height: 66px; }
}

/* Zwischenbreite: aus 3×3 wird 2×5, bevor eine Karte unter die Lesbarkeit
   ihrer Chips fällt. */
@media (max-width: 1080px) {
  .bf-karten { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  /* Dieselbe Schwelle wie in der Zentrale (.kk-raster): darunter fiele die
     schmale Spalte unter 280px und der Entscheid verlöre seine Knopfbreite. */
  .bf-freigabe { grid-template-columns: minmax(0, 1fr); }
}

@media (max-width: 720px) {
  /* Auf 390px steht eine Karte je Zeile — das ist zugleich die Führung, die
     die Referenz auf dem Handy als Checkliste zeichnet: eine Frage im Bild,
     der Fortschritt darüber. */
  .bf-karten { grid-template-columns: minmax(0, 1fr); }
  /* Der Fortschritt bricht auf zwei Zeilen: Zeichen und Text oben, Balken
     darunter über die volle Breite. Nebeneinander bliebe für keines von
     beiden eine lesbare Breite. */
  .bf-fortschritt {
    grid-template-columns: auto minmax(0, 1fr) auto;
    grid-template-areas: "ic kopf frist" "ic satz satz" "balken balken balken";
    gap: 4px 12px;
  }
  .bf-fortschritt .stat__bar { margin-top: 8px; }
  /* Die Chips füllen die Zeile zu zweit — dieselbe Regel, die style.css:1681
     für jede andere Tap-Gruppe setzt; hier nur ohne Zentrierung, weil links
     die Auswahl-Marke steht und Wörter unterschiedlich lang sind. */
  .bf-wahl .tap-btn { flex: 1 1 100%; justify-content: flex-start; }
  .bf-fuss { flex-wrap: wrap; }
  .bf-fuss .ghost-btn, .bf-fuss .primary-btn { flex: 1 1 100%; }
  /* Der Abschluss steht auf dem Handy zuoberst im Fuss: er ist der Weg,
     «Zurück» ist der Ausweg. */
  .bf-fuss .primary-btn { order: 0; }
  .bf-fuss .ghost-btn { order: 1; }
  .bf-satz { font-size: 14px; margin-bottom: 14px; }
}

/* ============================================================
   Patch-Integration — Namensraum ew-; Quelle: docs/design/patch-entwuerfe.css
   Der Block wird bei Integration als GANZES ersetzt, nie editiert. Neu in W-C (C3).
   ============================================================ */
/* Material versions share one reading/action order in every booking view. */
.material-file {
  display:grid;
  grid-template-columns:minmax(0,1fr) auto;
  align-items:start;
  gap:10px 16px;
  padding:14px;
}
.material-file__open { order:0; min-height:44px; width:100%; }
.material-file__open strong { white-space:normal; overflow-wrap:anywhere; font-weight:600; }
.material-file__open span { overflow-wrap:anywhere; }
.material-file__states { display:flex; flex-wrap:wrap; gap:6px; align-items:start; justify-content:flex-end; }
.material-file__stand { font-variant-numeric:tabular-nums; white-space:nowrap; }
.material-file__actions { grid-column:1 / -1; display:flex; flex-wrap:wrap; gap:8px; }
.material-file__actions > button { min-height:44px; min-width:44px; padding:8px 12px; order:0; }
.material-file__actions .material-file__del { margin-left:auto; }
.material-file:has(.material-file__stand.sl-badge--aktiv) { border-color:rgba(var(--good-rgb),.38); }
.material-file:has(.material-file__stand.sl-badge--ruhend) .material-file__open strong { color:var(--text-secondary); }
@media (max-width:640px) {
  .material-file { grid-template-columns:minmax(0,1fr); padding:12px; }
  .material-file__states { justify-content:flex-start; }
  .material-file__actions .material-file__del { margin-left:0; }
}

/* ============================================================
   Patch-Integration — Namensraum pv-; Quelle: docs/design/patch-pnl.css
   Der Block wird bei Integration als GANZES ersetzt, nie editiert. Neu in W-D.
   ============================================================ */
/* =========================================================================
   P&L-Verlauf (#/v/pnl) — Erscheinung zur Owner-Referenz `13_25_56 (3)`
   («Umsatz-/Verguetungsverlauf als Flaechendiagramm») und zur Fertig-Karte
   §11 «Umsatz-Verlaufskurve ueber 6/12 Monate intern».

   EINSETZEN: Diesen Block unveraendert an das ENDE von public/style.css
   haengen — nach dem bestehenden Mobile-Block der Verkaufs-Views
   (Projekt-Cascade-Regel, Memory project_css_cascade_mobile: ein eigener
   @media-Block gehoert NACH die Basis-Regeln, sonst wirkt er nicht).
   Danach die Service-Worker-VERSION in public/sw.js hochzaehlen und ueber
   ./scripts/jetzt-ausliefern.sh ausliefern.

   Warum als Patch-Datei und nicht direkt in style.css: diese Etappe lief in
   einer Welle mit vier parallelen Teams. Vier Haende in derselben
   8'800-Zeilen-Datei sind ein Konflikt mit Ansage; der Wellen-Integrator
   haengt die Bloecke in einem Zug an.

   Bausteine, die WIEDERVERWENDET werden (kein Nachbau): .panel,
   .panel__header/.panel__hint, .view-toggle/.view-toggle__btn, .empty-state,
   .so-hint, .ghost-btn, .pnl-pos/.pnl-neg/.pnl-warn. Neu ist nur das
   Koordinatensystem selbst — es gibt in diesem Blatt keines
   (`grep -n "chart-wrap" public/src` → 0 Treffer: die alte .chart-wrap-Regel
   hat seit Iter 27 keinen Nutzer mehr und wird hier bewusst NICHT
   wiederbelebt, sondern durch das kleinere .pnl-kurve ersetzt; entfernt wird
   sie nicht — das waere eine fremde Zeile in einer fremden Welle).

   EIN Akzent (EINHEIT 1.3): Einnahmen tragen Tuerkis, Kosten den gedaempften
   Textton, der Rohertrag den sekundaeren. Keine zweite Farbfamilie, kein
   Rot ausser an der Zahl, die negativ IST (.pnl-neg, bestehende Klasse).
   ========================================================================= */

/* Kopfzeile des Panels: Titel links, 6/12-Umschalter rechts. Der Umschalter
   ist derselbe .view-toggle wie die Jahresnavigation darueber — eine Bauart
   je Art der Wahl (EINHEIT 4.4). */
.pnl-verlauf .panel__header { align-items: center; }

/* Achse links, Feld rechts. Die Achse ist schmal und fest: eine mitwachsende
   Spalte laesst die Kurve bei jedem Zahlenwechsel springen. */
.pnl-kurve { display: grid; grid-template-columns: 62px 1fr; gap: 10px; }
.pnl-kurve__achse {
  display: flex; flex-direction: column; justify-content: space-between;
  text-align: right; padding-bottom: 20px;
  font-size: 11px; font-variant-numeric: tabular-nums; color: var(--text-tertiary);
}

/* Das Feld traegt die Kurve und darunter den Streifen fuer die Monate; die
   Monatsspalten liegen absolut darueber, damit jede exakt unter ihrem Punkt
   steht (die Lage kommt als Prozentwert aus sales-pnl.js). */
.pnl-kurve__feld { position: relative; padding-bottom: 20px; }
.pnl-kurve__svg { display: block; width: 100%; height: 170px; overflow: visible; }

.pnl-kurve__flaeche { fill: rgba(var(--accent-rgb), .13); stroke: none; }
.pnl-kurve__null {
  stroke: var(--border); stroke-width: 1; vector-effect: non-scaling-stroke;
}
.pnl-kurve__linie {
  fill: none; stroke-width: 2; stroke-linejoin: round; stroke-linecap: round;
  vector-effect: non-scaling-stroke;
}
.pnl-kurve__linie--soll   { stroke: var(--accent); }
.pnl-kurve__linie--kosten { stroke: var(--text-tertiary); stroke-width: 1.5; stroke-dasharray: 4 3; }
.pnl-kurve__linie--marge  { stroke: var(--text-secondary); stroke-width: 1.5; }

.pnl-kurve__raster { position: absolute; inset: 0; }
.pnl-kurve__monat {
  position: absolute; top: 0; bottom: 0; transform: translateX(-50%);
  display: flex; align-items: flex-end; justify-content: center;
  border-radius: var(--radius-card); transition: background var(--transition);
}
.pnl-kurve__monat:hover { background: rgba(var(--accent-rgb), .07); }
.pnl-kurve__monat i {
  font-style: normal; font-size: 11px; color: var(--text-tertiary);
  white-space: nowrap;
}

/* Legende: das Wort, die Summe des Fensters, davor der Strich in der Farbe
   der Reihe. Kein Punkt — ein Strich zeigt, dass es eine Linie ist, und
   unterscheidet die gestrichelte Kostenreihe sofort. */
.pnl-kurve__legende {
  display: flex; flex-wrap: wrap; gap: 6px 18px; margin-top: 12px;
  font-size: 12px; color: var(--text-secondary);
}
.pnl-leg { display: inline-flex; align-items: center; gap: 7px; }
.pnl-leg b { color: var(--text-primary); font-variant-numeric: tabular-nums; font-weight: 600; }
.pnl-leg::before {
  content: ''; width: 16px; height: 0; flex: 0 0 auto;
  border-top: 2px solid var(--text-secondary);
}
.pnl-leg--soll::before   { border-top-color: var(--accent); }
.pnl-leg--kosten::before { border-top-style: dashed; border-top-color: var(--text-tertiary); }

/* Handy: die Achse wird schmaler, die Kurve flacher, und bei zwoelf Monaten
   traegt der Streifen nur noch jeden zweiten Monatsnamen — zwoelf Woerter
   auf 320 px Feldbreite sind ein Balken aus Buchstaben, kein Label.
   Eigener @media-Block NACH den Basis-Regeln (project_css_cascade_mobile).
   SPALTE 56 px STATT 46 (21.08.2026, Schrift-Boden-Gang): die Achsenschrift
   stand mit 10px unter dem Boden aus DESIGN.md §2 und ist auf 11px gehoben.
   46 px waren schon vorher zu eng — die breiteste Beschriftung, die
   `kurzChf()` erzeugen kann, ist «−999’999» und mass im Browser 48.0px bei
   10px und misst 52.3px bei 11px. Sie waere also umgebrochen und haette die
   Achse zweizeilig gemacht. Gemessen, nicht geschaetzt (Range-Messung auf
   390px, Inter tabular). 56 px lassen 3.7 px Luft; das Feld verliert 10 px,
   die Monatsnamen bleiben mit 18.6px in ihren 23 px Fach. */
@media (max-width: 720px) {
  .pnl-kurve { grid-template-columns: 56px 1fr; gap: 6px; }
  .pnl-kurve__svg { height: 132px; }
  .pnl-kurve__achse { font-size: 11px; }
  .pnl-kurve__monat i { font-size: 11px; }
  .pnl-kurve__raster[data-n="12"] .pnl-kurve__monat:nth-child(even) i { display: none; }
  .pnl-kurve__legende { gap: 4px 12px; }
}

/* ============================================================
   Patch-Integration — Namensraum mk-; Quelle: docs/design/patch-mediathek.css
   Der Block wird bei Integration als GANZES ersetzt, nie editiert. Neu in W-D.
   ============================================================ */
/* ============================================================
   W-D/D4 · Medien (#/v/mediathek) — Kachelgalerie + Varianten-Vergleich
   Namensraum: mk-
   Referenz: docs/design/referenzen/Kundenansichtenportal/
             «… 13_20_23 (8).png» — Kachelzeile mit Vorschaubild, Filterzeile
             darüber, Vergleichsblock «Schnell vergleichen» mit rundem
             VS-Zeichen zwischen zwei Ständen.
   Gesetz:   docs/design/EINHEIT.md — 1.3 EIN Akzent (Türkis), 1.5 Titel 26 px
             ohne Icon, 1.6 kein Erklärtext unter dem Titel, 4.1 Kachelbauart,
             4.7 Status als Wort-Chip, 4.11 Leerzustand einzeilig, 6.1 das Wort
             ist «Medien».
   Genutzt aus dem Bestand (NICHT neu definiert): .panel, .stat/.stat__label/
             .stat__value/.stat__sub, .gz-kachel/.gz-ic/.gz-panel__titel,
             .field/.field--wide, .sl-badge*, .ghost-btn, .empty-state,
             .load-error.
   Integration: als Block ans Ende von public/style.css hängen.
   ============================================================ */

/* ---- Kopf ------------------------------------------------- */
.mk-kopf { margin-bottom: 16px; }
/* Der eigene Brotkrumen-Pfad dieser Flaeche ist am 17.08. ERSETZT worden:
   das Ortsschild zeichnet die Schale seither zentral fuer JEDE Flaeche
   (`components/ortsschild.js`, Tabelle `config/bereiche.js`, Gesetz
   docs/BEREICHE.md §3). Die Klassen `.mk-krume` standen danach noch hier und
   trugen nichts mehr — «Ersetzen statt daneben»; entfernt 18.08. */
/* Die Kopf-Hülle dieser Fläche ist am 19.08.2026 gefallen — sie trägt jetzt
   den EINEN Seitenkopf (components/seiten-kopf.js), und dessen eigene Reihe
   («Titel + Beiwerk daneben») ersetzt die Reihe, die sich hier sieben Flächen
   je selbst gebaut hatten. «Ersetzen statt daneben»: die Regel ist entfernt,
   nicht stehen gelassen. Was BLEIBT, ist die Zahl daneben — sie wird dem
   Bauteil als `neben` hereingereicht und behält ihre Klasse. */
.mk-kopf__zahl {
  font-size: 12.5px; color: var(--text-tertiary);
  font-variant-numeric: tabular-nums;
}

/* ---- Kachelzeile ------------------------------------------ */
.mk-kacheln { margin-bottom: 16px; }
.mk-kacheln .stat { padding: 14px 16px; }
.mk-kacheln .stat__value { font-size: 22px; }
.mk-kacheln .gz-ic { --gz-ic-gr: 28px; margin-bottom: 8px; }

/* ---- Filterzeile ------------------------------------------ */
.mk-filter {
  display: flex; gap: 12px; align-items: flex-end; flex-wrap: wrap;
  padding: 14px 16px; margin-bottom: 16px;
}
.mk-filter .field { flex: 0 1 200px; margin: 0; }
.mk-filter__suche { flex: 1 1 280px; }
.mk-filter__hinweis {
  margin: 0 0 4px auto; font-size: 12px; color: var(--text-tertiary);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
/* W-G/G3: die gespeicherten Ansichten stehen auf einer eigenen Zeile unter den
   Filtern. Neben vier Feldern gedraengt waeren Chip und Knoepfe beide unlesbar
   schmal; die Bauart des Chips selbst ist die der Partner-Liste (EINHEIT). */
.mk-filter__ansichten { flex: 1 1 100%; }

/* ---- Galerie ---------------------------------------------- */
.mk-galerie {
  display: grid; gap: 14px;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
}
.mk-kachel {
  display: grid; gap: 4px; align-content: start;
  background: var(--surface-2); border: 1px solid var(--hairline);
  border-radius: var(--radius-card); padding: 12px; min-width: 0;
}
.mk-kachel.is-gewaehlt {
  border-color: var(--accent);
  box-shadow: 0 0 0 1px var(--accent) inset;
}
.mk-kachel__kopf {
  display: flex; align-items: center; justify-content: space-between;
  gap: 8px; margin-top: 8px; min-width: 0;
}
.mk-kachel__kopf b {
  font-size: 13px; font-weight: 600; color: var(--text-primary);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0;
}
.mk-kachel__kunde { margin: 0; font-size: 12.5px; color: var(--text-secondary); }
.mk-kachel__sub,
.mk-kachel__meta {
  margin: 0; font-size: 11.5px; color: var(--text-tertiary);
  font-variant-numeric: tabular-nums;
}
/* W6.1 «Beschriftungs-Pass»: die Handlungszeile der Kachel. Bis W6.1 stand hier
   nur das Vergleichs-Kästchen — die QR-Zähladresse war ein NEBENEFFEKT davon,
   genau EIN Kästchen anzukreuzen (Bericht C, Klasse D3). Jetzt stehen beide
   Wege nebeneinander und dürfen umbrechen, wenn die Kachel schmal wird. */
.mk-kachel__handeln {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
}
.mk-kachel__waehlen {
  display: flex; align-items: center; gap: 8px; margin-top: 8px;
  font-size: 12px; color: var(--text-secondary); cursor: pointer;
  min-height: 44px;
}
.mk-kachel__waehlen input { width: 18px; height: 18px; accent-color: var(--accent); }

/* ---- Vorschau --------------------------------------------- */
.mk-vorschau {
  display: block; position: relative; width: 100%; aspect-ratio: 16 / 9;
  border-radius: var(--radius-card); overflow: hidden; background: var(--surface-3);
}
.mk-vorschau img,
.mk-vorschau video { width: 100%; height: 100%; object-fit: cover; display: block; }
.mk-vorschau--leer {
  display: grid; place-content: center; gap: 4px; text-align: center;
  border: 1px dashed var(--hairline);
}
.mk-vorschau__typ {
  font-size: 15px; font-weight: 650; letter-spacing: .04em; color: var(--text-secondary);
}
.mk-vorschau__satz { font-size: 11.5px; color: var(--text-tertiary); }
/* Gross heisst gross genug zum Beurteilen, nicht bildschirmfüllend: zwei
   Vorschauen müssen auf 1400 px nebeneinander lesbar bleiben. */
.mk-vorschau.is-gross { aspect-ratio: 16 / 9; max-width: 460px; }

/* ---- Vergleich -------------------------------------------- */
.mk-vergleich { padding: 16px 18px; margin-bottom: 16px; }
.mk-vergleich__kopf {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; flex-wrap: wrap; margin-bottom: 14px;
}
.mk-vergleich__kopf h2 { font-size: 14px; font-weight: 600; margin: 0; }
.mk-vergleich__zahl {
  font-size: 12px; color: var(--text-secondary);
  background: rgba(var(--tint-rgb), .10); border-radius: var(--radius-badge); padding: 3px 10px;
  font-variant-numeric: tabular-nums;
}
.mk-vs {
  display: grid; grid-template-columns: 1fr auto 1fr; gap: 14px;
  align-items: center;
}
.mk-vs__seite { display: grid; gap: 5px; justify-items: start; min-width: 0; }
.mk-vs__seite b { font-size: 13px; font-weight: 600; color: var(--text-primary); }
.mk-vs__seite span { font-size: 11.5px; color: var(--text-tertiary); }
.mk-vs__zeichen {
  display: grid; place-content: center; width: 40px; height: 40px;
  border-radius: 999px; background: rgba(var(--accent-rgb), .14);
  color: var(--accent-strong); font-size: 12px; font-weight: 650;
  letter-spacing: .06em;
}

/* Diff-Liste: Label links, beide Werte rechts. Abweichende Zeilen tragen den
   Akzent — das ist die einzige Stelle, an der der Vergleich etwas behauptet. */
.mk-diff { margin: 16px 0 0; padding: 0; display: grid; gap: 0; }
.mk-diff__zeile {
  display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr) minmax(0, 1fr);
  gap: 12px; align-items: baseline;
  padding: 7px 8px; border-top: 1px solid var(--hairline);
  border-radius: var(--radius-card);
}
.mk-diff__zeile.is-anders { background: rgba(var(--accent-rgb), .07); }
.mk-diff dt {
  font-size: 12.5px; color: var(--text-secondary); margin: 0;
  display: grid; gap: 1px;
}
.mk-diff dt i {
  font-style: normal; font-size: 11px; color: var(--text-tertiary);
}
.mk-diff dd {
  margin: 0; font-size: 12.5px; color: var(--text-primary);
  font-variant-numeric: tabular-nums;
}
.mk-diff__zeile.is-anders dd { color: var(--accent-strong); font-weight: 600; }
.mk-vergleich__satz {
  margin: 14px 0 12px; font-size: 12px; line-height: 1.5; color: var(--text-tertiary);
}

/* ---- Handy ------------------------------------------------ */
@media (max-width: 720px) {
  /* Auf 390 px stehen zwei Kacheln nebeneinander; «Läuft auf den
     Bildschirmen» passt dann nicht in eine Zeile. Umbrechen statt kürzen —
     ein abgeschnittenes Label ist keine Beschriftung (dasselbe Muster wie
     .kk-stat, docs/design/patch-kundenzentrale.css). */
  .mk-kacheln .stat__label { white-space: normal; overflow: visible; }
  .mk-filter { padding: 12px; }
  .mk-filter .field, .mk-filter__suche { flex: 1 1 100%; }
  .mk-filter__hinweis { margin: 0; }
  .mk-galerie { grid-template-columns: 1fr; }
  .mk-vs { grid-template-columns: 1fr; justify-items: center; }
  .mk-vs__seite { justify-items: center; text-align: center; width: 100%; }
  .mk-diff__zeile { grid-template-columns: 1fr; gap: 2px; }
  .mk-diff dd::before {
    content: attr(data-seite); font-size: 11px; color: var(--text-tertiary);
    margin-right: 6px;
  }
}

/* Stand-Karte (Gegenpass-W-D W2/W3): Zaehladresse + Scans eines gewaehlten
   Stands. Die Adresse ist bewusst als <code> gesetzt — sie wird kopiert,
   nicht gelesen. */
.mk-stand__zeile { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; padding: 8px 0; }
.mk-stand__label { font-size: 12.5px; color: var(--text-secondary); min-width: 130px; }
.mk-stand__code { font-size: 12px; padding: 4px 8px; background: rgba(148,180,180,.08); border-radius: var(--radius-card); overflow-wrap: anywhere; max-width: 100%; }
.mk-stand__satz { font-size: 12.5px; color: var(--text-secondary); margin: 4px 0 10px; }
@media (max-width: 720px) {
  .mk-stand__zeile { align-items: flex-start; flex-direction: column; gap: 6px; }
  .mk-stand__zeile .ghost-btn { min-height: 44px; }
}
/* ============================================================
   Patch-Integration — Namensraum kb-; Quelle: docs/design/patch-kundenberichte.css
   Der Block wird bei Integration als GANZES ersetzt, nie editiert. Neu in W-D.
   ============================================================ */
/* ============================================================
   W-D/D4 · Berichte im Kundenportal (#/k/berichte)
   Namensraum: kb-
   Referenz: docs/design/referenzen/Kundenansichtenportal/
             «… 13_21_10 (10).png» (Sidebar-Punkt «Berichte», Kampagnenzeilen
             mit zwei Leistungswerten + Aktionsknopf) und
             «… 13_21_30 (12).png» (Panel «Letzte Reports» mit «Anzeigen»).
   Gesetz:   docs/design/EINHEIT.md — 1.3 EIN Akzent, 1.6 kein Erklärtext unter
             dem Titel, 4.1 Kachelbauart, 4.3 jede Karte trägt ein visuelles
             Element, 4.7 Status als Wort-Chip, 4.11 Leerzustand einzeilig,
             6.1 das Wort ist «Berichte».
   Die EINE Sache, die dieser Block leistet: gespielt (gezählt), gesehen
   (modelliert) und Scans (gemessen) sind drei verschiedene Herkünfte und
   tragen drei verschiedene Marken. Sie dürfen sich optisch nie angleichen —
   sonst liest ein Kunde einen Modellwert als Messung.
   Genutzt aus dem Bestand (NICHT neu definiert): .panel, .panel__header,
             .panel__title, .panel-row*, .stat*, .stat-strip, .kk-stat/.kk-stat__sub,
             .gz-ic, .kp-count, .sl-badge*, .primary-btn/.ghost-btn,
             .table-wrap/.team-table, .empty-state, .load-error.
   Integration: als Block ans Ende von public/style.css hängen.
   ============================================================ */

.kb-kacheln { margin-bottom: 18px; }

/* ---- Kampagnenliste --------------------------------------- */
.kb-liste { margin-bottom: 16px; }
.kb-zeile {
  display: grid; grid-template-columns: minmax(0, 1fr) auto auto;
  gap: 12px; align-items: center;
}
.kb-zeile.is-offen { background: rgba(var(--accent-rgb), .06); }
.kb-tun { min-height: 44px; white-space: nowrap; }

/* ---- Der Bericht ------------------------------------------ */
.kb-bericht { padding: 16px 18px; }
.kb-satz {
  margin: 0 0 14px; font-size: 12.5px; color: var(--text-secondary);
  font-variant-numeric: tabular-nums;
}

/* Zwei Karten nebeneinander: links gezählt, rechts modelliert. Nie
   untereinander auf dem Desktop — die Gegenüberstellung IST die Aussage. */
.kb-zwei {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 14px; margin-bottom: 16px;
}
.kb-karte {
  display: grid; gap: 8px; align-content: start;
  background: var(--surface-2); border: 1px solid var(--hairline);
  border-radius: var(--radius-card); padding: 14px 16px; min-width: 0;
}
.kb-karte h3 { margin: 0; font-size: 13px; font-weight: 600; color: var(--text-primary); }
.kb-karte__wert {
  margin: 0; font-size: 26px; font-weight: 650; letter-spacing: -.02em;
  color: var(--text-primary); font-variant-numeric: tabular-nums;
  display: grid; gap: 2px;
}
.kb-karte__wert span {
  font-size: 12px; font-weight: 400; letter-spacing: 0; color: var(--text-tertiary);
}
.kb-karte__liste { margin: 4px 0 0; display: grid; gap: 0; }
.kb-karte__liste > div {
  display: flex; justify-content: space-between; gap: 10px;
  padding: 4px 0; border-top: 1px solid var(--hairline);
}
.kb-karte__liste dt { font-size: 12px; color: var(--text-secondary); margin: 0; }
.kb-karte__liste dd {
  margin: 0; font-size: 12px; color: var(--text-primary);
  font-variant-numeric: tabular-nums;
}

/* Die Herkunfts-Marke. Drei Herkünfte, drei Töne — der Akzent bleibt der
   gezählten Wahrheit vorbehalten, das Modell trägt neutral, die Messung
   Bernstein. Kein zweiter Markenakzent (EINHEIT 1.3). */
.kb-marke {
  justify-self: start; font-size: 11px; font-weight: 650;
  letter-spacing: .07em; text-transform: uppercase;
  border-radius: var(--radius-badge); padding: 3px 9px;
}
.kb-marke.is-gezaehlt { background: rgba(var(--accent-rgb), .14); color: var(--accent-strong); }
.kb-marke.is-modell { background: rgba(var(--tint-rgb), .12); color: var(--text-secondary); }
.kb-marke.is-gemessen { background: rgba(var(--warn-rgb), .13); color: var(--warn-strong); }

.kb-fuss {
  margin: 2px 0 0; font-size: 11.5px; line-height: 1.5; color: var(--text-tertiary);
}
/* ENTFERNT, nicht ersetzt: .kb-leer — GEFALLEN 21.08.2026 — die Leer-Zeile des Hauses ist EINE Form:
   `.empty-state.empty-state--zeile` + `.empty-state__weg` in docs/design/grund.css. */

/* ---- QR-Scans --------------------------------------------- */
.kb-scans {
  border-top: 1px solid var(--hairline); padding-top: 14px; margin-bottom: 16px;
}
.kb-scans__kopf { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; }
.kb-scans__kopf h3 { margin: 0; font-size: 13px; font-weight: 600; color: var(--text-primary); }
.kb-scans__zahlen { display: flex; gap: 28px; flex-wrap: wrap; }
.kb-scans__zahlen span {
  display: grid; gap: 1px; font-size: 12px; color: var(--text-tertiary);
}
.kb-scans__zahlen b {
  font-size: 22px; font-weight: 650; color: var(--text-primary);
  font-variant-numeric: tabular-nums;
}
.kb-scans__orte {
  list-style: none; margin: 10px 0 0; padding: 0; display: grid; gap: 3px;
  font-size: 12px; color: var(--text-secondary); font-variant-numeric: tabular-nums;
}

/* ---- Standort-Tabelle -------------------------------------- */
.kb-orte { margin-top: 4px; }
.kb-ort__sub {
  display: block; font-size: 11.5px; color: var(--text-tertiary);
}

/* ---- Handy ------------------------------------------------ */
@media (max-width: 720px) {
  .kb-zeile { grid-template-columns: 1fr; align-items: start; }
  .kb-zeile .sl-badge { justify-self: start; }
  .kb-tun { width: 100%; }
  .kb-zwei { grid-template-columns: 1fr; }
  .kb-scans__zahlen { gap: 20px; }
}
/* ============================================================
   Patch-Integration — Namensraum kr-; Quelle: docs/design/patch-rechnungen.css
   Der Block wird bei Integration als GANZES ersetzt, nie editiert. Neu in W-E.
   ============================================================ */
/* ===========================================================================
   W-E/E4 · Rechnungen (#/k/rechnungen) · Standortpunkte auf der Karte ·
            Kopie einer Buchung
   Namensräume: kr- (neu, Rechnungsfläche) · Ergänzungen an kk- (Zentrale:
                Karten-Panel, Kopie-Kopf) · bs-punkt* (Bauteil schweiz-karte.js)
   Referenz:  docs/design/referenzen/Kundenansichtenportal/
              «… 13_20_23 (8).png» (Wieder buchen & Varianten kopieren:
              Aktionszeile, Statuszeilen, Fussbanner) und
              «… 13_21_20 (4).png» (Karte mit Salon-Punkten und Legende);
              «Rechnungen» als eigener Sidebar-Punkt in 6 von 11 Fassungen
              (INVENTAR-KUNDE.md:196).
   Gesetz:    docs/design/EINHEIT.md — 1.6 eine Zeile je Fläche, 2.7 Preise als
              `CHF 1'234.50`, 3.3 der Punkt heisst «Rechnungen», 4.1 Kachelbauart,
              4.7 Zustand als Wort-Chip, 4.11 Leerzustand einzeilig,
              4.13 Karte: Städtepunkte beschriftet, KEIN Leuchtradius,
              5.10 eine Zahlweise (Owner-Veto V2).

   Die EINE Sache, die dieser Block leistet: der Zahlungsstand ist auf einen
   Blick lesbar, ohne dass eine Zahl erfunden wird. «Überfällig» trägt den
   Warnton, «Offen» den ruhigen, «Bezahlt» den guten — drei Zustände, drei
   Töne, keine Zwischenstufe.

   Genutzt aus dem Bestand (NICHT neu definiert): .panel, .panel__header,
   .panel__title, .panel-row/__main/__sub/__tag, .stat*, .stat-strip,
   .kk-stat/.kk-stat__sub, .kk-betrag, .kk-stand, .kk-raster, .gz-ic,
   .kp-count, .kp-zahl, .sl-badge*, .tap-group/.tap-btn, .empty-state,
   .load-error, .bs-karte/.bs-kanton.

   EINBAU: diesen Block unverändert ans Ende von public/style.css hängen.
   Die Handy-Regeln stehen am Schluss des Blocks — nach ihren Basisregeln
   (Memory project_css_cascade_mobile).
   =========================================================================== */

/* ---- Rechnungsfläche ------------------------------------------------------ */
.kr-kacheln { margin-bottom: 18px; }
/* Die Warnkachel bekommt ihren eigenen Ton, aber nur, wenn sie etwas zu sagen
   hat. Eine rote 0.00 wäre eine Drohung ohne Anlass — deshalb hängt der Ton
   nicht an der Kachel, sondern am Zustand ihrer Zahl (:has). */
.kr-kacheln [data-kachel="ueberfaellig"] .gz-ic { --gz-feld: var(--warn-rgb); }
.kr-kacheln [data-kachel="bezahlt"] .gz-ic { --gz-feld: var(--good-rgb); }

.kr-mahnung {
  margin: -4px 0 16px;
  padding: 10px 14px;
  border-radius: var(--radius-card);
  background: rgba(var(--warn-rgb), .10);
  color: var(--warn-strong);
  font-size: 14px; line-height: 1.5;
}

.kr-panel { margin-bottom: 14px; }

/* Zeile: Nummer und Herkunft links, Betrag und Zustand rechts, Zahlangaben
   darunter über die volle Breite. Dieselbe Anatomie wie .kk-rechnung in der
   Zentrale — die Rechnung sieht an beiden Orten gleich aus. */
.kr-zeile {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  align-items: center;
  gap: 6px 14px;
}
.kr-zeile .kk-betrag { justify-self: end; }
.kr-zeile .panel-row__tag { margin-top: 2px; }
.kr-zahl { grid-column: 1 / -1; }
.kr-zahl dd { overflow-wrap: anywhere; }

/* Summenzeile: der Schlussstrich unter der Liste. Tabellenziffern, damit die
   Beträge untereinander stehen wie auf einem Kontoauszug. */
.kr-summe {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px 22px;
  margin-top: 12px; padding-top: 12px;
  border-top: 1px solid var(--border);
  font-size: 14px; font-variant-numeric: tabular-nums;
}
.kr-summe__wort {
  font-size: 11px; font-weight: 700; letter-spacing: .08em;
  text-transform: uppercase; color: var(--text-tertiary);
  margin-right: auto;
}
.kr-summe__paar b {
  font-size: 11px; font-weight: 700; letter-spacing: .04em;
  color: var(--text-tertiary); margin-right: 6px;
}

/* ---- Karte mit eigenen Standorten (Zentrale) ------------------------------ */
/* Die Grösse der Karte steht in patch-karte-finger.css, nicht hier.
   BEFUND 27.08.2026 (Wächter test:stil:einmalig): `.kk-karte-panel .bs-karte`
   stand in ZWEI Blättern — die Grundgrösse hier, die Handy-Fassung des
   25.08.-Umbaus dort. Weil karte-finger im Bauplan später steht (Blatt 75 vs.
   13), hat dessen `max-width: none` die hiesige Handy-Zeile `max-width: 100%`
   überschrieben: eine Regel, die niemand mehr sah und die trotzdem im
   ausgelieferten Blatt stand. Wer die Karte ändern wollte, musste zwei Orte
   kennen — genau der Grund, aus dem dieser Wächter zählt.
   Alles zur Karte liegt jetzt an EINEM Ort. */
.kk-karte__legende {
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px 16px;
  margin: 6px 0 0; font-size: 12.5px; color: var(--text-secondary);
}
.kk-punkt-marke {
  display: inline-block; width: 10px; height: 10px; border-radius: 50%;
  margin-right: 6px; vertical-align: -1px;
  background: var(--text-tertiary);
  box-shadow: 0 0 0 3px rgba(148, 180, 180, .14);
}
.kk-punkt-marke.is-laeuft {
  background: var(--accent);
  box-shadow: 0 0 0 3px rgba(var(--accent-rgb), .20);
}

/* ---- Die Punkte im Kartenbauteil ------------------------------------------ */
/* Ein Punkt, ein Ring, ein Ortsname. Kein Leuchtradius und keine Strassen:
   die Postleitzahl gibt genau diese Genauigkeit her (EINHEIT 4.13). */
.bs-punkt__ring { fill: rgba(148, 180, 180, .16); }
.bs-punkt__kern { fill: var(--text-tertiary); }
.bs-punkt.is-laeuft .bs-punkt__ring { fill: rgba(var(--accent-rgb), .22); }
.bs-punkt.is-laeuft .bs-punkt__kern { fill: var(--accent); }
.bs-punkt__wort {
  fill: var(--text-primary);
  font-size: 20px; font-weight: 620;
  paint-order: stroke;
  stroke: var(--surface-1); stroke-width: 4px; stroke-linejoin: round;
}

/* ---- Kopie einer Buchung -------------------------------------------------- */
.kk-uebernahme__kopf {
  display: flex; align-items: center; gap: 8px;
  margin: 0 0 8px;
  font-size: 11px; font-weight: 700; letter-spacing: .08em;
  text-transform: uppercase; color: var(--accent-strong);
}
.kk-uebernahme__kopf .gz-ic {
  --gz-feld: var(--accent-rgb);
  width: 26px; height: 26px; border-radius: var(--radius-card);
  display: inline-flex; align-items: center; justify-content: center;
  color: rgb(var(--gz-feld)); background: rgba(var(--gz-feld), .13);
}
.kk-uebernahme__kopf .gz-ic svg { width: 14px; height: 14px; }
.kk-kopie__wahl { margin-top: 12px; }
.kk-uebernahme__nicht {
  margin: 10px 0 0; font-size: 12.5px; line-height: 1.5; color: var(--text-tertiary);
}

/* ---- Handy ---------------------------------------------------------------- */
@media (max-width: 720px) {
  .kr-zeile { grid-template-columns: minmax(0, 1fr) auto; }
  .kr-zeile .sl-badge { grid-column: 2; justify-self: end; }
  .kr-zeile .kk-betrag { grid-column: 2; }
  .kr-summe { gap: 4px 14px; }
  .kr-summe__wort { flex-basis: 100%; margin-right: 0; }
  .kk-kopie__wahl .tap-btn { flex: 1 1 45%; }
  .bs-punkt__wort { font-size: 26px; }
}

/* ============================================================
   Patch-Integration — Namensraum be-; Quelle: docs/design/patch-buchungsentwuerfe.css
   Der Block wird bei Integration als GANZES ersetzt, nie editiert. Neu in W-E.
   ============================================================ */
/* =============================================================================
   W-E/E2 · Buchungs-Entwürfe — Patch
   =============================================================================
   Namensraum `be-`. Der Namensraum `ew-` ist vergeben (W-C/C3, Entwurfsstände
   je Buchung, `public/style.css` Block «Quelle: docs/design/patch-entwuerfe.css»)
   — zwei verschiedene Sachen tragen nie dieselben Klassen.

   Einbauort: als eigener Integrationsblock am ENDE von `public/style.css`.
   Grund: Projekt-Lehre `project_css_cascade_mobile` — ein früherer Block
   überschreibt eine später definierte Komponente nicht mehr, und die Reihe
   `.kk-raster` der Kundenzentrale steht weiter oben.

   Ohne diesen Patch funktioniert die Fläche vollständig; sie benutzt sonst nur
   bestehende Klassen (`.panel`, `.panel-row`, `.primary-btn`, `.ghost-btn`,
   `.kk-panel`, `.kp-count`). Der Patch macht drei Dinge:
     1. die dritte Spalte der Panel-Reihe (EINHEIT 4.15),
     2. den Fortschrittsbalken der Referenz `13_20_22 (7)`,
     3. die ruhige Zeile «Zwischenstand gesichert» unter der Schrittleiste.
   ========================================================================== */

/* --- 1) Die dreispaltige Reihe (Wieder buchen · Entwürfe · Benötigte Inhalte)
   Nur oberhalb der Zwischenbreite: darunter macht `.kk-raster` bereits einen
   Einspalter (`patch-kundenzentrale.css`, @media max-width:1080px), und dieser
   Block darf ihn nicht zurückdrehen. Deshalb min-width statt max-width — ein
   späterer Block gewinnt sonst gegen die Handy-Regel. */
@media (min-width: 1081px) {
  .kk-raster.be-raster3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

/* --- 2) Die Entwurfszeile ------------------------------------------------- */
.be-entwurf { align-items: center; }

/* Der Balken ist die visuelle Quelle der Prozentzahl (EINHEIT 4.3: jede Karte
   trägt ein visuelles Element). Er steht UNTER dem Untertitel und über dem
   Zahlenwort — dieselbe Reihenfolge wie in der Referenz. */
.be-balken {
  display: block;
  height: 6px;
  margin: 8px 0 6px;
  border-radius: 999px;
  background: var(--surface-3, rgba(255, 255, 255, .08));
  overflow: hidden;
}
.be-balken > i {
  display: block;
  height: 100%;
  border-radius: 999px;
  background: var(--accent, #29d3c2);
  /* Ein Entwurf bei 0 % hat einen sichtbaren Anfang, keine unsichtbare Linie. */
  min-width: 2px;
}

/* Die Rückfrage sitzt an der Stelle der beiden Knöpfe — die Zeile springt
   dadurch nicht in der Höhe (EINHEIT 5.11: kein Browser-Dialog). */
.be-frage {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  justify-content: flex-end;
}
.be-frage__satz {
  font-size: 13px;
  color: var(--text-secondary, rgba(255, 255, 255, .68));
  white-space: nowrap;
}

/* --- 3) Der Zwischenspeicher unter der Schrittleiste ---------------------- */
.be-merker {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  /* Leer heisst leer: kein Abstand, wo nichts steht. */
  margin: 0;
}
.be-merker:not(:empty) { margin: -4px 0 16px; }

.be-merker__satz {
  margin: 0;
  font-size: 13px;
  color: var(--text-secondary, rgba(255, 255, 255, .68));
}
.be-merker__satz--fehler { color: var(--warn-strong, #e8b04b); }

.be-merker__tun {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
}
.be-merker__tun svg { width: 15px; height: 15px; }

/* Touch-Boden auch auf Tablets (Memory project_tablet_touch_breakpoint):
   720px allein deckt die Bruchzone 768/1024 nicht ab. */
@media (max-width: 1024px), (pointer: coarse) {
  .be-merker__tun { min-height: 44px; }
  .be-entwurf .kk-tun { min-height: 44px; }
}

/* Auf dem Handy stehen Fortfahren und Verwerfen unter der Zeile, nicht daneben
   — rechts ist dort kein Platz für zwei Knöpfe und den Balken. */
@media (max-width: 720px) {
  .be-entwurf { flex-wrap: wrap; }
  .be-entwurf .kk-tun { flex: 1 1 140px; }
  .be-frage { width: 100%; justify-content: flex-start; }
}

/* ============================================================
   Patch-Integration — Namensraum ei-/el-; Quelle: docs/design/patch-einladungen.css
   Der Block wird bei Integration als GANZES ersetzt, nie editiert. Neu in W-E (E1).
   ============================================================ */
/* ============================================================
   W-E/E1 · Einladungen — zwei Flächen, ein Vorgang
   Namensräume: ei-  (innen,  #/p/einladungen — LoopX13)
                el-  (aussen, #/einladung/:token — LoopScreens)
   Referenz: docs/design/referenzen/Kundenansichtenportal/
             «… 13_20_06 (1).png», «… 13_21_19 (1).png»,
             «… 13_21_01 (1).png» — QR-Einstieg: Chip «QR-Code erkannt»,
             Standortkarte mit Zeichen links, gestapelte Wahl-Zeilen,
             Nutzenstreifen im Fuss, kein Fensterrahmen.
   Gesetz:   docs/design/EINHEIT.md — 1.1 zwei Wortmarken (aussen
             «LoopScreens», ohne Signet) · 1.3 EIN Akzent Türkis · 1.4 drei
             Knopfstufen · 1.5 Titel 26 px ohne Zeichen · 2.1 «du» aussen ·
             3.6 aussen KEINE Statusleiste · 3.9 kein Fensterrahmen,
             kein macOS-Mockup · 4.1 Kachelbauart · 4.4 Einfachwahl trägt eine
             Marke, nie nur einen Rahmen · 4.7 Zustand als Wort-Chip ·
             4.11 Leerzustand einzeilig · 4.14 Nutzenstreifen genau drei Punkte.
   Genutzt aus dem Bestand (NICHT neu definiert): .panel, .stat/.stat__label/
             .stat__value/.stat__sub, .gz-kachel/.gz-ic/.gz-panel__titel,
             .stat-strip/--auto, .field/.field--wide, .sl-badge*, .primary-btn,
             .ghost-btn, .empty-state, .load-error.
   Integration: als Block ans Ende von public/style.css hängen.
   ============================================================ */

/* Welle 8 «Muster», 18.08.2026 — ENTFERNT, nicht ersetzt: .ei-kopf__zeile (1×).
   Diese Hülle(n) waren eine Nachbildung der EINEN Kopfreihe. Sie kommt jetzt
   aus `components/seiten-kopf.js` (Blatt patch-seitenkopf.css, Abschnitt 1b/2).
   «Ersetzen statt daneben» — Hausregel 7. */

/* ================= INNEN — #/p/einladungen ================== */

.ei-kopf { margin-bottom: 16px; }
.ei-kopf__zahl {
  font-size: 12.5px; color: var(--text-tertiary);
  font-variant-numeric: tabular-nums;
}

/* Kachelzeile: dieselbe Bauart wie überall (Zeichen oben, Label, Zahl, EINE
   Zusatzzeile). Der Bereichston ist Grün — Standortbetreiber. */
.ei-kacheln { margin-bottom: 16px; }
.ei .gz-ic { --gz-feld: var(--gz-partner); }
.ei-kacheln .stat { padding: 14px 16px; }
.ei-kacheln .stat__value { font-size: 22px; }
.ei-kacheln .gz-ic { --gz-ic-gr: 28px; margin-bottom: 8px; }

/* --- Neue Einladung ---------------------------------------- */
.ei-neu { margin-bottom: 16px; }
.ei-neu__form {
  display: flex; flex-wrap: wrap; align-items: flex-end; gap: 12px;
  margin-top: 14px;
}
.ei-neu__form .primary-btn { min-height: 40px; }
.ei-neu__satz {
  margin: 10px 0 0; font-size: 12.5px; line-height: 1.5;
  color: var(--text-tertiary);
}
.ei-frist { border: 0; padding: 0; margin: 0; min-width: 0; }
.ei-frist legend {
  padding: 0 0 6px; color: var(--text-tertiary); font-size: 11px;
  text-transform: uppercase; letter-spacing: .07em; font-weight: 600;
}
.ei-frist__wahl {
  display: inline-flex; align-items: center; gap: 7px;
  min-height: 40px; padding: 0 13px; margin-right: 8px;
  border: 1px solid var(--border); border-radius: var(--radius-card);
  background: var(--surface); cursor: pointer;
  font-size: 13px; color: var(--text-secondary);
  transition: border-color var(--transition), color var(--transition);
}
.ei-frist__wahl input { accent-color: var(--accent); width: 16px; height: 16px; }
.ei-frist__wahl.is-gewaehlt { border-color: var(--accent-line); color: var(--text-primary); }

/* --- QR-Block ---------------------------------------------- */
.ei-qr { margin-bottom: 16px; }
.ei-qr__kopf {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; flex-wrap: wrap; margin-bottom: 14px;
}
.ei-qr__leib { display: flex; flex-wrap: wrap; gap: 20px; align-items: flex-start; }
/* Der Code selbst bleibt schwarz auf weiss — jeder andere Kontrast kostet
   Lesbarkeit beim Scannen, und genau dafür ist er da. */
.ei-qr__bild {
  flex: 0 0 auto; border-radius: var(--radius-card); background: #fff;
  border: 1px solid var(--border);
}
.ei-qr__daten { display: grid; gap: 10px; min-width: min(340px, 100%); flex: 1 1 340px; }
.ei-qr__frist {
  margin: 0; font-size: 12.5px; color: var(--text-secondary);
  font-variant-numeric: tabular-nums;
}
.ei-qr__zeile { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.ei-qr__code {
  flex: 1 1 240px; min-width: 0; overflow-wrap: anywhere;
  padding: 8px 10px; border-radius: var(--radius-card);
  background: var(--surface-inset); border: 1px solid var(--border);
  font-size: 12px; color: var(--text-secondary);
}
.ei-qr__satz { margin: 0; font-size: 12.5px; line-height: 1.5; color: var(--text-tertiary); }

/* --- Liste -------------------------------------------------- */
.ei-liste { padding: 0; }
.ei-zeile { padding: 14px 18px; border-top: 1px solid var(--border); }
.ei-zeile:first-child { border-top: 0; }
.ei-zeile__kopf {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
}
.ei-zeile__haupt { display: grid; gap: 1px; min-width: 0; flex: 1 1 220px; }
.ei-zeile__sub { font-size: 11px; color: var(--text-tertiary); letter-spacing: .02em; }
.ei-zeile__haupt b { font-size: 13.5px; font-weight: 600; color: var(--text-primary); }
.ei-zeile__frist {
  font-size: 12px; color: var(--text-tertiary);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.ei-zeile__knoepfe { display: flex; gap: 8px; margin-left: auto; }
.ei-zeile__knoepfe .ghost-btn { min-height: 36px; }
.ei-btn--weg { color: var(--bad-strong); border-color: rgba(var(--bad-rgb), .35); }
.ei-btn--weg:hover { border-color: var(--bad-strong); }
/* Die Notiz gehört zum Namen, nicht ans Zeilenende: auf 390 px rutschte sie
   sonst unter die Knöpfe und stand hinter der Handlung statt bei ihrem
   Gegenstand. */
.ei-zeile__notiz { font-size: 12.5px; color: var(--text-secondary); }

/* Der gestellte Antrag: alles, was der Admin für die Freigabe braucht — und
   der Weg dorthin als echter Knopf, nicht als Satz. */
.ei-antrag {
  margin-top: 12px; padding: 12px 14px;
  border-radius: var(--radius-card); background: var(--surface-inset);
}
.ei-antrag__liste {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 10px 18px; margin: 0;
}
.ei-antrag__liste > div { display: grid; gap: 2px; min-width: 0; }
.ei-antrag__liste dt {
  font-size: 11px; text-transform: uppercase; letter-spacing: .07em;
  font-weight: 600; color: var(--text-tertiary);
}
.ei-antrag__liste dd {
  margin: 0; font-size: 13px; color: var(--text-primary); overflow-wrap: anywhere;
}
.ei-antrag__weiter {
  display: inline-flex; margin-top: 12px; max-width: 100%;
  /* Der Satz ist lang und darf umbrechen — .ghost-btn hält ihn sonst in EINER
     Zeile und schiebt die Fläche auf 390 px über den Rand hinaus. */
  white-space: normal; text-align: left; line-height: 1.35;
  padding-top: 9px; padding-bottom: 9px; height: auto;
}

@media (max-width: 720px) {
  .ei-neu__form { gap: 10px; }
  .ei-neu__form .primary-btn { width: 100%; min-height: 46px; }
  .ei-zeile__knoepfe { margin-left: 0; width: 100%; }
  .ei-zeile__knoepfe .ghost-btn { flex: 1 1 auto; min-height: 46px; }
  .ei-frist__wahl { min-height: 46px; }
}

/* ================= AUSSEN — #/einladung/:token ============== */
/* Eine Karte, mittig, kein App-Chrome, kein Fensterrahmen (EINHEIT 3.9),
   keine Statusleiste (3.6). Was ein Fremder sieht, ist eine Seite — nicht
   ein Werkzeug, in das er versehentlich geraten ist. */
.el {
  --gz-feld: var(--accent-rgb);
  display: flex; justify-content: center;
  /* flex-start, nicht der Default «stretch»: sonst wird die Karte auf die volle
     Höhe gezogen und ein kurzer Zustand (toter Code, Danke) endet in einem
     halben Bildschirm Leere. */
  align-items: flex-start;
  padding: clamp(20px, 6vh, 56px) 16px calc(40px + env(safe-area-inset-bottom));
  min-height: 100dvh;
}
.el-karte {
  width: 100%; max-width: 620px; padding: clamp(20px, 4vw, 34px);
}
.el-laedt { margin: 0; color: var(--text-secondary); font-size: 13.5px; }

.el-kopf {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; flex-wrap: wrap; margin-bottom: 22px;
}
/* Wortmarke aussen: gemischte Schreibung, «Screens» in Türkis, ohne Signet. */
.el-marke {
  font-size: 17px; font-weight: 650; letter-spacing: -.01em;
  color: var(--text-primary); white-space: nowrap;
}
.el-marke__akzent { color: var(--accent); }
.el-titel .el-marke { font-size: inherit; font-weight: inherit; letter-spacing: inherit; }

.el-erkannt {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 5px 11px; border-radius: var(--radius-badge);
  background: var(--accent-soft); color: var(--accent-strong);
  border: 1px solid var(--accent-line);
  font-size: 12px; font-weight: 600; white-space: nowrap;
}
.el-erkannt svg { width: 13px; height: 13px; }

.el-titel {
  margin: 0 0 10px; font-size: 26px; font-weight: 650; letter-spacing: -.02em;
  line-height: 1.18; color: var(--text-primary);
}
.el-satz {
  margin: 0 0 22px; font-size: 14px; line-height: 1.55;
  color: var(--text-secondary);
}
.el-haken {
  display: grid; place-items: center; width: 44px; height: 44px;
  margin-bottom: 14px; border-radius: var(--radius-card);
  background: rgba(var(--good-rgb), .13); color: var(--good-strong);
}
.el-haken svg { width: 22px; height: 22px; }

/* «Gescannt bei …» — die Standortkarte der Referenz, ohne erfundenes Foto:
   es gibt in diesem System kein Bild eines Standorts. */
.el-standort {
  display: flex; align-items: center; gap: 12px;
  padding: 13px 15px; margin-bottom: 22px;
  border-radius: var(--radius-card); background: var(--surface-inset);
  border: 1px solid var(--border);
}
.el-standort__text { display: grid; gap: 2px; min-width: 0; }
/* «Gescannt bei» steht in der Referenz «13_21_19 (1)» in gemischter Schreibung
   — und gesperrte Versalien gehören in diesem System dem Spaltenkopf
   (EINHEIT 1.5). */
.el-standort__label {
  font-size: 11.5px; letter-spacing: 0; font-weight: 500;
  color: var(--text-tertiary);
}
.el-standort__text b { font-size: 14.5px; font-weight: 600; color: var(--text-primary); }

.el-form { display: grid; gap: 18px; }
/* Aussen sind die Feldnamen Fragen, keine Spaltenköpfe: gemischte Schreibung,
   dieselbe Stufe wie die Legenden der Tap-Gruppen (EINHEIT 1.5 — gesperrte
   Versalien tragen genau EINE Aufgabe, und das ist der Tabellenkopf). */
.el-form .field > span {
  font-size: 13.5px; font-weight: 600; letter-spacing: 0;
  text-transform: none; color: var(--text-primary);
}
.el-paar { display: flex; flex-wrap: wrap; gap: 12px; }
.el-paar .field { flex: 1 1 180px; }
.el-feld { border: 0; padding: 0; margin: 0; min-width: 0; }
.el-feld legend {
  padding: 0 0 9px; font-size: 13.5px; font-weight: 600;
  color: var(--text-primary);
}
.el-feld__satz { margin: 8px 0 0; font-size: 12px; color: var(--text-tertiary); }

/* Tap-Felder: die Wahl ist die Fläche, nicht der kleine Punkt daneben.
   ≥44 px hoch (mobile PWA mandatory), Marke bei Auswahl (EINHEIT 4.4). */
.el-chips { display: flex; flex-wrap: wrap; gap: 9px; }
.el-chip {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 46px; padding: 0 16px;
  border: 1px solid var(--border); border-radius: var(--radius-card);
  background: var(--surface); cursor: pointer;
  font-size: 13.5px; color: var(--text-secondary);
  transition: border-color var(--transition), background var(--transition), color var(--transition);
}
.el-chips--eng .el-chip { min-width: 52px; padding: 0 10px; }
.el-chip input {
  position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none;
}
.el-chip:hover { border-color: var(--accent-line); }
.el-chip:focus-within { outline: 2px solid var(--accent); outline-offset: 2px; }
.el-chip.is-gewaehlt {
  border-color: var(--accent); background: var(--accent-soft);
  color: var(--text-primary); font-weight: 600;
}
/* Die Marke der Einfachwahl: ein gefüllter Kreis mit Haken, links im Feld. */
.el-chip.is-gewaehlt span::before {
  content: ""; display: inline-block; width: 15px; height: 15px;
  margin-right: 8px; vertical-align: -2px; border-radius: 50%;
  background: var(--accent) center / 10px 10px no-repeat;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23042a26' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E");
}

.el-senden { min-height: 50px; width: 100%; font-size: 15px; }
.el-fehler {
  margin: 0; padding: 10px 12px; border-radius: var(--radius-card);
  background: rgba(var(--bad-rgb), .10); border: 1px solid rgba(var(--bad-rgb), .35);
  color: var(--bad-strong); font-size: 13px;
}
.el-recht { margin: 0; font-size: 11.5px; line-height: 1.5; color: var(--text-tertiary); }

/* Nutzenstreifen: genau drei Punkte, fester Wortlaut (EINHEIT 4.14). */
.el-nutzen {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 16px;
  margin-top: 26px; padding-top: 20px; border-top: 1px solid var(--border);
}
.el-nutzen__punkt { display: grid; gap: 5px; min-width: 0; }
.el-nutzen__punkt .gz-ic { --gz-ic-gr: 30px; }
.el-nutzen__punkt b { font-size: 13px; font-weight: 600; color: var(--text-primary); }
.el-nutzen__punkt span:not(.gz-ic) {
  font-size: 12px; line-height: 1.45; color: var(--text-secondary);
}

@media (max-width: 560px) {
  .el-karte { padding: 20px 16px; }
  .el-titel { font-size: 22px; }
  .el-nutzen { grid-template-columns: 1fr; gap: 14px; }
  .el-paar .field { flex: 1 1 100%; }
}

/* ============================================================
   Patch-Integration — Namensraum en-; Quelle: docs/design/patch-entscheide.css
   Der Block wird bei Integration als GANZES ersetzt, nie editiert. Neu in W-F.
   ============================================================ */
/* ============================================================
   W-F/F2 · Entscheide — der Owner-Bildschirm
   Namensraum: en-  (innen, #/v/entscheide)
   Referenz:   docs/design/referenzen/Portaluikomplett/
               «… 13_25_33 (10).png» — Warnbanner über den Optionen, zwei
               gleich breite Optionskarten nebeneinander, je eine Liste
               vergleichender Kennwerte in Label-links/Wert-rechts-Zeilen,
               darunter «Deine Entscheidung» mit Wahl und gesperrtem
               Bestätigen-Knopf.
   Gesetz:     docs/design/EINHEIT.md — 1.3 EIN Akzent Türkis · 1.4 drei
               Knopfstufen · 1.5 Titel 26 px ohne Zeichen, Panel-Titel in
               gemischter Schreibung · 1.6 kein Erklärtext unter dem Titel ·
               2.1 «du» · 2.6/2.7 CHF mit Apostroph und zwei Rappenstellen ·
               4.1 Kachelbauart · 4.4 Einfachwahl trägt eine Marke, nie nur
               einen Rahmen · 4.6 KEIN Chip ohne Quelle (deshalb kein
               «Empfohlen») · 4.7 Zustand als Wort-Chip · 4.8 Risiko als
               Status-Chip · 4.11 Leerzustand einzeilig.
   Bereichston: Stahl (--gz-missionen) — der Entscheid gehört dem Betrieb
               selbst, nicht Verkauf, Geld oder Partner.
   Genutzt aus dem Bestand (NICHT neu definiert): .panel, .stat/.stat__label/
               .stat__value/.stat__sub, .stat-strip/--auto, .gz-kachel/.gz-ic/
               .gz-panel__titel, .sl-badge*, .primary-btn, .ghost-btn,
               .empty-state, .load-error.
   Integration: als Block ans Ende von public/style.css hängen.
   ============================================================ */

.en { --gz-feld: var(--gz-missionen); }
.en-kopf { margin-bottom: 16px; }
/* Die Kopf-Hülle dieser Fläche ist am 19.08.2026 gefallen — sie trägt jetzt
   den EINEN Seitenkopf (components/seiten-kopf.js), und dessen eigene Reihe
   («Titel + Beiwerk daneben») ersetzt die Reihe, die sich hier sieben Flächen
   je selbst gebaut hatten. «Ersetzen statt daneben»: die Regel ist entfernt,
   nicht stehen gelassen. Was BLEIBT, ist die Zahl daneben — sie wird dem
   Bauteil als `neben` hereingereicht und behält ihre Klasse. */
.en-kopf__zahl {
  font-size: 12.5px; color: var(--text-tertiary);
  font-variant-numeric: tabular-nums;
}

/* Kachelzeile: dieselbe Bauart wie überall (Zeichen oben, Label, Zahl, EINE
   Zusatzzeile). */
.en-kacheln { margin-bottom: 16px; }
.en-kacheln .stat { padding: 14px 16px; }
.en-kacheln .stat__value { font-size: 22px; }
.en-kacheln .gz-ic { --gz-ic-gr: 28px; margin-bottom: 8px; }

/* --- Die Frage --------------------------------------------- */
.en-frage { margin-bottom: 16px; }
.en-frage__kopf {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; flex-wrap: wrap; margin-bottom: 12px;
}
.en-frist {
  font-size: 12.5px; font-variant-numeric: tabular-nums;
  color: var(--warn-strong); white-space: nowrap;
}

/* Das Warnband der Referenz. Bernstein, nicht Rot: es ist eine Ansage, kein
   Fehler (EINHEIT 1.3). */
.en-warnung {
  display: flex; align-items: center; gap: 10px; margin: 0 0 12px;
  padding: 11px 14px; border-radius: var(--radius-card);
  background: rgba(var(--warn-rgb), .10);
  border: 1px solid rgba(var(--warn-rgb), .28);
  font-size: 12.5px; line-height: 1.5; color: var(--warn-strong);
}
.en-warnung .gz-ic--warn { --gz-feld: var(--warn-rgb); --gz-ic-gr: 26px; }

/* Die dritte Zahl. Sie steht nur da, wenn der Server sie geliefert hat —
   und dann immer mit ihrer Fallzahl im Satz daneben. */
.en-quote {
  display: flex; align-items: baseline; gap: 10px; margin: 0 0 14px;
  padding: 10px 14px; border-radius: var(--radius-card);
  background: var(--surface-inset);
  font-size: 12.5px; line-height: 1.5; color: var(--text-secondary);
}
.en-quote__wert {
  font-size: 20px; font-weight: 650; letter-spacing: -.02em;
  color: var(--accent-strong); font-variant-numeric: tabular-nums;
}

/* --- Die Optionen nebeneinander ----------------------------- */
.en-optionen {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px;
}
.en-option {
  display: flex; flex-direction: column; gap: 10px;
  padding: 16px 18px; border-radius: var(--radius-card);
  background: var(--surface-inset);
  border: 1px solid var(--line);
}
.en-option.is-wahl { border-color: var(--accent); background: var(--accent-soft); }
.en-option.is-gewaehlt { border-color: rgba(var(--good-rgb), .45); }
.en-option.is-tot { opacity: .62; }
/* «Option A» ist eine Ordnungsmarke, kein Werturteil — deshalb Tertiärton und
   kein Chip. Ein «Empfohlen» gäbe es hier nur mit Quelle (EINHEIT 4.6). Die
   Ecke rechts daneben bleibt leer: ein Chip, der an jeder offenen Möglichkeit
   dasselbe Wort trägt, sagt nichts, was der Knopf darunter nicht schon sagt. */
.en-option__marke {
  font-size: 11.5px; letter-spacing: .08em; text-transform: uppercase;
  color: var(--text-tertiary);
}
.en-option__titel {
  margin: 0; font-size: 15px; font-weight: 620; letter-spacing: -.01em;
  color: var(--text-primary); line-height: 1.35;
}

/* Die vergleichenden Zeilen: Label links, Wert rechts, feine Trennlinie —
   genau die Anatomie der Referenz. */
.en-vergleich { margin: 0; display: flex; flex-direction: column; }
.en-vergleich > div {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 14px; padding: 8px 0; border-top: 1px solid var(--line);
}
.en-vergleich > div:first-child { border-top: 0; }
.en-vergleich dt {
  flex: 0 0 auto; font-size: 12px; color: var(--text-tertiary);
}
.en-vergleich dd {
  margin: 0; text-align: right; font-size: 12.5px; line-height: 1.5;
  color: var(--text-secondary);
}
.en-vergleich__zahl {
  font-variant-numeric: tabular-nums; font-weight: 620;
  color: var(--text-primary) !important;
}
.en-risiko--niedrig { background: rgba(var(--good-rgb),.13); color: var(--good-strong); border-color: rgba(var(--good-rgb),.35); }
.en-risiko--mittel  { background: rgba(var(--warn-rgb),.13); color: var(--warn-strong); border-color: rgba(var(--warn-rgb),.35); }
.en-risiko--hoch    { background: rgba(var(--bad-rgb),.13);  color: var(--bad-strong);  border-color: rgba(var(--bad-rgb),.35); }

.en-option__waehlen { margin-top: auto; align-self: stretch; min-height: 40px; }

/* --- Der Bestätigungsschritt -------------------------------- */
.en-bestaetigung {
  margin-top: 14px; padding: 16px 18px; border-radius: var(--radius-card);
  background: var(--surface-inset); border: 1px solid var(--accent-line);
}
.en-bestaetigung h3 {
  margin: 0 0 6px; font-size: 13px; font-weight: 620; color: var(--text-primary);
}
.en-bestaetigung__satz {
  margin: 0 0 12px; font-size: 12.5px; line-height: 1.6; color: var(--text-secondary);
}
.en-bestaetigung__satz b { color: var(--text-primary); }

/* Wahl-Chips statt Tippfeld. Jeder Chip trägt seine Marke (EINHEIT 4.4) —
   ein Rahmen allein sagt nicht, dass genau eine Wahl gemeint ist. */
.en-gruende { border: 0; margin: 0 0 14px; padding: 0; }
.en-gruende legend {
  padding: 0; margin-bottom: 8px;
  font-size: 12px; color: var(--text-tertiary);
}
.en-gruende__chip {
  display: inline-flex; align-items: center; gap: 8px;
  margin: 0 8px 8px 0; padding: 8px 12px; min-height: 40px;
  border-radius: var(--radius-badge); border: 1px solid var(--line);
  background: var(--surface); cursor: pointer;
  font-size: 12.5px; color: var(--text-secondary);
}
.en-gruende__chip input { accent-color: var(--accent); margin: 0; }
.en-gruende__chip.is-gewaehlt {
  border-color: var(--accent); background: var(--accent-soft);
  color: var(--accent-strong);
}
.en-bestaetigung__knoepfe { display: flex; gap: 10px; flex-wrap: wrap; }
.en-bestaetigung__knoepfe .primary-btn,
.en-bestaetigung__knoepfe .ghost-btn { min-height: 44px; }
.en-bestaetigung__knoepfe .primary-btn[disabled] { opacity: .45; cursor: not-allowed; }
.en-bestaetigung__fuss {
  margin: 10px 0 0; font-size: 12px; line-height: 1.5; color: var(--text-tertiary);
}

.en-frage__fuss {
  margin: 12px 0 0; font-size: 12px; line-height: 1.5; color: var(--text-tertiary);
}
.en-frage__fuss code {
  font-size: 11.5px; color: var(--text-secondary);
  background: var(--surface-inset); padding: 1px 6px; border-radius: var(--radius-card);
}

/* --- Protokoll ---------------------------------------------- */
.en-protokoll { margin-bottom: 16px; }
.en-zeile { padding: 12px 0; border-top: 1px solid var(--line); }
.en-zeile:first-of-type { border-top: 0; }
.en-zeile__kopf {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; flex-wrap: wrap;
}
.en-zeile__frage { font-size: 13px; font-weight: 620; color: var(--text-primary); }
.en-zeile__satz {
  margin: 6px 0 0; font-size: 12.5px; line-height: 1.6; color: var(--text-secondary);
}
.en-zeile__satz b { color: var(--text-primary); }
.en-zeile__rest {
  margin: 4px 0 0; font-size: 12px; color: var(--text-tertiary);
}
.en-zeile__rest:empty { display: none; }

/* --- Handy: die Optionen stapeln, die Tap-Flächen bleiben ---- */
@media (max-width: 900px) {
  .en-optionen { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 720px) {
  .en-kacheln { grid-auto-flow: row; grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .en-frage__kopf { align-items: flex-start; }
  .en-vergleich > div { flex-direction: column; align-items: flex-start; gap: 2px; }
  .en-vergleich dd { text-align: left; }
  .en-option__waehlen { min-height: 44px; }
}

/* ============================================================
   Patch-Integration — Namensraum ag-; Quelle: docs/design/patch-agenten.css
   Der Block wird bei Integration als GANZES ersetzt, nie editiert. Neu in W-F.
   ============================================================ */
/* ============================================================
   W-F/F4 · Agenten & Rollen — #/v/agenten
   Namensraum: ag-  (innen, LoopX13 · Agent OS)
   Referenz:   docs/design/referenzen/Portaluikomplett/
               «… 13_25_33 (5).png» — Kopf «Agenten & Rollen», Sonderkarte des
               Owner-Agenten mit Zustands-Pill und Kennwerten rechts, darunter
               die Liste der Agenten mit Zuweisung, Status, Fähigkeits-Chips
               und einer Vertrauensspalte.
   Bewusst NICHT übernommen (der Prototyp erfindet dort, was es nicht gibt):
     · «Vertrauen 98 %» als nackte Zahl → hier stehen die BESTANDTEILE
       (Vorschauen · ausgeführt · offen · zurückgenommen · abgewiesen) und die
       Quote nur mit Nenner und Herkunftssatz (FINISH-STANDARD 7).
     · zehn erfundene Spezialisten mit Modell-/Tool-Chips (GPT-4o, Claude,
       Figma MCP) → es gibt EINEN Bausatz, den Chat, mit einer Zeile je Rolle
       (20260729000500). Fremde Marken-Logos: keine (EINHEIT 1.7).
     · Kronen-Icon und Sonderkarte → jede Karte hat dieselbe Bauart; wer
       handeln darf, sagt sein Wort-Chip, nicht seine Grösse.
   Gesetz:   docs/design/EINHEIT.md — 1.3 EIN Akzent Türkis · 1.5 Titel 26 px
             ohne Zeichen · 1.6 kein Erklärtext unter dem Titel · 2.6 Schweizer
             Zahlen · 2.10 Datum TT.MM.JJJJ · 4.1 Kachelbauart · 4.3 visuelles
             Element nur mit Quelle · 4.7 Zustand als gerahmter Wort-Chip ·
             4.11 Leerzustand einzeilig.
   Genutzt aus dem Bestand (NICHT neu definiert): .panel, .panel-row,
             .panel-row__main, .stat/.stat__label/.stat__value/.stat__sub,
             .stat__bar, .stat-strip/--auto, .gz-kopf, .gz-ic, .gz-kachel,
             .gz-kacheln, .badge, .empty-state, .load-error.
   Integration: als Block ans Ende von public/style.css hängen.
   ============================================================ */

/* Welle 8 «Muster», 18.08.2026 — ENTFERNT, nicht ersetzt: .ag-kopf__zeile (1×), .ag-kopf__steuer (1×).
   Diese Hülle(n) waren eine Nachbildung der EINEN Kopfreihe. Sie kommt jetzt
   aus `components/seiten-kopf.js` (Blatt patch-seitenkopf.css, Abschnitt 1b/2).
   «Ersetzen statt daneben» — Hausregel 7. */

.ag-kopf { margin-bottom: 16px; }
/* Der Zeitraum steht im Kopf, nicht als Erklärtext darunter (EINHEIT 1.6):
   er ist eine Angabe zu den Zahlen, kein Satz über die Fläche. */
.ag-kopf__zeitraum {
  font-size: 12.5px; color: var(--text-tertiary);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}

/* --- Kachelzeile: dieselbe Bauart wie in der Zentrale ------------------- */
.ag-kacheln { margin-bottom: 16px; }
.ag .gz-ic { --gz-feld: var(--gz-missionen, 168, 190, 205); }
.ag-kacheln .stat { padding: 14px 16px; }
.ag-kacheln .stat__value { font-size: 22px; }
.ag-kacheln .gz-ic { --gz-ic-gr: 28px; margin-bottom: 8px; }

/* --- Die Karten --------------------------------------------------------- */
.ag-liste { display: grid; gap: 14px; }
.ag-karte { display: grid; gap: 14px; padding: 18px 20px; }
/* Wer nichts darf und nichts getan hat, bekommt eine flache Karte statt einer
   grossen mit fünf Nullen darin (FINISH-STANDARD: keine leeren Riesenkarten). */
.ag-karte--knapp { gap: 8px; padding: 14px 20px; }

.ag-karte__kopf { display: flex; align-items: center; gap: 12px; min-width: 0; }
.ag-karte__ic { --gz-ic-gr: 34px; }
.ag-karte__wer { display: grid; gap: 2px; min-width: 0; flex: 1 1 auto; }
.ag-karte__name {
  font-size: 15px; font-weight: 650; letter-spacing: -.01em;
  color: var(--text-primary);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ag-karte__meta {
  font-size: 11.5px; color: var(--text-tertiary);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* Wort-Chips, gerahmt (EINHEIT 4.7). Türkis trägt nur den EINEN Zustand, der
   wirklich Handlung bedeutet — «antwortet nur» und «aus» sind neutral, nicht
   rot: sie sind kein Fehler, sondern die ausgelieferte Einstellung. */
.ag-chip { border: 1px solid var(--line-strong); }
.ag-chip--aktiv { background: var(--accent-soft); color: var(--accent-strong); border-color: rgba(var(--accent-rgb), .35); }
.ag-chip--offen { background: rgba(var(--tint-rgb), .08); color: var(--text-secondary); }
.ag-chip--ruhend { background: rgba(var(--tint-rgb), .06); color: var(--text-tertiary); }

/* --- Die Rechnung statt der Prozentzahl --------------------------------- */
/* Fünf Bestandteile nebeneinander, Zahl über Wort. Auf 390 px umbrechend
   statt gestaucht — eine abgeschnittene Beschriftung wäre genau die Sorte
   Zahl ohne Herkunft, die diese Fläche vermeidet. */
.ag-rechnung {
  display: grid; grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 10px 8px;
  padding: 14px 16px; border-radius: var(--radius-card);
  background: rgba(var(--tint-rgb), .04); border: 1px solid var(--border);
}
.ag-teil { display: grid; gap: 2px; min-width: 0; }
.ag-teil b {
  font-size: 20px; font-weight: 650; letter-spacing: -.02em;
  color: var(--text-primary); font-variant-numeric: tabular-nums;
}
.ag-teil i {
  font-style: normal; font-size: 11.5px; line-height: 1.35;
  color: var(--text-tertiary);
}
/* Bernstein erst, wenn die Zahl grösser als null ist — eine bernsteinfarbene
   Null behauptet ein Problem, das es nicht gibt. */
.ag-teil--warn b { color: var(--warn-strong); }

/* --- Die Quote, wenn sie einen Nenner hat ------------------------------- */
.ag-quote { display: grid; gap: 8px; }
.ag-quote__kopf { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.ag-quote__zahl {
  font-size: 14px; font-weight: 650; color: var(--text-primary);
  font-variant-numeric: tabular-nums;
}
.ag-quote__prozent {
  font-size: 12.5px; color: var(--accent-strong);
  font-variant-numeric: tabular-nums;
}
.ag-quote__bar { margin: 0; }
.ag-quote__satz { margin: 0; font-size: 12px; line-height: 1.5; color: var(--text-tertiary); }
/* Ohne Nenner: ein Satz, keine Zahl, kein Balken (EINHEIT 4.3/4.11). */
.ag-quote--leer { margin: 0; font-size: 12.5px; line-height: 1.5; color: var(--text-tertiary); }

/* --- Scope: was dieser Agent überhaupt darf ----------------------------- */
.ag-scope { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.ag-faehig {
  background: rgba(var(--tint-rgb), .07); color: var(--text-secondary);
  border: 1px solid var(--border);
}
/* Nicht umkehrbar: ein Zeichen am Chip, kein zweiter Chip und kein
   Ausrufezeichen im Wort — das läse sich als Befehl statt als Warnung. */
.ag-faehig__warn { display: inline-flex; margin-left: 5px; color: var(--warn-strong); }
.ag-faehig__warn svg { width: 12px; height: 12px; }
.ag-scope__satz {
  flex: 1 1 100%; margin: 0; font-size: 12px; line-height: 1.5;
  color: var(--text-tertiary);
}

/* --- Letzte Handlungen -------------------------------------------------- */
.ag-verlauf { display: grid; }
.ag-zeile { padding: 10px 0; gap: 8px 12px; }
.ag-zeile:first-child { padding-top: 0; }
.ag-zeile__wer { flex: 1 1 220px; }
.ag-zeile__meta { font-size: 12px; color: var(--text-tertiary); font-variant-numeric: tabular-nums; }
.ag-zeile__zeit {
  font-size: 12px; color: var(--text-tertiary);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
/* Zustand einer einzelnen Handlung — dieselben Wort-Chips wie oben, mit den
   drei Bedeutungen, die es wirklich gibt: gewirkt, unterwegs, zurückgedreht. */
.ag-chip--succeeded { background: var(--accent-soft); color: var(--accent-strong); }
.ag-chip--partial { background: rgba(var(--warn-rgb), .13); color: var(--warn-strong); }
.ag-chip--previewed,
.ag-chip--running { background: rgba(var(--tint-rgb), .08); color: var(--text-secondary); }
.ag-chip--failed { background: rgba(var(--bad-rgb), .13); color: var(--bad-strong); }
.ag-chip--reversed,
.ag-chip--partially_reversed { background: rgba(var(--warn-rgb), .13); color: var(--warn-strong); }

/* ENTFERNT, nicht ersetzt: .ag-leer — GEFALLEN 21.08.2026 — die Leer-Zeile des Hauses ist EINE Form:
   `.empty-state.empty-state--zeile` + `.empty-state__weg` in docs/design/grund.css. */

/* --- Handy -------------------------------------------------------------- */
/* Eigener Block NACH den Basisregeln (Memory project_css_cascade_mobile).
   Fünf Bestandteile passen auf 390 px nicht nebeneinander: zwei Reihen, jede
   Beschriftung vollständig lesbar. Touch-Boden ≥ 44 px an jeder Zeile. */
@media (max-width: 720px) {
  .ag-karte { padding: 16px; gap: 12px; }
  .ag-rechnung { grid-template-columns: repeat(2, minmax(0, 1fr)); padding: 12px 14px; }
  .ag-teil b { font-size: 18px; }
  .ag-teil i { white-space: normal; }
  .ag-kopf__zeitraum { white-space: normal; }
  .ag-zeile { min-height: 44px; }
  /* Auf 390 px lieber zwei Zeilen als ein abgeschnittenes «Portal ver…» */
  .ag-karte__name, .ag-karte__meta { white-space: normal; }
}
@media (max-width: 1024px), (pointer: coarse) {
  .ag-zeile { min-height: 44px; }
}

/* ============================================================
   Patch-Integration — Namensraum pj-; Quelle: docs/design/patch-projekte.css
   Der Block wird bei Integration als GANZES ersetzt, nie editiert. Neu in W-F.
   ============================================================ */
/* ===========================================================================
   W-F/F5 · Projektportfolio (#/v/projekte) · Projekt-Detail (#/v/projekt/:id)
            · «Nächste autonome Aktion» · Freigabe-Tore als Fläche
   Namensraum: pj- (neu, ausschliesslich)
   Referenz:  docs/design/referenzen/Portaluikomplett/
              «… 13_25_33 (3).png» (Portfolio: breite Projektzeilen mit
              Fortschrittsbalken, Metrik-Chips, «Letzter Fortschritt»,
              Verantwortlichen-Kürzel und «Öffnen»),
              «… 13_25_33 (4).png» (Detail: Brotkrume, Titel mit Zustand und
              Phasenbalken, Tab-Reihe, Panelraster, «Nächste autonome Aktion»
              mit «Jetzt ausführen»),
              «… 13_25_33 (10).png» (Freigabe-Tore als Liste mit Zustand).
   Gesetz:    docs/design/EINHEIT.md — 1.4 drei Knopfstufen, 1.5 Titel 26 px
              ohne Zeichen, 1.6 kein Erklärtext unter dem Titel, 1.8 Avatare
              als Initialen in EINEM Ton, 2.5 deutsch auch für Fachflächen,
              2.10 Datum TT.MM.JJJJ, 4.1 Kachelbauart, 4.3 jede Karte trägt
              ein visuelles Element, 4.7 Zustand als Wort-Chip, 4.9 Tabelle
              (Versal-Spaltenkopf, Zahlen rechts), 4.11 Leerzustand einzeilig,
              4.12 Tabs mit Icon und «Übersicht» zuerst.

   Die EINE Sache, die dieser Block leistet: der Fortschritt ist auf einen
   Blick lesbar, OHNE dass eine Zahl erfunden wird. Ein Projekt ohne
   Arbeitsschritt bekommt keinen Balken auf 0 %, sondern einen leeren Balken
   mit «—» und dem Grund daneben. Genau daran unterscheidet sich diese Fläche
   von jedem Projektwerkzeug, in dem 80 % steht, weil es jemand hingeschrieben
   hat.

   Genutzt aus dem Bestand (NICHT neu definiert): .panel, .gz-panel__titel,
   .gz-kopf, .gz-ic, .gz-avatar, .gz-kachel, .stat/.stat__label/__value/__sub,
   .stat-strip/--auto, .sl-badge, .primary-btn, .ghost-btn, .empty-state,
   .load-error, .admin-page, .field.

   EINBAU: diesen Block unverändert ans Ende von public/style.css hängen.
   Die Handy-Regeln stehen am Schluss des Blocks — nach ihren Basisregeln
   (Memory project_css_cascade_mobile: ein früherer @media-Block wäre für eine
   später definierte Komponente wirkungslos).
   =========================================================================== */

/* Welle 8 «Muster», 18.08.2026 — ENTFERNT, nicht ersetzt: .pj-kopf__zeile (1×).
   Diese Hülle(n) waren eine Nachbildung der EINEN Kopfreihe. Sie kommt jetzt
   aus `components/seiten-kopf.js` (Blatt patch-seitenkopf.css, Abschnitt 1b/2).
   «Ersetzen statt daneben» — Hausregel 7. */

.pj { --gz-feld: 96, 165, 250; }

.pj-kopf__zahl {
  font-size: 12.5px; color: var(--text-tertiary); font-variant-numeric: tabular-nums;
}
/* Der eigene Brotkrumen-Pfad dieser Flaeche ist am 17.08. ERSETZT worden:
   das Ortsschild zeichnet die Schale seither zentral fuer JEDE Flaeche
   (`components/ortsschild.js`, Tabelle `config/bereiche.js`, Gesetz
   docs/BEREICHE.md §3). Die Klassen `.pj-krume` standen danach noch hier und
   trugen nichts mehr — «Ersetzen statt daneben»; entfernt 18.08. */
.pj-kopf__balken { display: flex; align-items: center; gap: 10px; margin-left: auto; }
.pj-kopf__schritte {
  font-size: 12px; color: var(--text-tertiary); font-variant-numeric: tabular-nums;
}

/* Ton des Symbol-Quadrats nach BEDEUTUNG, nicht nach Ort — dieselbe Regel wie
   in der Missionsfläche (.mi-ic--*, style.css:6958). */
.pj-ic--gut { background: var(--accent-soft); color: var(--accent); }
.pj-ic--warn { background: rgba(var(--warn-rgb), .13); color: var(--warn-strong); }
.pj-ic--bad { background: rgba(var(--bad-rgb), .13); color: var(--bad-strong); }
.pj-ic--still { background: rgba(var(--tint-rgb), .08); color: var(--text-tertiary); }

/* --- Zustands-Chip (EINHEIT 4.7: Wort, gerahmt, gemischte Schreibung) ----- */
.pj-chip { font-weight: 600; }
.pj-chip--aktiv { background: var(--accent-soft); color: var(--accent-strong); border-color: rgba(var(--accent-rgb), .32); }
.pj-chip--geplant { background: rgba(var(--tint-rgb), .08); color: var(--text-secondary); }
.pj-chip--pausiert { background: rgba(var(--warn-rgb), .13); color: var(--warn-strong); border-color: rgba(var(--warn-rgb), .3); }
.pj-chip--fertig { background: rgba(var(--tint-rgb), .06); color: var(--text-tertiary); }
.pj-chip--ab { background: rgba(var(--bad-rgb), .1); color: var(--bad-strong); border-color: rgba(var(--bad-rgb), .28); }

/* --- Fortschrittsbalken --------------------------------------------------- */
.pj-balken { display: inline-flex; align-items: center; gap: 10px; min-width: 0; }
.pj-balken__spur {
  position: relative; flex: 1 1 120px; min-width: 80px; height: 6px;
  border-radius: 999px; background: rgba(var(--tint-rgb), .12); overflow: hidden;
}
.pj-balken__spur i {
  position: absolute; inset: 0 auto 0 0; display: block; height: 100%;
  border-radius: 999px; background: var(--accent);
}
.pj-balken em {
  font-style: normal; font-size: 12.5px; font-weight: 650;
  font-variant-numeric: tabular-nums; color: var(--text-primary);
}
/* Kein Balken ohne Quelle (FINISH-STANDARD 7): «—» plus der Grund daneben. */
.pj-balken--leer em { color: var(--text-tertiary); }
.pj-balken__hinweis { font-size: 11.5px; color: var(--text-tertiary); }
.pj-balken--kopf .pj-balken__spur { flex: 0 0 140px; }

/* --- Portfolio-Zeile ------------------------------------------------------ */
.pj-liste { display: grid; gap: 12px; }
.pj-zeile { display: grid; gap: 14px; padding: 16px 18px; }
.pj-zeile__kopf { display: flex; align-items: center; gap: 12px; }
.pj-zeile__name { display: grid; gap: 2px; min-width: 0; flex: 1 1 auto; }
.pj-zeile__name b { font-size: 14.5px; font-weight: 650; letter-spacing: -.01em; }
.pj-zeile__name span {
  font-size: 12px; color: var(--text-tertiary);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.pj-zeile__mitte {
  display: grid; grid-template-columns: minmax(180px, 1fr) auto;
  align-items: center; gap: 16px;
}
.pj-zeile__fortschritt { display: grid; gap: 4px; min-width: 0; }
.pj-zeile__frist { font-size: 11.5px; color: var(--text-tertiary); }
.pj-spaet { color: var(--bad-strong); }

.pj-metriken { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.pj-metrik {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 9px; border-radius: var(--radius-card);
  background: rgba(var(--tint-rgb), .06); border: 1px solid var(--border);
  font-size: 11.5px; color: var(--text-tertiary);
}
.pj-metrik b { font-size: 12.5px; font-weight: 650; color: var(--text-primary); font-variant-numeric: tabular-nums; }
.pj-metrik__ic { display: grid; place-items: center; opacity: .75; }
.pj-metrik__ic svg { width: 13px; height: 13px; }
.pj-metrik--warn b { color: var(--warn-strong); }
.pj-metrik--bad b { color: var(--bad-strong); }

.pj-zeile__fuss {
  display: grid; grid-template-columns: 1fr 1fr auto auto;
  align-items: center; gap: 16px;
  padding-top: 12px; border-top: 1px solid var(--border);
}
.pj-letzt, .pj-naechste { display: grid; gap: 2px; min-width: 0; }
.pj-letzt__label {
  font-size: 11px; letter-spacing: .08em; text-transform: uppercase;
  color: var(--text-tertiary);
}
.pj-letzt__zeile, .pj-naechste__satz {
  font-size: 12px; color: var(--text-secondary);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.pj-letzt__zeile em { font-style: normal; color: var(--text-tertiary); margin-left: 6px; }
.pj-zeile__wer { display: flex; align-items: center; gap: 8px; }
.pj-wer__name { font-size: 12px; color: var(--text-secondary); }
.pj-oeffnen { white-space: nowrap; }

/* --- Detail: Tab-Reihe (EINHEIT 4.12) ------------------------------------- */
.pj-tabs {
  display: flex; align-items: center; gap: 4px; flex-wrap: wrap;
  margin: 4px 0 16px; border-bottom: 1px solid var(--border);
}
.pj-tab {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 9px 12px; min-height: 40px;
  background: none; border: 0; border-bottom: 2px solid transparent;
  color: var(--text-tertiary); font-size: 13px; font-weight: 600; cursor: pointer;
}
.pj-tab:hover { color: var(--text-secondary); }
.pj-tab.is-aktiv { color: var(--text-primary); border-bottom-color: var(--accent); }
.pj-tab__ic { display: grid; place-items: center; }
.pj-tab__ic svg { width: 15px; height: 15px; }

/* --- Detail: Panelraster --------------------------------------------------- */
/* KAESTEN IN EINER REIHE TEILEN IHRE UNTERKANTE (Hausregel 06.09.2026).
   Hier stand `align-items: start`; damit war jeder Kasten nur so hoch wie sein
   Inhalt und die Unterkanten flatterten. Anlass ist die Betreiber-Akte
   («so viele Bereiche versetzt und nicht schoen geordnet», 06.09.), aber der
   Fehler steckte in vier Blaettern zugleich — er wird darum an jeder Quelle
   entfernt, nicht an einer Stelle ueberschrieben. `stretch` ist die Vorgabe
   von Grid; die Zeile faellt ersatzlos weg. Waechter:
   `npm run test:kastenkanten`. */
.pj-raster { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
.pj-panel { padding: 16px 18px; display: grid; gap: 12px; }
.pj-ziel__satz { margin: 0; font-size: 13.5px; line-height: 1.5; color: var(--text-primary); }
.pj-kontext { display: grid; gap: 8px; margin: 0; }
.pj-kontext > div { display: grid; grid-template-columns: 120px 1fr; gap: 10px; align-items: baseline; }
.pj-kontext dt { font-size: 11.5px; color: var(--text-tertiary); }
.pj-kontext dd { margin: 0; font-size: 12.5px; color: var(--text-secondary); }
.pj-hinweis { margin: 0; font-size: 11.5px; color: var(--text-tertiary); }

/* --- Die Karte: nächste autonome Aktion ----------------------------------- */
.pj-aktion { border: 1px solid rgba(var(--accent-rgb), .22); }
.pj-aktion--spaet { border-color: rgba(var(--bad-rgb), .28); }
.pj-aktion__satz { margin: 0; font-size: 15px; font-weight: 650; letter-spacing: -.01em; }
.pj-aktion__zeile { display: flex; flex-wrap: wrap; gap: 8px 16px; margin: 0; font-size: 11.5px; color: var(--text-tertiary); }
.pj-aktion__regel::before { content: '·'; margin-right: 8px; }
.pj-aktion__zahl::before { content: '·'; margin-right: 8px; }
.pj-aktion__grund { margin: 0; font-size: 12px; color: var(--text-secondary); }
.pj-aktion__tun { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.pj-aktion__tuer { font-size: 11.5px; color: var(--text-tertiary); }
.pj-aktion__sperre {
  margin: 0; padding: 10px 12px; border-radius: var(--radius-card);
  background: rgba(var(--warn-rgb), .09); border: 1px solid rgba(var(--warn-rgb), .22);
  font-size: 12.5px; color: var(--warn-strong);
}
.pj-aktion__fall { font-size: 12px; }

.pj-vorschau {
  display: grid; gap: 10px; padding: 12px 14px; border-radius: var(--radius-card);
  background: var(--surface-2); border: 1px solid var(--border);
}
.pj-vorschau__titel { font-size: 12.5px; }
.pj-vorschau__liste { display: grid; gap: 6px; margin: 0; padding: 0; list-style: none; }
.pj-vorschau__liste li { display: flex; gap: 10px; align-items: baseline; font-size: 12px; }
.pj-vorschau__art { color: var(--text-secondary); }
.pj-vorschau__wirkung { color: var(--accent); font-weight: 600; }
.pj-vorschau__grund { color: var(--warn-strong); }
.pj-vorschau__stopp { margin: 0; font-size: 12.5px; color: var(--bad-strong); }
.pj-vorschau__tun { display: flex; gap: 10px; flex-wrap: wrap; }

/* --- Zeitachse ------------------------------------------------------------ */
.pj-zeitachse { display: grid; gap: 10px; margin: 0; padding: 0; list-style: none; }
.pj-zeitachse li {
  display: grid; grid-template-columns: 10px 1fr auto; align-items: baseline;
  gap: 10px; font-size: 12.5px;
}
.pj-zeit__punkt {
  width: 6px; height: 6px; border-radius: 50%; background: var(--accent);
  transform: translateY(-2px);
}
.pj-zeit__wer { color: var(--text-tertiary); font-size: 11.5px; }
.pj-zeitachse em {
  font-style: normal; color: var(--text-tertiary); font-size: 11.5px;
  /* Ohne nowrap bricht «30.07.26, 11:59» hinter dem Komma um und landet unter
     dem Ereignis — die Zeitachse liest sich dann wie eine zweispaltige Liste. */
  white-space: nowrap;
}
/* Die Zeitachse ist die Chronik des ganzen Vorhabens und laeuft ueber beide
   Spalten. Halb so breit neben einer leeren Spalte sah sie aus wie ein Rest. */
.pj-zeit { grid-column: 1 / -1; }
.pj-aktion__fall { color: var(--text-secondary); text-decoration: none; justify-self: start; }
.pj-aktion__fall:hover { color: var(--accent); text-decoration: underline; }

/* --- Tabellen (EINHEIT 4.9, BEREICHE §10) ---------------------------------
   ENTFERNT am 21.08.2026, nicht ersetzt: `.pj-tabelle` als eigene BAUART
   (Rahmen, Kopfzeile, Zellenmasse) und ihre eigene Handy-Fassung weiter unten.
   Die Fläche trägt jetzt `class="team-table pj-tabelle"` in einem
   `.table-wrap` — dieselbe Bauart wie die 63 anderen Tabellen des Hauses.
   `pj-tabelle` überlebt nur als MARKE für die eigenen Spalten, so wie
   `sl-table` am `team-table` hängt; eine Marke ist keine Bauart.
   WAS DAMIT GEWONNEN IST, und zwar am Handy: die alte Handy-Fassung stapelte
   die Zellen OHNE Beschriftung. Auf 390 px standen sechs Werte untereinander,
   und keiner sagte, wofür er steht. Die Haus-Regel
   (`.table-wrap table:has(td[data-label])`) schreibt die Spaltenüberschrift vor
   jeden Wert; `components/tabelle-beschriften.js` setzt sie von selbst.
   ------------------------------------------------------------------------- */
.pj-tabelle a { color: var(--text-primary); text-decoration: none; }
.pj-tabelle a:hover { color: var(--accent); }
.pj-num { text-align: right; font-variant-numeric: tabular-nums; }

/* --- Freigabe-Tore -------------------------------------------------------- */
.pj-tore__zahl {
  margin-left: auto; font-size: 12.5px; font-weight: 650;
  font-variant-numeric: tabular-nums; color: var(--text-secondary);
}
.pj-torliste { display: grid; gap: 6px; margin: 0; padding: 0; list-style: none; }
.pj-tor {
  display: grid; grid-template-columns: 34px 1fr auto; align-items: center; gap: 12px;
  padding: 10px 12px; border-radius: var(--radius-card);
  background: rgba(var(--tint-rgb), .04); border: 1px solid var(--border);
}
.pj-tor__nr {
  display: grid; place-items: center; width: 26px; height: 26px; border-radius: 7px;
  background: rgba(var(--tint-rgb), .08); color: var(--text-tertiary);
  font-size: 11px; font-weight: 650;
}
.pj-tor__text { display: grid; gap: 2px; min-width: 0; }
.pj-tor__text b { font-size: 12.5px; font-weight: 600; color: var(--text-primary); }
.pj-tor__text span {
  font-size: 11.5px; color: var(--text-tertiary);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.pj-tor__stand { font-size: 11.5px; font-weight: 600; color: var(--text-tertiary); white-space: nowrap; }
.pj-tor--gut { border-color: rgba(var(--accent-rgb), .26); }
.pj-tor--gut .pj-tor__nr { background: var(--accent-soft); color: var(--accent); }
.pj-tor--gut .pj-tor__stand { color: var(--accent); }
.pj-tor--bad { border-color: rgba(var(--bad-rgb), .3); }
.pj-tor--bad .pj-tor__nr { background: rgba(var(--bad-rgb), .13); color: var(--bad-strong); }
.pj-tor--bad .pj-tor__stand { color: var(--bad-strong); }
.pj-tor--warn .pj-tor__nr { background: rgba(var(--warn-rgb), .13); color: var(--warn-strong); }
.pj-tor--warn .pj-tor__stand { color: var(--warn-strong); }

/* ENTFERNT, nicht ersetzt: `.pj-leer { margin-top: 8px }` — GEFALLEN 22.08.2026.
   Die letzte der vierzehn Eigennamen-Fassungen, und die harmloseste: reine
   Platzierung. Sie faellt trotzdem, weil ein Name auf `-leer` beim naechsten
   Lesen wieder wie eine eigene Bauart aussieht — und weil 8px auf einem Block
   mit 34px Polsterung keine Aussage sind. Der Kanon steht in grund.css. */

/* ===========================================================================
   Handy und Tablet — NACH den Basisregeln (project_css_cascade_mobile).
   Der Touch-Boden gilt bis 1024 px und für jedes grobe Zeigegerät
   (project_tablet_touch_breakpoint) — sonst fällt die Tab-Reihe genau in die
   Bruchzone 768/1024.
   =========================================================================== */
@media (max-width: 1024px), (pointer: coarse) {
  .pj-tab { min-height: 44px; padding: 11px 12px; }
  .pj-oeffnen { min-height: 44px; display: inline-flex; align-items: center; }
}

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

@media (max-width: 720px) {
  /* Fuenf Kacheln in zwei Spalten lassen eine allein in der letzten Reihe.
     Ohne `start` zieht sie sich auf die Hoehe der Reihe und sieht aus, als
     fehle ihr Inhalt. */
  .pj-kacheln { align-items: start; }
  .pj-zeile { padding: 14px; }
  .pj-zeile__mitte { grid-template-columns: minmax(0, 1fr); }
  .pj-zeile__fuss { grid-template-columns: minmax(0, 1fr); gap: 12px; }
  .pj-kopf__balken { margin-left: 0; width: 100%; }
  .pj-balken--kopf .pj-balken__spur { flex: 1 1 auto; }
  .pj-kontext > div { grid-template-columns: minmax(0, 1fr); gap: 2px; }
  /* Die Tab-Reihe bleibt EINE Reihe und wird gewischt — umgebrochen sähe sie
     auf 390 px wie zwei Navigationen aus. */
  .pj-tabs { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; }
  .pj-tabs::-webkit-scrollbar { display: none; }
  .pj-tab { white-space: nowrap; }
  /* ENTFERNT am 21.08.2026, nicht ersetzt: die eigene Handy-Fassung der
     Tabelle. Sie stapelte die Zellen, schrieb aber keine Beschriftung davor —
     sechs nackte Werte untereinander. Das Haus-Gehäuse `.table-wrap` bringt
     die Kartenform MIT Beschriftung mit (style.css, `td[data-label]::before`),
     und die Zahl bleibt darin rechtsbündig. */
  .pj-tor { grid-template-columns: 30px 1fr; gap: 10px; }
  .pj-tor__stand { grid-column: 2; }
  .pj-metriken { gap: 6px; }
}

/* ============================================================
   Patch-Integration — Namensraum sy-; Quelle: docs/design/patch-systemlage.css
   ============================================================ */
/* =========================================================================
   Systemlage — #/v/systemlage, die Kurven und die EINE Gesundheitszahl.
   Referenz: docs/design/referenzen/Portaluikomplett/13_25_27.png
   («System Performance» + Gesundheit in Prozent). Gesetz: docs/design/EINHEIT.md.

   WAS DIE REFERENZ ZEIGT und was hier daraus wird:
     * Zwei laufende CPU-/Speicher-Kurven → elf Messreihen, jede mit Quelle,
       Spanne und Zahl der Messungen. Was der Prototyp als Maschinenwärme
       zeigt, ist hier das, was diese Datenbank über sich selbst weiss;
       CPU-Prozent gibt es bewusst nicht (Owner-Gate Metrikzugang).
     * Grosse Prozentzahl «System-Gesundheit» → EINE Zahl mit Balken, die sich
       auf ihre vier Teile aufklappt. Jedes Teil trägt seine Rechnung im
       Klartext; ein Prozentwert ohne seine Bestandteile ist genau die Anzeige,
       die niemand ernst nimmt (PROTOTYP-ANALYSE C6).

   DREI TÖNE, KEIN VIERTER: gut ≥ 85 (Türkis), offen ≥ 60 (Bernstein),
   schlecht darunter (Rot). Ein Teil ohne frische Messung bekommt GAR KEINEN
   Ton — es ist nicht «grau schlecht», es ist unbekannt, und das muss anders
   aussehen als eine gemessene Null.

   Bausteine aus style.css werden benutzt, nicht ersetzt: .panel, .panel__head,
   .ghost-btn, .btn, .empty-state, .load-error, .sparkline und die
   .gz-*-Sprache der Zentrale (Symbol-Quadrat, Panel-Titel). Der Orchestrator
   hängt diese Datei an style.css an — sie steht darum NACH allen Basisregeln
   (Memory project_css_cascade_mobile). Präfix sy- für alles Neue.
   ========================================================================= */

/* --- Kopf: Titel links, Zeitfenster rechts ------------------------------- */
.sy-kopf {
  display: flex; flex-wrap: wrap; align-items: center;
  justify-content: space-between; gap: 12px 18px;
}
.sy-fenster { display: flex; flex-wrap: wrap; gap: 6px; }
.sy-fenster__knopf {
  min-height: 32px; padding: 0 12px;
  font-size: 12.5px; font-weight: 550; letter-spacing: 0;
}
.sy-fenster__knopf.is-aktiv {
  border-color: rgba(var(--accent-rgb), .55);
  background: var(--accent-soft);
  color: var(--accent-strong);
}

/* --- Die EINE Zahl ------------------------------------------------------- */
.sy-gesund { padding: 0; margin-bottom: 14px; overflow: hidden; }
.sy-gesund__kopf {
  display: grid; width: 100%;
  grid-template-columns: auto minmax(0, 1fr) minmax(120px, 2fr) auto;
  align-items: center; gap: 14px;
  padding: 16px 18px; min-height: 60px;
  background: none; border: 0; cursor: pointer; text-align: left;
  color: inherit; font: inherit;
}
.sy-gesund__kopf:hover { background: rgba(var(--tint-rgb), .05); }
.sy-gesund__wort { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.sy-gesund__wort i {
  font-style: normal; font-size: 11.5px; font-weight: 600;
  letter-spacing: .06em; text-transform: uppercase; color: var(--text-secondary);
}
/* Die Zahl ist das grösste Element der Fläche — sie ist der Grund, warum es
   diese Fläche gibt (EINHEIT 1.4: eine Hauptzahl je Bildschirm). */
.sy-gesund__zahl {
  font-size: 26px; font-weight: 650; letter-spacing: -.5px;
  font-variant-numeric: tabular-nums; line-height: 1.1;
}
.sy-gesund__zahl--gut { color: var(--good-strong); }
.sy-gesund__zahl--offen { color: var(--warn-strong); }
.sy-gesund__zahl--schlecht { color: var(--bad-strong); }
.sy-gesund__zahl--still { color: var(--text-secondary); }
.sy-gesund__balken,
.sy-teil__balken {
  display: block; height: 6px; border-radius: 3px;
  background: rgba(var(--tint-rgb), .10); overflow: hidden;
}
.sy-teil__fuellung { display: block; height: 100%; border-radius: 3px; }
.sy-teil__fuellung--gut { background: rgb(var(--good-rgb)); }
.sy-teil__fuellung--offen { background: rgb(var(--warn-rgb)); }
.sy-teil__fuellung--schlecht { background: rgb(var(--bad-rgb)); }
.sy-teil__fuellung--still { background: rgba(var(--tint-rgb), .18); }
.sy-gesund__pfeil {
  display: inline-flex; color: var(--text-secondary);
  transition: transform .16s ease;
}
.sy-gesund__pfeil svg { width: 16px; height: 16px; }
.sy-gesund[data-offen="ja"] .sy-gesund__pfeil { transform: rotate(90deg); }

/* --- Die vier Teile ------------------------------------------------------ */
.sy-teile {
  border-top: 1px solid var(--border);
  padding: 4px 18px 16px;
}
.sy-teil {
  display: grid; gap: 4px;
  padding: 12px 0; border-bottom: 1px solid var(--border);
}
.sy-teil:last-of-type { border-bottom: 0; }
.sy-teil__kopf { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
.sy-teil__titel { font-size: 13.5px; font-weight: 600; }
.sy-teil__gewicht {
  font-size: 11.5px; color: var(--text-secondary); font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
/* Die Rechnung steht als Text da, nicht als Erklärung: sie IST der Beleg. */
.sy-teil__rechnung {
  font-size: 12.5px; color: var(--text-primary); font-variant-numeric: tabular-nums;
}
.sy-teil__quelle { font-size: 11.5px; color: var(--text-secondary); }
/* Ein Teil ohne frische Messung ist zurückgenommen — aber nicht versteckt. */
.sy-teil[data-frisch="nein"] { opacity: .62; }
.sy-teil[data-frisch="nein"] .sy-teil__rechnung { color: var(--warn-strong); }
.sy-summe {
  margin: 12px 0 0; padding-top: 12px; border-top: 1px solid var(--border);
  font-size: 12.5px; font-variant-numeric: tabular-nums; color: var(--text-secondary);
}
.sy-hinweis {
  margin: 10px 0 0; font-size: 12.5px; color: var(--warn-strong);
}

/* --- Gewichtung ---------------------------------------------------------- */
.sy-regler { padding: 0; margin-bottom: 14px; overflow: hidden; }
.sy-regler__kopf {
  display: flex; align-items: center; gap: 12px; width: 100%;
  padding: 12px 18px; min-height: 48px;
  background: none; border: 0; cursor: pointer; text-align: left;
  color: inherit; font: inherit; font-size: 13.5px; font-weight: 600;
}
.sy-regler__kopf:hover { background: rgba(var(--tint-rgb), .05); }
.sy-regler__pfeil { margin-left: auto; display: inline-flex; color: var(--text-secondary); transition: transform .16s ease; }
.sy-regler__pfeil svg { width: 16px; height: 16px; }
.sy-regler[data-offen="ja"] .sy-regler__pfeil { transform: rotate(90deg); }
.sy-regler__feld {
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 12px; padding: 4px 18px 16px;
  border-top: 1px solid var(--border);
}
.sy-regler__zeile { display: flex; flex-direction: column; gap: 5px; min-width: 0; }
.sy-regler__zeile span { font-size: 11.5px; color: var(--text-secondary); }
.sy-regler__zeile input {
  min-height: 40px; padding: 0 10px;
  border: 1px solid var(--border); border-radius: var(--radius-card);
  background: var(--surface-inset); color: var(--text-primary);
  font: inherit; font-variant-numeric: tabular-nums;
}
.sy-regler__zeile input:focus-visible {
  outline: 2px solid rgba(var(--accent-rgb), .5); outline-offset: 1px;
}
/* Die drei Grenzen sind keine Gewichte — sie stehen sichtbar abgesetzt. */
.sy-regler__zeile.is-grenze span { color: var(--text-tertiary, var(--text-secondary)); }
.sy-regler__fuss {
  grid-column: 1 / -1; display: flex; align-items: center;
  justify-content: flex-end; gap: 14px;
}
.sy-regler__stand { font-size: 12.5px; color: var(--text-secondary); }
.sy-regler__stand.is-fehler { color: var(--bad-strong); }

/* --- Messreihen ---------------------------------------------------------- */
.sy-stand {
  margin-left: auto; font-size: 11.5px; color: var(--text-secondary);
  font-variant-numeric: tabular-nums;
}
.sy-reihen { display: grid; }
.sy-reihe {
  display: grid;
  grid-template-columns: auto minmax(0, 1.6fr) minmax(78px, auto) minmax(70px, 1fr) minmax(0, auto) minmax(0, auto);
  align-items: center; gap: 14px;
  padding: 12px 18px; border-top: 1px solid var(--border);
}
.sy-reihen .sy-reihe:first-child { border-top: 0; }
.sy-reihe__wort { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.sy-reihe__wort b { font-size: 13.5px; font-weight: 600; }
.sy-reihe__quelle {
  font-style: normal; font-size: 11.5px; color: var(--text-secondary);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.sy-reihe__wert {
  font-size: 15px; font-weight: 600; text-align: right;
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.sy-reihe__spanne,
.sy-reihe__zeit {
  font-size: 11.5px; color: var(--text-secondary);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.sy-spark { display: block; width: 100%; min-width: 60px; height: 26px; color: var(--accent); opacity: .85; }
.sy-spark svg { width: 100%; height: 100%; }
.sy-spark--leer { color: var(--text-secondary); opacity: 1; font-size: 12.5px; line-height: 26px; text-align: center; }
/* ENTFERNT, nicht ersetzt: `.sy-leer { padding: 22px 18px }` — GEFALLEN 22.08.2026.
   Eine Marke neben dem Kanon darf PLATZIEREN, nicht KLEIDEN: 22px statt 34px
   senkrecht und 18px statt 0 waagerecht sind Gestalt, und damit sah der
   Leerzustand hier anders aus als ueberall sonst. Der Kanon in grund.css
   bringt sein Mass mit (`.empty-state { padding: 34px 0 }`; waagerecht faellt
   weg, damit der Satz an der Spaltenkante steht). */

/* --- Handy: 390px --------------------------------------------------------
   Die Reihe faltet sich in zwei Zeilen: Symbol + Name + Wert oben, Kurve und
   Spanne darunter. Die Zahl der Messungen fällt weg — auf 390px ist sie die
   am wenigsten tragende Angabe, und eine gequetschte Kurve wäre schlimmer als
   eine fehlende Nebenzahl (EINHEIT 4.9).                                     */
@media (max-width: 720px) {
  .sy-gesund__kopf {
    grid-template-columns: auto minmax(0, 1fr) auto;
    grid-template-areas: "ic wort pfeil" "balken balken balken";
    row-gap: 10px;
  }
  .sy-gesund__kopf > .gz-ic { grid-area: ic; }
  .sy-gesund__wort { grid-area: wort; }
  .sy-gesund__balken { grid-area: balken; }
  .sy-gesund__pfeil { grid-area: pfeil; }
  .sy-regler__feld { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .sy-reihe {
    grid-template-columns: auto minmax(0, 1fr) auto;
    grid-template-areas: "ic wort wert" "spark spark spanne";
    row-gap: 8px;
  }
  .sy-reihe > .gz-ic { grid-area: ic; }
  .sy-reihe__wort { grid-area: wort; }
  .sy-reihe__wert { grid-area: wert; }
  .sy-spark { grid-area: spark; }
  .sy-reihe__spanne { grid-area: spanne; text-align: right; }
  .sy-reihe__zeit { display: none; }
}
/* --- «Wie steht das Haus» — zwei Kernzeilen -------------------------------
   Karte 01.08., Position 5: «Beweise» (48,2 Handy-Bildschirme) und «Nutzung»
   (29,9) hatten je eine eigene Fläche mit 172 bzw. 78 Tabellenzeilen aus der
   Werkstatt. Ihr Kernsatz lebt jetzt hier, als je EINE Zeile: Wort links, Satz
   darunter, Zustands-Chip rechts, daneben der Owner-Schalter der Messung.
   Dieselbe Zeilen-Anatomie wie .sy-reihe, nur ohne Kurve.                    */
.sy-haus__zeilen { display: grid; }
.sy-haus__zeile {
  display: grid; grid-template-columns: minmax(0, 1fr) auto auto;
  align-items: center; gap: 12px; padding: 11px 0;
}
.sy-haus__zeile + .sy-haus__zeile { border-top: 1px solid var(--border); }
.sy-haus__wort { display: grid; gap: 2px; min-width: 0; }
.sy-haus__wort b { font-size: 13px; font-weight: 600; color: var(--text-primary); }
.sy-haus__satz {
  font-style: normal; font-size: 11.5px; color: var(--text-secondary);
  font-variant-numeric: tabular-nums;
}
.sy-haus__chip { white-space: nowrap; }
.sy-haus__chip--gut { color: var(--good-strong, var(--accent-strong)); }
.sy-haus__chip--offen { color: var(--warn); }
.sy-haus__chip--schlecht { color: var(--bad-strong); }
.sy-haus__chip--still { color: var(--text-tertiary); }
@media (max-width: 720px) {
  .sy-haus__zeile {
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas: "wort chip" "aktion aktion";
    row-gap: 8px;
  }
  .sy-haus__wort { grid-area: wort; }
  .sy-haus__chip { grid-area: chip; }
  .sy-haus__schalt { grid-area: aktion; justify-self: start; }
}

/* Touch-Boden für jede Schaltfläche dieser Seite (Memory
   project_tablet_touch_breakpoint: @720 allein greift die Bruchzone nicht). */
@media (max-width: 1024px), (pointer: coarse) {
  .sy-fenster__knopf { min-height: 44px; padding: 0 14px; }
  .sy-regler__zeile input { min-height: 44px; }
  .sy-haus__schalt { min-height: 44px; display: inline-flex; align-items: center; }
}

/* ============================================================
   Patch-Integration — Namensraum dw-; Quelle: docs/design/patch-dateien.css
   Der Block wird bei Integration als GANZES ersetzt, nie editiert. Neu in W-H.
   ============================================================ */
/* ===========================================================================
   W-H/H3 · Dateien & Workspace (#/v/dateien) — das Register über alle
            Ablagen, Kürzlich, Papierkorb, Projektgrenze, Berechtigungen
   Namensraum: dw- (neu, ausschliesslich)
   Referenz:  docs/design/referenzen/Portaluikomplett/
              «… 13_25_33 (7).png» — Tab-Reihe über dem Inhalt;
              Projektkontext-Wähler links neben dem Grenz-Banner;
              linke Spalte «Repository Roots» als Liste mit Zweitzeile;
              breite Dateitabelle mit Legende darunter;
              rechte Spalte «Berechtigungen & Grenzen» mit Rollen und
              dreistufigen Zugriffsregeln (Haken / Warnung / Verbot).
   Gesetz:    docs/design/EINHEIT.md — 1.5 Titel 26 px ohne Zeichen,
              1.6 kein Erklärtext unter dem Titel, 2.1 du-Anrede,
              2.2 Schweizer ss, 2.10 Datum TT.MM.JJJJ, 4.7 Status als
              Wort-Chip (nie Versalien), 4.9 Tabelle mit Versal-Spaltenkopf
              und rechtsbündigen Zahlen, 4.11 Leerzustand einzeilig,
              4.12 Tab-Reihe mit Icon in gemischter Schreibung.

   Die EINE Sache, die dieser Block leistet: man sieht auf einen Blick, WAS
   sichtbar ist und WARUM — die Ablage, die Projektgrenze und die
   Berechtigung stehen gleichzeitig im Bild wie in der Referenz, statt in
   drei Untermenüs zu liegen. Und eine weggelegte Datei sieht aus wie
   weggelegt: Zeile gedämpft, Restfrist als Chip daneben.

   ABWEICHUNG von EINHEIT 4.12, bewusst: der erste Tab heisst «Alle Dateien»
   und nicht «Übersicht». 4.12 entscheidet den Fall einer Detailfläche, deren
   Tabs verschiedene Sichten AUF EIN Objekt zeigen; hier ist der erste Tab
   der Inhalt selbst, und «Übersicht» wäre ein Wort ohne Gegenstand. Die
   übrigen Forderungen der Regel — Icon, gemischte Schreibung, dieselbe
   Reihe in jedem Tab — gelten unverändert.

   Genutzt aus dem Bestand (NICHT neu definiert): .panel, .gz-panel__titel,
   .gz-kopf, .gz-ic, .stat/.stat__label/__value, .sl-badge,
   .sl-badge--aktiv/--pipeline/--ruhend, .primary-btn, .ghost-btn,
   .empty-state, .load-error, .admin-page, .field, .field--wide, .num,
   .visually-hidden.

   EINBAU: diesen Block unverändert ans Ende von public/style.css hängen.
   Die Handy-Regeln stehen am Schluss des Blocks — nach ihren Basisregeln
   (Memory project_css_cascade_mobile: ein früherer @media-Block wäre für eine
   später definierte Komponente wirkungslos).
   =========================================================================== */

/* Welle 8 «Muster», 18.08.2026 — ENTFERNT, nicht ersetzt: .dw-kopf__zeile (1×).
   Diese Hülle(n) waren eine Nachbildung der EINEN Kopfreihe. Sie kommt jetzt
   aus `components/seiten-kopf.js` (Blatt patch-seitenkopf.css, Abschnitt 1b/2).
   «Ersetzen statt daneben» — Hausregel 7. */

.dw { --gz-feld: var(--good-rgb); }   /* war rohes Türkis; folgt seit 03.09. dem Token */

.dw-kopf__zahl {
  font-size: 12.5px; color: var(--text-tertiary); font-variant-numeric: tabular-nums;
}
.dw-tabs {
  display: flex; align-items: center; gap: 4px; flex-wrap: wrap;
  margin: 4px 0 16px; border-bottom: 1px solid var(--border);
}
.dw-tab {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 9px 12px; min-height: 40px;
  background: none; border: 0; border-bottom: 2px solid transparent;
  color: var(--text-tertiary); font-size: 13px; font-weight: 600; cursor: pointer;
}
.dw-tab:hover { color: var(--text-secondary); }
.dw-tab.is-aktiv { color: var(--text-primary); border-bottom-color: var(--accent); }
.dw-tab__ic { display: grid; place-items: center; }
.dw-tab__ic svg { width: 15px; height: 15px; }
/* Der Zähler am Papierkorb zeigt den gemessenen Stand — ist er null, ist er
   nicht da (EINHEIT 2.14). Die View rendert ihn dann gar nicht erst. */
.dw-tab__zahl {
  min-width: 18px; padding: 0 5px; border-radius: var(--radius-card);
  background: rgba(var(--tint-rgb), .12); color: var(--text-secondary);
  font-size: 11px; font-variant-numeric: tabular-nums; text-align: center;
}

/* --- Projektgrenze: Wähler + Banner in EINER Zeile (Referenz) ------------- */
.dw-grenze {
  display: grid; grid-template-columns: minmax(220px, 300px) 1fr; gap: 16px;
  align-items: center; padding: 14px 16px; margin-bottom: 12px;
}
.dw-grenze.is-aktiv {
  border-left: 2px solid rgb(var(--gz-feld));
  background: linear-gradient(90deg, rgba(var(--gz-feld), .05), transparent 42%);
}
.dw-grenze__wahl { margin: 0; }
.dw-grenze__satz { display: grid; gap: 6px; min-width: 0; }
.dw-grenze__satz p { margin: 0; font-size: 12.5px; color: var(--text-secondary); }
.dw-grenze__satz .sl-badge { justify-self: start; }
.dw-grenze__leer {
  grid-column: 1 / -1; margin: 0; font-size: 12.5px; color: var(--text-tertiary);
}

/* --- Zweispalter: Ablagen und Arbeitsfläche ------------------------------- */
/* Die dritte Spalte der Referenz («Berechtigungen & Grenzen») ist am 01.08.
   gefallen (Karte Position 14): fünf Absätze Hausordnung neben null Dateien.
   Wer welche Ablage sehen darf, steht weiterhin an der Ablage selbst und in
   der Legende unter der Tabelle — ein Werkzeug erklärt sich nicht. */
.dw-raster {
  display: grid; grid-template-columns: fit-content(340px) minmax(0, 1fr);
  gap: 12px; align-items: start;
}
/* 07.09.2026 (Owner-Bild «schrecklich gerendert»): die linke Spalte war fest
   250 px, ihr Inhalt aber nicht — die Knöpfe der Ablagen brechen nicht um
   (Haus-Knopf: white-space nowrap), «Beleg an eine Rechnung hängen» misst
   ~285 px. Der Kasten lief 50–70 px über die Spalte hinaus, die Karten mit ihm,
   ohne Scrollbalken. `fit-content(340px)`: die Spalte ist so breit wie ihr
   schmalster Inhalt verlangt und höchstens 340 px; die Mitte nimmt den Rest. */
/* `minmax(0, 1fr)` ist hier kein Schmuck: ohne die Null-Untergrenze nimmt die
   innere Spalte die Mindestbreite der TABELLE an, und die Vorschau-Karte
   darüber wächst mit — bis unter die rechte Spalte. Genau das ist beim Bau
   passiert (Playwright: «rechte Spalte intercepts pointer events»). */
.dw-raster__mitte {
  display: grid; grid-template-columns: minmax(0, 1fr); gap: 12px; min-width: 0;
}
.dw-panel { padding: 14px 16px; display: grid; gap: 12px; }

/* --- Linke Spalte: die Ablagen -------------------------------------------- */
.dw-ablagen { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }
.dw-ablage > button {
  width: 100%; display: grid; gap: 2px; text-align: left;
  padding: 9px 11px; min-height: 44px;
  background: none; border: 1px solid transparent; border-radius: var(--radius-card);
  color: inherit; cursor: pointer;
}
.dw-ablage > button:hover { border-color: var(--border); }
.dw-ablage.is-aktiv > button {
  border-color: rgba(var(--gz-feld), .45); background: rgba(var(--gz-feld), .07);
}
.dw-ablage b { font-size: 13px; font-weight: 600; color: var(--text-primary); }
.dw-ablage__was, .dw-ablage__zahl {
  font-size: 11.5px; color: var(--text-tertiary);
  overflow: hidden; text-overflow: ellipsis;
}
.dw-ablage__zahl { font-variant-numeric: tabular-nums; }
/* Eine gesperrte Ablage bleibt sichtbar und sagt warum — sie verschwindet
   nicht, sonst wüsste niemand, dass es sie gibt. */
.dw-ablage.is-gesperrt > button { cursor: not-allowed; opacity: .55; }

/* --- Filterzeile ---------------------------------------------------------- */
.dw-filter {
  display: flex; flex-wrap: wrap; align-items: flex-end; gap: 10px 14px;
  padding: 12px 16px;
}
.dw-filter__suche { flex: 1 1 300px; margin: 0; }
.dw-filter__treffer {
  margin: 0 0 6px; font-size: 12px; color: var(--text-tertiary);
  font-variant-numeric: tabular-nums;
}
/* Aktionsleiste über der Tabelle (EINHEIT 4.9): «N ausgewählt» + Aktion +
   Aufheben. Sie erscheint erst mit der ersten Auswahl. */
.dw-stapel {
  flex: 1 1 100%; display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px;
  padding-top: 10px; border-top: 1px solid var(--border);
  font-size: 12.5px; color: var(--text-secondary);
}

/* --- Die Tabelle ---------------------------------------------------------- */
.dw-liste { padding: 0; gap: 0; overflow: hidden; }
.dw-tabelle { width: 100%; border-collapse: collapse; font-size: 12.5px; }
.dw-tabelle th {
  padding: 10px 12px; text-align: left; white-space: nowrap;
  font-size: 11px; font-weight: 650; letter-spacing: .06em; text-transform: uppercase;
  color: var(--text-tertiary); border-bottom: 1px solid var(--border);
}
.dw-tabelle td {
  padding: 10px 12px; vertical-align: top;
  border-bottom: 1px solid var(--border-subtle, var(--border));
  color: var(--text-secondary);
}
.dw-tabelle tr:last-child td { border-bottom: 0; }
.dw-tabelle th.num, .dw-tabelle td.num { text-align: right; font-variant-numeric: tabular-nums; }
.dw-tabelle tr.is-gewaehlt td { background: rgba(var(--gz-feld), .06); }
/* Spaltenbreiten: ohne sie nimmt sich «Sichtbar für» so viel Platz, dass
   Kreditor und Mensch daneben abgeschnitten werden — genau das, was EINHEIT
   4.9 mit «Zweizeilen-Hauptspalte» meint. Angesprochen über data-label, weil
   nth-child bei einer späteren Spalte still auf die falsche zeigt. */
.dw-tabelle__wahl { width: 34px; }
.dw-tabelle td[data-label="Gehört zu"] { min-width: 170px; }
.dw-tabelle td[data-label="Geändert"],
.dw-tabelle td[data-label="Weggelegt"] { width: 150px; }
.dw-tabelle td[data-label="Geändert"] > *:first-child,
.dw-tabelle td[data-label="Weggelegt"] > *:first-child { white-space: nowrap; }
.dw-tabelle__tat { width: 1%; white-space: nowrap; text-align: right; }
.dw-tabelle__tat .ghost-btn { padding: 4px 10px; font-size: 11.5px; min-height: 30px; }
.dw-wahl { display: inline-flex; align-items: center; justify-content: center;
  min-width: 24px; min-height: 24px; cursor: pointer; }
.dw-name {
  padding: 0; background: none; border: 0; cursor: pointer;
  font: inherit; font-weight: 600; color: var(--text-primary); text-align: left;
}
.dw-name:hover { color: var(--accent); }
.dw-tabelle td b { display: block; font-weight: 600; color: var(--text-primary); }
.dw-sub { display: block; font-size: 11.5px; color: var(--text-tertiary); }
/* Zwei Zeilen je Zelle, mehr nicht: eine Tabelle, in der jede Zeile vier
   Zeilen hoch wird, ist keine Tabelle mehr (Referenz: sechs schlanke Zeilen
   nebeneinander). Der ganze Text steht im Titel-Attribut und in der Karte. */
.dw-tabelle td b, .dw-tabelle td .dw-sub {
  overflow: hidden; text-overflow: ellipsis;
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;
}
/* Wer die Datei sehen darf — als kurzer Vermerk UNTER dem Namen, nicht als
   eigene Spalte. Neun Spalten passen auf 1400 px nicht neben zwei
   Seitenspalten; die Referenz führt fünf. Ausgeschrieben steht dieselbe
   Aussage im Titel-Attribut, in der Legende unter der Tabelle, in der Karte
   der Datei und rechts unter «Berechtigungen & Grenzen». */
.dw-sicht {
  display: flex; align-items: center; gap: 5px; margin-top: 3px;
  font-size: 11px; color: var(--text-tertiary);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.dw-sicht__ic { display: grid; place-items: center; flex: 0 0 auto; }
.dw-sicht__ic svg { width: 12px; height: 12px; }
/* Das Projekt steht als dritte Zeile an der Zugehörigkeit — es IST eine
   Zugehörigkeit, keine eigene Grösse. */
.dw-projekt {
  display: inline-block; margin-top: 3px; padding: 1px 7px; border-radius: var(--radius-card);
  background: rgba(var(--gz-feld), .10); color: rgb(var(--gz-feld));
  font-size: 11px; font-weight: 600;
}
/* Ohne Projekt ist kein Projekt: derselbe Chip in Türkis würde eine
   Zugehörigkeit behaupten, die es nicht gibt. */
.dw-projekt--ohne {
  background: rgba(var(--tint-rgb), .10); color: var(--text-tertiary); font-weight: 500;
}
.dw-art {
  display: inline-block; padding: 1px 7px; border-radius: var(--radius-card);
  background: rgba(var(--tint-rgb), .10); color: var(--text-secondary);
  font-size: 11px; font-weight: 600; letter-spacing: .03em;
}
/* Die Legende unter der Tabelle — in der Referenz die Git-Buchstaben, hier
   die Ablagen mit ihrer Sichtbarkeit. */
.dw-legende {
  display: flex; flex-wrap: wrap; gap: 6px 20px;
  margin: 0; padding: 10px 12px; border-top: 1px solid var(--border);
  font-size: 11.5px; color: var(--text-tertiary);
}
.dw-legende b { color: var(--text-secondary); font-weight: 600; }

/* --- Papierkorb: Frist ---------------------------------------------------- */
.dw-frist {
  display: flex; flex-wrap: wrap; align-items: flex-end; gap: 10px 14px;
  padding: 12px; border-top: 1px solid var(--border);
}
.dw-frist p {
  flex: 1 1 260px; margin: 0; font-size: 12px; color: var(--text-tertiary);
}
.dw-frist__feld { margin: 0; width: 130px; }

/* --- Vorschau-Karte ------------------------------------------------------- */
.dw-vorschau { display: grid; gap: 12px; padding: 14px 16px; }
.dw-vorschau__kopf {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
}
.dw-vorschau__kopf h2 { margin: 0; font-size: 15px; font-weight: 650; }
.dw-vorschau__daten {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 8px 16px; margin: 0;
}
.dw-vorschau__daten > div { display: grid; gap: 2px; min-width: 0; }
.dw-vorschau__daten dt {
  font-size: 11px; letter-spacing: .06em; text-transform: uppercase;
  color: var(--text-tertiary);
}
.dw-vorschau__daten dd {
  margin: 0; font-size: 12.5px; color: var(--text-primary); overflow-wrap: anywhere;
}
.dw-vorschau__bild {
  display: grid; place-items: center; min-height: 120px; padding: 10px;
  border: 1px solid var(--border); border-radius: var(--radius-card);
  background: rgba(var(--tint-rgb), .04);
}
.dw-vorschau__bild img, .dw-vorschau__bild video {
  max-width: 100%; max-height: 320px; border-radius: var(--radius-card);
}
.dw-vorschau__leer { font-size: 12.5px; color: var(--text-tertiary); }

/* --- Handy und Tablet ----------------------------------------------------- */
@media (max-width: 1180px) {
  .dw-raster { grid-template-columns: minmax(0, 1fr); }
  .dw-raster__links { order: 2; }
  .dw-raster__mitte { order: 1; }
  .dw-ablagen { grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); display: grid; }
}
@media (max-width: 720px) {
  .dw-tabs { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; }
  .dw-tabs::-webkit-scrollbar { display: none; }
  .dw-tab { white-space: nowrap; }
  .dw-grenze { grid-template-columns: minmax(0, 1fr); }
  /* Eine Neun-Spalten-Tabelle ist auf 390 px unlesbar, und Querlauf verbietet
     sich (feedback_mobile_pwa_mandatory). Jede Zeile wird zum Block, jede
     Zelle trägt ihre Beschriftung aus data-label. */
  .dw-tabelle, .dw-tabelle tbody, .dw-tabelle tr, .dw-tabelle td { display: block; width: 100%; }
  .dw-tabelle thead { display: none; }
  .dw-tabelle tr {
    padding: 10px 12px; border-bottom: 1px solid var(--border);
  }
  .dw-tabelle tr:last-child { border-bottom: 0; }
  /* Beschriftung ÜBER dem Wert, nicht daneben: eine 110-px-Spalte für das
     Wort presst den Wert in den Rest und schneidet ihn ab («Hinzugefügt ·
     Alm…»). Auf 390 px ist Untereinander die einzige Anordnung, die den
     ganzen Wert zeigt. */
  .dw-tabelle td { display: block; padding: 5px 0; border: 0; }
  .dw-tabelle td::before {
    content: attr(data-label); display: block; margin-bottom: 2px;
    font-size: 11px; letter-spacing: .06em; text-transform: uppercase;
    color: var(--text-tertiary);
  }
  .dw-tabelle td.num { text-align: left; }
  /* Auf dem Handy wird nichts geklemmt — Platz nach unten ist da. */
  .dw-tabelle td b, .dw-tabelle td .dw-sub {
    -webkit-line-clamp: none; display: block; overflow: visible; white-space: normal;
  }
  .dw-tabelle td[data-label="Geändert"] > *:first-child,
  .dw-tabelle td[data-label="Weggelegt"] > *:first-child { white-space: normal; }
  .dw-tabelle td[data-label="Gehört zu"],
  .dw-tabelle td[data-label="Geändert"],
  .dw-tabelle td[data-label="Weggelegt"] { width: auto; min-width: 0; }
  .dw-sicht { white-space: normal; }
  /* Auswahl und Aktion tragen ihre Beschriftung nicht sichtbar — sie sind
     selbsterklärend, und zwei leere Wortzeilen je Datei sind Lärm. */
  .dw-tabelle td.dw-tabelle__wahl::before,
  .dw-tabelle td.dw-tabelle__tat::before { content: none; }
  .dw-tabelle__tat .ghost-btn { width: 100%; }
  .dw-tabelle__wahl, .dw-tabelle__tat { width: auto; text-align: left; }
  .dw-vorschau__daten { grid-template-columns: minmax(0, 1fr); }
}
/* Touch-Boden: jede Tap-Fläche hält 44 px, auch in der Tablet-Bruchzone
   (Memory project_tablet_touch_breakpoint — @720px allein greift bei 768 und
   1024 px nicht). */
@media (max-width: 1024px), (pointer: coarse) {
  .dw-tab { min-height: 44px; }
  .dw-name { min-height: 44px; display: inline-flex; align-items: center; }
  .dw-wahl { min-width: 44px; min-height: 44px; }
  .dw-ablage > button { min-height: 48px; }
  .dw-tabelle__tat .ghost-btn { min-height: 44px; }
}

/* Connected document workspace: files and their business context, one surface. */
.files-workspace { container-type:inline-size; container-name:files; --files-line:var(--border); --files-muted:var(--text-secondary); max-width:1600px; margin:0 auto; min-width:0; color:var(--text-primary); }
.files-workspace :is(h1,h2,p) { margin:0; }
.files-workspace :is(button,a,input,select,summary):focus-visible { outline:2px solid var(--accent); outline-offset:3px; }
.files-workspace :is(button,input,select) { min-height:42px; font:inherit; }
.files-workspace :is(button,a,small,dd,h2) { overflow-wrap:anywhere; }
.files-heading,.files-upload>header,.files-preview>header { display:flex; align-items:center; justify-content:space-between; gap:20px; }
.files-heading { margin:0 0 24px; }
.files-heading h1 { font-size:28px; font-weight:650; letter-spacing:-.025em; line-height:1.2; }
.files-heading p { margin-top:7px; font-size:14px; color:var(--files-muted); }
.files-heading .ico,.files-context .ico { width:18px; height:18px; flex:none; }
.files-heading .primary-btn { display:inline-flex; align-items:center; gap:9px; }
.files-tabs { display:flex; flex-wrap:wrap; gap:6px; border-bottom:1px solid var(--files-line); margin-bottom:18px; padding-bottom:8px; }
.files-tabs button { padding:9px 14px; border:0; border-radius:8px; background:transparent; color:var(--files-muted); cursor:pointer; }
.files-tabs button:hover { background:var(--surface-hover); color:var(--text-primary); }
.files-tabs button[aria-pressed=true] { color:var(--accent-strong); background:var(--accent-soft); font-weight:600; }
.files-tabs span { font-variant-numeric:tabular-nums; }
.files-filters { display:flex; flex-wrap:wrap; align-items:center; gap:10px; margin-bottom:18px; }
.files-filters>label { min-width:0; }
.files-search { display:flex; flex:1 1 280px; gap:9px; align-items:center; padding:0 12px; border:1px solid var(--files-line); background:var(--surface-inset); border-radius:8px; }
.files-search .ico { flex:none; width:19px; height:19px; color:var(--files-muted); }
.files-search input { border:0; padding:10px 0; width:100%; background:transparent; color:inherit; outline-offset:4px; }
.files-filters select,.files-upload select { max-width:100%; border:1px solid var(--files-line); border-radius:8px; color:var(--text-primary); background:var(--surface); padding:8px 32px 8px 12px; }
.files-layout { display:grid; grid-template-columns:minmax(0,1.25fr) minmax(330px,.9fr); gap:24px; align-items:start; }
.files-index { min-width:0; }
.files-index [data-files-list] { max-height:max(360px,calc(100dvh - 285px)); overflow:auto; overscroll-behavior:contain; scrollbar-gutter:stable; }
.files-index .files-list-head { position:sticky; top:0; z-index:1; background:var(--surface); }
.files-list { list-style:none; margin:0; padding:0; }
.files-list>li { position:relative; }
.files-list>li:has(.files-select)>.files-row { padding-left:42px; }
.files-workspace .files-select { position:absolute; left:10px; top:50%; transform:translateY(-50%); width:18px; height:18px; min-height:18px; margin:0; accent-color:var(--accent); }
.files-selection:not([hidden]) { display:flex; flex-wrap:wrap; align-items:center; gap:12px; padding:12px; margin-bottom:16px; background:var(--accent-soft); border-radius:8px; font-size:14px; }
.files-rules { margin-top:25px; padding-top:16px; border-top:1px solid var(--border); font-size:13px; color:var(--text-secondary); }
.files-rules summary { cursor:pointer; }
.files-rules p { margin:12px 0; max-width:70ch; }
.files-list-head,.files-row { display:grid; grid-template-columns:minmax(0,1.45fr) minmax(0,1fr) 82px; column-gap:16px; align-items:center; }
.files-list-head { font-size:12px; color:var(--files-muted); padding:12px; border-bottom:1px solid var(--files-line); }
.files-row { width:100%; padding:15px 12px; text-align:left; border:0; border-bottom:1px solid var(--files-line); color:inherit; background:transparent; cursor:pointer; transition:background-color 160ms ease-out; border-radius:0; }
.files-row:hover { background:var(--surface-hover); }
.files-row[aria-pressed=true] { background:var(--accent-soft); color:var(--accent-strong); }
.files-row-name { display:flex; gap:12px; min-width:0; align-items:center; }
.files-row-name>.ico { width:24px; height:24px; flex:none; color:var(--files-muted); }
.files-row-name>span { min-width:0; }
.files-row b { font-weight:550; font-size:14px; display:block; line-height:1.45; }
.files-row small { display:block; font-size:12px; color:var(--files-muted); margin-top:4px; line-height:1.5; }
.files-row-context { font-size:13px; line-height:1.45; min-width:0; }
.files-row time { font-size:12px; color:var(--files-muted); font-variant-numeric:tabular-nums; }
.files-preview { position:sticky; top:20px; min-width:0; background:var(--surface); border:1px solid var(--files-line); border-radius:14px; padding:20px; overflow:hidden; }
.files-preview>header { align-items:start; margin-bottom:16px; gap:12px; }
.files-preview h2,.files-upload h2 { font-size:17px; line-height:1.45; font-weight:600; }
.files-preview>header button { flex:none; min-width:40px; padding:8px; }
.files-preview .ico { width:20px; height:20px; }
.files-preview-empty { padding:52px 15px; text-align:center; max-width:42ch; margin:auto; }
.files-preview-empty>.ico { width:38px; height:38px; margin-bottom:18px; color:var(--accent-strong); }
.files-preview-empty p { margin-top:12px; font-size:14px; line-height:1.6; color:var(--files-muted); }
.files-context { display:flex; flex-wrap:wrap; gap:10px; margin-bottom:18px; align-items:center; font-size:13px; }
.files-context p { flex-basis:100%; color:var(--files-muted); }
.files-context a { display:inline-flex; align-items:center; gap:8px; }
.files-preview video,.files-preview img { max-width:100%; height:auto; }
.files-preview .private-document-preview__paper { max-height:65vh; }
.files-preview .private-document-preview__tools { gap:6px; font-size:12px; }
.files-preview .private-document-preview__tools button { font-size:12px; padding:6px 9px; }
.files-metadata { border-top:1px solid var(--files-line); margin-top:18px; padding-top:12px; font-size:13px; }
.files-metadata summary { cursor:pointer; min-height:32px; }
.files-metadata dl { margin:12px 0; }
.files-metadata dl>div { display:grid; grid-template-columns:100px minmax(0,1fr); gap:12px; margin-bottom:10px; }
.files-metadata dt { color:var(--files-muted); }
.files-metadata dd { margin:0; }
.files-empty,.files-loading { padding:50px 20px; text-align:center; color:var(--files-muted); }
.files-empty h2 { font-size:17px; color:var(--text-primary); margin:15px 0 8px; }
.files-empty .ico { width:30px; height:30px; }
.files-empty p { margin:0 auto 18px; max-width:42ch; line-height:1.6; }
[data-files-pages] { display:flex; flex-wrap:wrap; align-items:center; justify-content:space-between; gap:10px; padding-top:16px; font-size:13px; }
[data-files-pages]>div { display:flex; gap:8px; }
[data-files-error]:not([hidden]) { padding:16px; margin-bottom:20px; border:1px solid var(--danger); border-radius:8px; color:var(--danger); }
.files-upload { padding:22px; background:var(--surface); border:1px solid var(--files-line); border-radius:14px; margin-bottom:22px; }
.files-upload>header { margin-bottom:16px; }
.files-upload label { display:flex; gap:12px; flex-wrap:wrap; align-items:center; margin:12px 0; }
.files-upload .document-work { margin-bottom:0; }
@media (max-width:1100px) { .files-layout { grid-template-columns:minmax(0,1fr) minmax(300px,.9fr); gap:16px; } .files-list-head,.files-row { grid-template-columns:minmax(0,1.4fr) minmax(0,1fr); gap:12px; } .files-list-head>span:last-child,.files-row time { display:none; } }
@container files (max-width:840px) { .files-layout { grid-template-columns:minmax(0,1fr); } .files-preview { position:static; order:-1; scroll-margin-top:16px; } .files-preview:has(.files-preview-empty) { display:none; } .files-layout:has(.files-preview>header) .files-index { display:none; } .files-heading { align-items:flex-start; gap:12px; } .files-heading h1 { font-size:24px; } .files-heading .primary-btn { font-size:13px; padding:9px 11px; } .files-filters select { width:100%; } .files-filters>label:not(.files-search) { flex:1 1 150px; } .files-tabs { gap:3px; } .files-tabs button { font-size:13px; padding:9px 10px; } .files-preview { padding:16px; } }
@media (prefers-reduced-motion:reduce) { .files-row { transition:none; } }

.private-document-preview [data-document-download][hidden] { display:none; }
.private-document-preview__download { display:inline-flex; margin-top:14px; }
.private-document-preview__source { white-space:pre-wrap; overflow-wrap:anywhere; font:13px/1.6 var(--font-mono,monospace); margin:0; padding:12px; }
.document-work__formats { margin-top:12px; font-size:12px; color:var(--text-secondary); }
@container files (max-width:840px) {
 .files-list-head,.files-row { grid-template-columns:minmax(0,1.5fr) minmax(0,1fr); }
 .files-list-head>span:last-child,.files-row time { display:none; }
 .files-filters .files-search { flex-basis:100%; }
 .files-preview .private-document-preview__paper { max-height:65dvh; }
}

/* ============================================================
   Patch-Integration — Namensraum po-; Quelle: docs/design/patch-post.css
   Der Block wird bei Integration als GANZES ersetzt, nie editiert.
   Post — Ein- und Ausgang an einem Ort, Sichtung zuerst. Neu in W-H/H4.
   ============================================================ */
/* ============================================================
   W-H/H4 · Post (Ein- und Ausgang) — #/v/mail
   Namensraum: po-  (innen, LoopX13 · Agent OS)
   Referenz:   die Mailflächen der Portal-Referenzen zeigen eine Liste mit
               Betreff, Absender, Zustand und Zeit. Übernommen ist die Struktur,
               nicht die Dekoration.
   Bewusst NICHT übernommen:
     · farbige Absender-Avatare → EINHEIT 1.8 (Initialen im neutralen Kreis)
       und hier gar keine: eine Mailadresse ist keine Person im System.
     · Vorschaubild / HTML-Vorschau der Mail → fremder Inhalt wird NIE als
       Markup gezeigt. Es steht ein escapeter Textauszug, mehr nicht.
   Gesetz:   docs/design/EINHEIT.md — 1.3 EIN Akzent Türkis · 1.5 Titel 26 px
             ohne Zeichen · 1.6 kein Erklärtext unter dem Titel · 2.6 Schweizer
             Zahlen · 2.10 Datum TT.MM.JJJJ · 4.1 Kachelbauart · 4.7 Zustand
             als gerahmter Wort-Chip · 4.11 Leerzustand einzeilig ·
             4.12 Tabs mit Icon.
   Genutzt aus dem Bestand (NICHT neu definiert): .panel-row,
             .panel-row__main, .stat/.stat__label/.stat__value/.stat__sub,
             .stat-strip/--auto, .gz-kopf, .gz-ic, .gz-kachel, .gz-kacheln,
             .badge, .ghost-btn, .empty-state, .load-error.
   Integration: als Block ans Ende von public/style.css hängen.
   ============================================================ */

/* Welle 8 «Muster», 18.08.2026 — ENTFERNT, nicht ersetzt: .po-kopf__zeile (1×).
   Diese Hülle(n) waren eine Nachbildung der EINEN Kopfreihe. Sie kommt jetzt
   aus `components/seiten-kopf.js` (Blatt patch-seitenkopf.css, Abschnitt 1b/2).
   «Ersetzen statt daneben» — Hausregel 7. */

.po-kopf { margin-bottom: 16px; }
.po-kopf__zahl {
  font-size: 12.5px; color: var(--text-tertiary);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}

/* --- Tabs (EINHEIT 4.12): Icon, gemischte Schreibung, gleiche Reihe --- */
.po-tabs {
  display: flex; gap: 4px; margin: 18px 0 12px;
  border-bottom: 1px solid var(--border); flex-wrap: wrap;
}
.po-tab {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 9px 14px; min-height: 40px;
  background: none; border: 0; border-bottom: 2px solid transparent;
  color: var(--text-secondary); font: inherit; font-size: 13px;
  cursor: pointer; border-radius: var(--radius-card) var(--radius-card) 0 0;
}
.po-tab:hover { color: var(--text-primary); background: rgba(var(--tint-rgb), .06); }
.po-tab--aktiv { color: var(--text-primary); border-bottom-color: var(--accent); }
.po-tab__ic { display: inline-flex; width: 15px; height: 15px; }
.po-tab__ic svg { width: 100%; height: 100%; }
.po-tab__zahl {
  font-style: normal; font-size: 11.5px; font-variant-numeric: tabular-nums;
  padding: 1px 6px; border-radius: var(--radius-badge);
  background: rgba(var(--accent-rgb), .14); color: var(--accent);
}

/* --- Die Liste: Panel-Rows, keine Tabelle --- */
.po-liste { display: flex; flex-direction: column; gap: 1px; }
.po-zeile {
  display: grid; align-items: start; gap: 10px 14px;
  grid-template-columns: minmax(0, 1fr) minmax(0, 210px) 132px 118px;
  padding: 12px 2px;
}
.po-zeile__wer { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.po-zeile__betreff {
  font-size: 13.5px; font-weight: 600; line-height: 1.35;
  overflow-wrap: anywhere;
}
.po-zeile__meta { font-size: 12px; color: var(--text-tertiary); overflow-wrap: anywhere; }
.po-zeile__auszug {
  font-size: 12px; color: var(--text-secondary); line-height: 1.45;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
}
.po-zeile__fehler { font-size: 12px; color: var(--bad); overflow-wrap: anywhere; }
.po-zeile__zeit {
  font-size: 12px; color: var(--text-tertiary);
  font-variant-numeric: tabular-nums; white-space: nowrap; text-align: right;
}

/* --- Der Bezug: Nummer gross, Grund klein darunter --- */
.po-bezug { display: flex; flex-direction: column; gap: 2px; min-width: 0; font-size: 12.5px; }
.po-bezug b { font-variant-numeric: tabular-nums; }
.po-bezug__grund {
  font-style: normal; font-size: 11.5px; color: var(--text-tertiary); line-height: 1.35;
}
.po-bezug--offen { color: var(--text-tertiary); }

/* --- Zustands-Chip: gerahmt, gemischte Schreibung (EINHEIT 4.7) --- */
.po-chip {
  border: 1px solid var(--border); border-radius: var(--radius-badge);
  padding: 2px 9px; font-size: 11.5px; white-space: nowrap;
  justify-self: start; background: none;
}
.po-chip--aktiv  { color: var(--accent); border-color: rgba(var(--accent-rgb), .45); }
.po-chip--offen  { color: var(--warn); border-color: rgba(var(--warn-rgb), .45); }
.po-chip--warn   { color: var(--bad); border-color: rgba(var(--bad-rgb), .45); }
.po-chip--ruhend { color: var(--text-tertiary); }

/* --- Die Handgriffe der Sichtung. Sie stehen in der Zeile, nicht in einem
       Dialog: ein Fenster für zwei Felder ist ein Umweg. --- */
.po-hand {
  grid-column: 1 / -1; display: flex; gap: 8px; align-items: center;
  flex-wrap: wrap; padding-top: 4px;
}
.po-hand__feld {
  flex: 0 1 200px; min-height: 40px; padding: 8px 10px;
  background: var(--surface-2); color: var(--text-primary);
  border: 1px solid var(--border); border-radius: var(--radius-card);
  font: inherit; font-size: 13px; font-variant-numeric: tabular-nums;
}
.po-hand__feld:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.po-hand__knopf { min-height: 40px; }

/* --- Handy: die Spalten werden zu Zeilen, Tippflächen bleiben ≥44 px.
       Breakpoint 1024/coarse statt 720 — Memory project_tablet_touch_breakpoint. */
@media (max-width: 1024px), (pointer: coarse) {
  .po-zeile { grid-template-columns: minmax(0, 1fr); gap: 8px; padding: 14px 2px; }
  .po-zeile__zeit { text-align: left; }
  .po-tab { min-height: 44px; }
  .po-hand__feld, .po-hand__knopf { min-height: 44px; }
  .po-hand__feld { flex: 1 1 100%; }
}

/* ============================================================
   Patch-Integration — Namensraum wz-; Quelle: docs/design/patch-werkzeuge.css
   Der Block wird bei Integration als GANZES ersetzt, nie editiert.
   Werkzeuge — Gesundheit, Laufzeit, Kosten und Begruendung. Neu in W-H/H4.
   ============================================================ */
/* ============================================================
   W-H/H4 · Werkzeuge — #/v/werkzeuge
   Namensraum: wz-  (innen, LoopX13 · Agent OS)
   Referenz:   docs/design/referenzen/Portaluikomplett/
               «… 13_25_33 (8).png» — «System & Tools / Capability Router»:
               vier KPI, Tab-Leiste, Tooltabelle mit Status, Health %, Latenz,
               Kosten/1K, Aufrufe (30 T), rechts «Routing-Entscheidung erklärt».
   Bewusst NICHT übernommen (der Prototyp erfindet dort, was es nicht gibt):
     · farbige Marken-Logos (Claude, Codex, GitHub, PostgreSQL) → EINHEIT 1.7:
       ein monochromes Strich-Set; der Betreiber steht als WORT in der Zeile.
     · «Health 98 %» als nackte Zahl → Zähler/Nenner mit Herkunftssatz, und nur
       dort, wo das Protokoll auch Misserfolge kennt (FINISH-STANDARD 7).
     · «Kosten/1K € 0.03» → es gibt keine Kostenquelle; statt einer Zahl steht
       der Satz, warum keine da ist. Und CHF, nie € (EINHEIT 2.8).
     · «Match 94 %» in der Routing-Erklärung → eine Entscheidung ist kein
       Messwert. Hier stehen zwei Sätze: warum dieses Werkzeug, und was die
       geprüfte Alternative war.
     · «Routing-Modus: Smart» mit «Konfigurieren» → es gibt keinen Router, der
       zwischen Werkzeugen wählt. Ein Knopf dafür wäre eine tote Tür.
   Gesetz:   docs/design/EINHEIT.md — 1.3 EIN Akzent Türkis · 1.5 Titel 26 px
             ohne Zeichen · 1.6 kein Erklärtext unter dem Titel · 2.6 Schweizer
             Zahlen · 4.1 Kachelbauart · 4.3 visuelles Element nur mit Quelle ·
             4.7 Zustand als gerahmter Wort-Chip · 4.11 Leerzustand einzeilig.
   Genutzt aus dem Bestand (NICHT neu definiert): .panel, .stat__bar,
             .stat/.stat__label/.stat__value/.stat__sub, .stat-strip/--auto,
             .gz-kopf, .gz-ic, .gz-kachel, .gz-kacheln, .badge, .empty-state,
             .load-error.
   Integration: als Block ans Ende von public/style.css hängen.
   ============================================================ */

/* Welle 8 «Muster», 18.08.2026 — ENTFERNT, nicht ersetzt: .wz-kopf__zeile (1×), .wz-kopf__steuer (1×).
   Diese Hülle(n) waren eine Nachbildung der EINEN Kopfreihe. Sie kommt jetzt
   aus `components/seiten-kopf.js` (Blatt patch-seitenkopf.css, Abschnitt 1b/2).
   «Ersetzen statt daneben» — Hausregel 7. */

.wz-kopf { margin-bottom: 16px; }
.wz-kopf__zeitraum {
  font-size: 12.5px; color: var(--text-tertiary);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}

/* Karten statt Tabelle: eine Zeile trägt hier zwei Sätze Begründung — in einer
   Tabellenzelle wäre das eine Textwand mit drei Wörtern Breite. */
.wz-liste {
  display: grid; gap: 12px;
  grid-template-columns: repeat(auto-fill, minmax(360px, 1fr));
}
.wz-karte { display: flex; flex-direction: column; gap: 10px; padding: 16px; }
.wz-karte__kopf { display: flex; align-items: center; gap: 10px; }
.wz-karte__ic { flex: 0 0 auto; }
.wz-karte__wer { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1 1 auto; }
.wz-karte__name { font-size: 14px; font-weight: 650; }
.wz-karte__meta { font-size: 12px; color: var(--text-tertiary); overflow-wrap: anywhere; }

.wz-chip {
  border: 1px solid var(--border); border-radius: var(--radius-badge);
  padding: 2px 9px; font-size: 11.5px; white-space: nowrap; background: none;
}
.wz-chip--aktiv  { color: var(--accent); border-color: rgba(var(--accent-rgb), .45); }
.wz-chip--warn   { color: var(--warn); border-color: rgba(var(--warn-rgb), .45); }
.wz-chip--ruhend { color: var(--text-tertiary); }
/* Abnahmebericht 01.08. (St. 78): «Ausfall» (mehr Fehler als Erfolge) trägt
   Rot — vorher trug 0,3 % Erfolgsquote dieselbe Warnfarbe wie 96 %. */
.wz-chip--rot    { color: var(--bad); border-color: rgba(var(--bad-rgb), .45); }

.wz-zweck { font-size: 12.5px; color: var(--text-secondary); line-height: 1.5; margin: 0; }

/* Die Bestandteile: Zahl über Wort. Zwei davon sind die Rechnung, aus der
   die Quote entsteht — sie stehen auch dann da, wenn es keine Quote gibt. */
.wz-rechnung { display: flex; gap: 18px; flex-wrap: wrap; }
.wz-teil { display: flex; flex-direction: column; gap: 1px; }
.wz-teil b { font-size: 19px; font-weight: 650; font-variant-numeric: tabular-nums; }
.wz-teil i { font-style: normal; font-size: 11.5px; color: var(--text-tertiary); }
.wz-teil--warn b { color: var(--warn); }

.wz-letzte {
  display: flex; gap: 16px; flex-wrap: wrap; margin: 0;
  font-size: 11.5px; color: var(--text-tertiary);
}
.wz-letzte b { font-variant-numeric: tabular-nums; color: var(--text-secondary); font-weight: 500; }

/* Die Gesundheit. Der Balken erscheint nur mit Zähler und Nenner. */
.wz-gesund { display: flex; flex-direction: column; gap: 5px; }
.wz-gesund__kopf { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
.wz-gesund__zahl { font-size: 13px; font-weight: 600; font-variant-numeric: tabular-nums; }
.wz-gesund__prozent { font-size: 13px; color: var(--accent); font-variant-numeric: tabular-nums; }
.wz-gesund__bar { width: 100%; }
.wz-gesund__satz, .wz-gesund--leer {
  margin: 0; font-size: 11.5px; color: var(--text-tertiary); line-height: 1.5;
}

/* Laufzeit und Kosten teilen eine Bauart: Label, Wert, Herkunftssatz. Wo der
   Wert fehlt, rückt der Satz an seine Stelle — nie eine leere Zeile. */
.wz-mess {
  display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; margin: 0;
  font-size: 12px; color: var(--text-secondary); line-height: 1.5;
}
.wz-mess__label {
  font-size: 11px; letter-spacing: .06em; text-transform: uppercase;
  color: var(--text-tertiary); flex: 0 0 auto;
}
.wz-mess__wert { font-size: 15px; font-weight: 650; font-variant-numeric: tabular-nums; }
.wz-mess__neben { font-size: 11.5px; color: var(--text-tertiary); font-variant-numeric: tabular-nums; }
.wz-mess__satz { flex: 1 1 100%; font-style: normal; font-size: 11.5px; color: var(--text-tertiary); }
.wz-mess--leer { color: var(--text-tertiary); font-size: 11.5px; }

/* Die Routing-Begründung — der Ersatz für «Match 94 %». */
.wz-warum {
  display: flex; flex-direction: column; gap: 3px;
  border-top: 1px solid var(--border); padding-top: 10px; margin-top: auto;
}
.wz-warum__label {
  font-size: 11px; letter-spacing: .06em; text-transform: uppercase;
  color: var(--text-tertiary);
}
.wz-warum p { margin: 0 0 6px; font-size: 12px; line-height: 1.55; color: var(--text-secondary); }
.wz-warum__alt { color: var(--text-tertiary); }
.wz-quelle { font-size: 11px; color: var(--text-tertiary); font-variant-numeric: tabular-nums; }

@media (max-width: 1024px), (pointer: coarse) {
  .wz-liste { grid-template-columns: minmax(0, 1fr); }
}

/* ============================================================
   Patch-Integration — Namensraum ao-; Quelle: docs/design/patch-chat.css
   Der Block wird bei Integration als GANZES ersetzt, nie editiert.
   Chat-Fläche nach Owner-Referenz (Team Chat, Welle 31.07.) — steht NACH
   dem ao-Basisblock, damit die Kaskade die neue Anordnung gewinnt.
   ============================================================ */
/* =========================================================================
   CHAT · Namensraum ao- — EIN NAMENSRAUM, EIN BLATT (zusammengelegt 21.08.2026)

   Bis zum 21.08. wurde dieser Namensraum von ZWEI vollstaendigen Blaettern
   bedient: docs/design/patch-agentos-chat.css (315 Zeilen, die Grundlage vom
   28.07.) und dieses Blatt (521 Zeilen, der Anatomie-Pass vom 31.07.). 41
   Selektoren standen in beiden, 61 nur im aelteren — und wirkten weiter, weil
   nichts sie ersetzte (Befund docs/BEFUNDE-2026-08-17.md:1011).

   WARUM DAS AELTERE BLATT NICHT WEGFIEL, SONDERN HIER STEHT: es war nicht
   tot. Der Anatomie-Pass ist ein DIFFERENZ-Pass — er setzt je Selektor nur
   die Eigenschaften, die er aendert. Nachgemessen am 21.08.: von den 41
   gemeinsamen Selektoren ist KEIN EINZIGER vollstaendig ueberschrieben.
   Beispiel `.ao-karte`: die Grundlage setzt display/gap/margin/padding/
   background/border/border-radius, der Pass nur margin-top/padding/gap/
   background/border-color/border-radius. Ohne die Grundlage verliert die
   Auftragskarte ihr `display: grid` und ihre Rahmenbreite.

   Also ist die Aufloesung ein ZUSAMMENLEGEN, kein Weglassen. Die Reihenfolge
   ist zeichengenau die der bisherigen Kaskade:

     ABSCHNITT A   die Grundlage (bis 21.08. docs/design/patch-agentos-chat.css)
     ABSCHNITT B   der Anatomie-Pass vom 31.07., der sie korrigiert

   BEWIESEN, NICHT BEHAUPTET: `node scripts/_ein_blatt_test.mjs` baut
   denselben Bildschirm zweimal — einmal mit dem style.css von vorher, einmal
   mit dem von nachher — und vergleicht fuer JEDES Element JEDE errechnete
   Eigenschaft. 1868 Elemente in 12 Lagen (sechs Zustaende x 1400px/390px),
   kein einziger Unterschied.

   Rueckweg: `git show ef2ed08:docs/design/patch-agentos-chat.css`
             `git show ef2ed08:docs/design/patch-chat.css`
   Kopie im Lager: ~/.claude-lager/loopx13/ein-blatt-2026-08-21/

   WER HIER ETWAS AENDERT: das Blatt ist die Quelle, public/style.css das
   Erzeugnis. Nach jeder Aenderung `node scripts/stil-bauen.mjs`.
   ========================================================================= */

/* =========================================================================
   ABSCHNITT A — DIE GRUNDLAGE
   Bis zum 21.08.2026 eine eigene Datei: docs/design/patch-agentos-chat.css.
   Ihr Kopf steht unveraendert darunter; er traegt die Anatomie der
   Owner-Referenz vom 28.07., auf der alles Folgende beruht.
   ========================================================================= */

/* =========================================================================
   Agent OS — Chat-Fläche (#/chat) exakt nach der Owner-Referenz vom 28.07.
   («Chat mit Super-Agent», docs/design/ZIELBILD-2026-07-28.md:10-21 und
   docs/design/PROTOTYP-ANALYSE.md Abschnitt C).

   EINSETZEN: Diesen Block unveraendert an das ENDE von public/style.css
   haengen — nach allen Basisregeln und nach den bestehenden Mobile-Bloecken
   (Projekt-Cascade-Regel, Memory project_css_cascade_mobile: ein eigener
   @media-Block gehoert NACH die Basis, sonst wirkt er nicht). Danach die
   Service-Worker-VERSION in public/sw.js hochzaehlen und ueber
   ./scripts/jetzt-ausliefern.sh ausliefern.

   Warum als Patch-Datei und nicht direkt in style.css: diese Etappe lief in
   einer Welle mit drei parallelen Teams. Vier Haende in derselben
   6'000-Zeilen-Datei sind ein Konflikt mit Ansage; der Wellen-Integrator
   haengt die Bloecke in einem Zug an. Bis dahin bleibt der Bildschirm
   bedienbar: alle tragenden Elemente stehen auf bestehenden Klassen
   (.panel, .panel__header, .panel-row/__main, .badge, .empty-state,
   .primary-btn/.ghost-btn, der globale <textarea>-Boden aus docs/design/grund.css).

   Anatomie der Referenz, hier in Regeln uebersetzt:
     1. Kopfzeile: Titel links, Werkzeuge rechts
     2. Raster: Chat-Spalte links, «Aktive Missionen» als schmale Spalte
        rechts (auf dem Handy darunter, gleichwertig — nie eine Restgroesse)
     3. im Verlauf AUFTRAGSKARTEN: Titel · Bereich · Begruendung · Ziele ·
        Wirkung · Knoepfe
     4. unten ein Lage-Streifen — nur Gemessenes. Keine Gesundheit in
        Prozent, kein Token-Zaehler: deren Weg steht in PROTOTYP-ANALYSE
        C5/C6/C7, ihre Quelle existiert noch nicht.
   Praefix ao- fuer alles Neue.
   ========================================================================= */

/* --- 1. Kopf ------------------------------------------------------------ */
/* .page-head war app-weit nie definiert (Fund 29.07.: zehn Views nutzen sie,
   public/style.css kennt sie nicht) — der Chat trug seinen Titel und seine
   Knoepfe darum ohne jede Ordnung untereinander. Hier eine eigene, definierte
   Kopfzeile statt einer Klasse, die ins Leere greift. */
.ao { display: grid; gap: 16px; }
.ao-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 12px; flex-wrap: wrap; }
.ao-head h1 { margin: 0; font-size: 20px; font-weight: 650; letter-spacing: -.01em; color: var(--text-primary); }

/* --- 2. Raster: Chat + Missionen ---------------------------------------- */
.ao-raster {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(288px, 340px);
  gap: 16px;
  align-items: start;
}
.ao-chat { display: flex; flex-direction: column; gap: 14px; min-width: 0; min-height: 60vh; }
/* GEFALLEN 21.08.: `.ao-chat .panel__header { margin-bottom: 0; align-items: center; }`
   `panel__header` steht in views/chat.js genau EINMAL (Zeile 602, im Zugang-Block)
   und liegt dort nicht in `.ao-chat`. Die Regel traf seit dem Panel-Umbau vom
   03.08. kein Element mehr. Rueckweg: git show ef2ed08:docs/design/patch-agentos-chat.css */

/* Der Verlauf ist die einzige Flaeche, die scrollt — Kopf, Eingabe und
   Lage-Streifen bleiben stehen. Der Inhalt haengt unten, direkt ueber der
   Eingabe (wie in jedem Gespraech); `margin-top:auto` am ersten Kind statt
   `justify-content:flex-end`, weil letzteres den oberen Rand eines
   Scrollbereichs in mehreren Engines unerreichbar macht. */
.ao-verlauf {
  flex: 1 1 auto; min-height: 160px; max-height: calc(100vh - 360px);
  overflow-y: auto; display: flex; flex-direction: column;
}
.ao-verlauf > :first-child { margin-top: auto; }
/* GEFALLEN 21.08.: `.ao-verlauf .empty-state { padding: 26px 20px; }`
   `empty-state` steht in views/chat.js genau EINMAL (Zeile 753, der Ladehinweis)
   und liegt direkt in `.ao--panel`, nicht im Verlauf. Gestaltet wird es von
   `.ao--panel > .empty-state` in docs/design/patch-agent-panel.css.
   Rueckweg: git show ef2ed08:docs/design/patch-agentos-chat.css */

/* Anatomie der Referenz: Zeichen im Kreis links, daneben Name und Uhrzeit in
   einer Zeile, darunter der Text. Kein Initialen-Avatar — «Du» ist der
   Lesende selbst, der Assistent kein Mensch (EINHEIT.md 1.7/1.8). */
.ao-nachricht { align-items: flex-start; gap: 12px; padding: 12px 0; }
.ao-nachricht__zeichen {
  display: grid; place-items: center; flex: 0 0 auto;
  width: 32px; height: 32px; border-radius: 50%;
  background: rgba(var(--tint-rgb), .08); border: 1px solid var(--border);
  color: var(--text-tertiary);
}
.ao-nachricht__zeichen svg { width: 16px; height: 16px; }
.ao-nachricht--agent .ao-nachricht__zeichen {
  background: var(--accent-soft); border-color: var(--accent-line); color: var(--accent);
}
.ao-nachricht__kopf { display: flex; align-items: baseline; gap: 10px; margin-bottom: 3px; }
.ao-nachricht__wer { font-weight: 600; font-size: 12.5px; letter-spacing: .01em; color: var(--text-primary); }
.ao-nachricht--agent .ao-nachricht__wer { color: var(--accent); }
.ao-nachricht__zeit {
  font-size: 11.5px; color: var(--text-tertiary); font-variant-numeric: tabular-nums;
}
.ao-nachricht__text {
  white-space: pre-wrap; color: var(--text-primary);
  font-size: 14px; line-height: 1.55; overflow-wrap: anywhere;
}

/* --- Eingabe ------------------------------------------------------------ */
.ao-eingabe { display: flex; gap: 8px; align-items: flex-end; }
.ao-eingabe__feld {
  flex: 1 1 auto; min-width: 0;
  min-height: 44px; max-height: 160px; resize: vertical;
  padding: 11px 12px; line-height: 1.45;
}
.ao-eingabe__senden { min-height: 44px; }

/* --- 3. Auftragskarte --------------------------------------------------- */
/* Eine Stufe heller als das Panel, damit sie im Verlauf als eigenes Objekt
   steht — sie ist kein Text, sondern ein Antrag an einen Menschen. */
.ao-karte {
  margin-top: 10px; padding: 14px;
  background: var(--surface-2); border: 1px solid var(--border);
  border-radius: var(--radius-card);
  display: grid; gap: 8px;
}
.ao-karte__kopf { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.ao-karte__titel { margin: 0; font-size: 14px; font-weight: 650; letter-spacing: -.01em; color: var(--text-primary); }
.ao-karte__grund { margin: 0; color: var(--text-secondary); font-size: 13.5px; line-height: 1.5; }
.ao-karte__ziele { display: grid; gap: 4px; }
.ao-ziel { display: flex; gap: 8px; align-items: baseline; font-size: 13px; min-width: 0; }
.ao-ziel__feld { color: var(--text-tertiary); flex: 0 0 auto; }
.ao-ziel__wert {
  color: var(--text-primary); font-family: var(--font-mono); font-size: 12px;
  overflow-wrap: anywhere; min-width: 0;
}
/* Die Wirkung steht abgesetzt: sie ist das Ergebnis der Vorschau, nicht Teil
   des Vorschlags. Zahlen tabellarisch, damit sie beim Neuzeichnen nicht wandern. */
.ao-karte__wirkung {
  display: flex; flex-wrap: wrap; gap: 6px 16px;
  padding-top: 9px; border-top: 1px solid var(--border);
  font-size: 13px; color: var(--text-secondary);
}
.ao-karte__zahl b { color: var(--text-primary); font-variant-numeric: tabular-nums lining-nums; }
.ao-karte__blocker { flex-basis: 100%; color: var(--warn-strong); font-size: 12.5px; }
.ao-karte__warnung { flex-basis: 100%; color: var(--warn-strong); }
.ao-karte__fehler { margin: 0; color: var(--bad-strong); font-size: 13px; }
.ao-karte__fertig { color: var(--good-strong); font-size: 13px; }
.ao-karte__nichts { color: var(--text-secondary); font-size: 13px; }
.ao-karte__fuss { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; }
.ao-karte__knoepfe { display: flex; gap: 8px; flex-wrap: wrap; }
.ao-karte__schluessel {
  color: var(--text-tertiary); font-family: var(--font-mono); font-size: 11px;
  overflow-wrap: anywhere;
}

/* --- 4. Kontext-Spalte (Referenz 13_25_33 (2): «Live-Kontext / Ausführung»)
   Vier Blöcke, jeder mit einer Quelle, die ohnehin schon geladen ist: Zugang ·
   Entscheidungen · Aktive Missionen · Werkzeuge. Die Spalte klebt beim
   Scrollen — sie ist die Orientierung, nicht der Inhalt. */
.ao-kontext {
  position: sticky; top: 16px;
  padding: 16px 18px;
  display: grid; gap: 16px; align-content: start;
  max-height: calc(100vh - 32px); overflow-y: auto;
}
.ao-kontext__kopf h2 { margin: 0; }
.ao-block { display: block; min-width: 0; }
.ao-block + .ao-block { padding-top: 14px; border-top: 1px solid var(--border); }
/* Block-Titel in gemischter Schreibung, nicht in Versalien wie im Prototyp:
   gesperrte Versalien tragen hier genau eine Aufgabe, den Spaltenkopf
   (EINHEIT.md 1.5). */
.ao-block__titel {
  margin: 0 0 8px; display: flex; align-items: center; gap: 8px;
  font-size: 13px; font-weight: 650; letter-spacing: -.01em; color: var(--text-primary);
}

/* Feldpaare wie das «Projekt-Routing» der Referenz: Label über Wert, zwei
   Spalten. */
.ao-felder { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px 14px; }
.ao-feld { display: grid; gap: 2px; min-width: 0; }
.ao-feld i { font-style: normal; font-size: 11px; color: var(--text-tertiary); }
.ao-feld b {
  font-size: 12.5px; font-weight: 600; color: var(--text-secondary);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* «Entscheidungen nötig»: zwei abgezählte Zahlen, keine geschätzte. */
.ao-zahlen { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
.ao-zahl { display: grid; gap: 1px; min-width: 0; }
.ao-zahl b {
  font-size: 22px; font-weight: 650; letter-spacing: -.5px; line-height: 1.1;
  color: var(--text-primary); font-variant-numeric: tabular-nums lining-nums;
}
.ao-zahl i { font-style: normal; font-size: 11.5px; color: var(--text-tertiary); }

/* Werkzeuge: was diese Person durch die Tür wirklich auslösen darf, mit den
   Grenzen, die im Register stehen. Kein Auslastungsbalken wie im Prototyp —
   dafür gibt es keine Messung (PROTOTYP-ANALYSE C2/C5). */
.ao-werkzeug { display: grid; gap: 2px; padding: 8px 0; border-top: 1px solid var(--border); }
.ao-block__titel + .ao-werkzeug { border-top: 0; padding-top: 0; }
.ao-werkzeug__kopf { display: flex; align-items: center; gap: 8px; min-width: 0; }
.ao-werkzeug__titel {
  font-size: 13px; font-weight: 600; color: var(--text-primary); min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ao-werkzeug__grenze { font-size: 11.5px; color: var(--text-tertiary); }


.ao-mission {
  display: grid; gap: 5px;
  padding: 11px 10px; margin: 0 -10px;
  border-top: 1px solid var(--border);
  border-radius: var(--radius-card);
  color: inherit; text-decoration: none;
  transition: background var(--transition);
}
.ao-mission:hover { background: rgba(var(--tint-rgb), .05); }
.ao-mission:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.ao-mission__kopf { display: flex; align-items: center; gap: 8px; justify-content: space-between; min-width: 0; }
.ao-mission__titel {
  font-size: 13.5px; font-weight: 600; color: var(--text-primary);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0;
}
.ao-mission__schritt { font-size: 13px; color: var(--text-secondary); line-height: 1.4; }
.ao-mission__frist {
  margin-left: auto; font-size: 11.5px; color: var(--text-tertiary);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.ao-mission__frist.is-spaet { color: var(--bad-strong); }

/* Fortschritt ist hier keine erfundene Prozentzahl, sondern die Abzaehlung
   der offenen Schritte: ein Strich je Schritt, gefuellt was laeuft, bernstein
   was blockiert. Mehr geben die Daten nicht her, und mehr wird nicht behauptet. */
.ao-takt { display: inline-flex; gap: 3px; align-items: center; }
.ao-takt__i { width: 14px; height: 4px; border-radius: 2px; background: rgba(var(--tint-rgb), .16); }
.ao-takt__i--arbeit { background: var(--accent); }
.ao-takt__i--blockiert { background: var(--warn); }
.ao-takt__text { font-size: 11.5px; color: var(--text-tertiary); font-variant-numeric: tabular-nums; }

/* ENTFERNT, nicht ersetzt: .ao-leer · .ao-leer a (+ :hover)
   GEFALLEN 21.08.2026 — die Leer-Zeile des Hauses ist EINE Form:
   `.empty-state.empty-state--zeile` + `.empty-state__weg` in docs/design/grund.css. */

/* --- Chips -------------------------------------------------------------- */
/* Zustand ist ein Wort in Pillenform (.badge traegt die Form). */
.ao-chip--bereich { background: var(--accent-soft); color: var(--accent-strong); }
/* Der gemessene Anbieterzustand im Kopf der Chat-Spalte (Referenz: «Online»).
   Er wiederholt keine Behauptung, sondern spiegelt genau den Wert, den der
   Lage-Streifen unten misst. */
.ao-chip--zustand { background: rgba(var(--tint-rgb), .08); color: var(--text-secondary); }
.ao-chip--zustand.is-an { background: var(--accent-soft); color: var(--accent-strong); }
.ao-chip--zustand.is-weg { background: rgba(var(--bad-rgb), .13); color: var(--bad-strong); }
.ao-chip--zustand.is-unklar { background: rgba(var(--warn-rgb), .13); color: var(--warn-strong); }
.ao-chip--zahl { background: rgba(var(--tint-rgb), .08); color: var(--text); font-variant-numeric: tabular-nums; }
.ao-chip--offen { background: rgba(var(--tint-rgb), .08); color: var(--text); }
.ao-chip--arbeit { background: rgba(var(--accent-rgb), .15); color: var(--accent-strong); }
.ao-chip--blockiert { background: rgba(var(--warn-rgb), .15); color: var(--warn-strong); }

/* --- 5. Lage-Streifen ---------------------------------------------------
   Dieselbe Anatomie wie die Fusszeile der Zentrale (Zeichen im Soft-Quadrat,
   Label über Wert): zwei Innenflächen, eine Leiste — genau das, was «sauber
   einheitlich» heisst. Labels in gemischter Schreibung (EINHEIT.md 1.5). */
.ao-lage {
  display: flex; flex-wrap: wrap; align-items: center; gap: 10px 24px;
  padding: 12px 16px;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-card);
  font-size: 12.5px; color: var(--text-secondary);
}
.ao-lage__punkt { display: inline-flex; align-items: center; gap: 9px; min-width: 0; }
.ao-lage__ic {
  display: grid; place-items: center; flex: 0 0 auto;
  width: 28px; height: 28px; border-radius: 9px;
  background: rgba(var(--tint-rgb), .07); color: var(--text-tertiary);
}
.ao-lage__ic svg { width: 14px; height: 14px; }
.ao-lage__ic--an { background: var(--accent-soft); color: var(--accent); }
.ao-lage__ic--weg { background: rgba(var(--bad-rgb), .13); color: var(--bad-strong); }
.ao-lage__ic--unklar { background: rgba(var(--warn-rgb), .13); color: var(--warn-strong); }
.ao-lage__text { display: grid; gap: 1px; min-width: 0; }
.ao-lage__text i { font-style: normal; font-size: 11px; color: var(--text-tertiary); white-space: nowrap; }
.ao-lage__text b { font-size: 12.5px; font-weight: 600; color: var(--text-secondary); white-space: nowrap; }
.ao-lage__detail { color: var(--text-tertiary); overflow-wrap: anywhere; }

/* --- Freischaltung (Wer darf den Chat) ---------------------------------- */
.ao-zugang__rolle {
  display: flex; flex-wrap: wrap; align-items: center; gap: 14px;
  padding: 8px 0; border-top: 1px solid var(--border);
}
.ao-zugang__wer { flex: 1 1 180px; display: flex; flex-direction: column; gap: 2px; }
.ao-zugang__portal { font-size: 12px; color: var(--text-secondary); }
.ao-zugang__schalter { display: flex; align-items: center; gap: 6px; min-height: 44px; font-size: 13.5px; }
.ao-zugang__sichern { min-height: 44px; }
.ao-zugang__grenzen { flex-basis: 100%; display: flex; flex-wrap: wrap; gap: 10px; }
.ao-zugang__hinweis { flex-basis: 100%; font-size: 11px; color: var(--text-tertiary); }
.ao-zugang__fehler { flex-basis: 100%; color: var(--bad-strong); font-size: 13px; }

/* =========================================================================
   Tablet und Handy — eigener Block NACH den Basisregeln.
   Die Missionen sind auf dem Handy keine Restgroesse: sie stehen unter dem
   Chat in voller Breite, mit derselben Zeile und derselben Tapflaeche.
   ========================================================================= */
@media (max-width: 1000px) {
  .ao-raster { grid-template-columns: minmax(0, 1fr); }
  .ao-kontext { position: static; max-height: none; }
  .ao-chat { min-height: 0; }
  .ao-verlauf { max-height: 52vh; }
}

@media (max-width: 640px) {
  .ao { gap: 12px; }
  .ao-head h1 { font-size: 19px; }
  .ao-verlauf { max-height: 46vh; }
  .ao-karte { padding: 12px; }
  .ao-karte__knoepfe { width: 100%; }
  .ao-karte__knoepfe .primary-btn { width: 100%; justify-content: center; }
  .ao-lage { gap: 6px 14px; padding: 12px 14px; }
  .ao-lage__punkt,
  .ao-lage__detail { flex-basis: 100%; }
  .ao-mission__frist { margin-left: 0; }
}

/* Der Tapflaechen-Boden gilt auf jedem Touch-Geraet, nicht nur unter 640px
   (Memory project_tablet_touch_breakpoint: 768/1024px sind die Bruchzone). */
@media (max-width: 1024px), (pointer: coarse) {
  .ao-mission { min-height: 44px; padding: 12px 10px; }
  .ao-eingabe__feld, .ao-eingabe__senden { min-height: 44px; }
  /* ENTFERNT: .ao-leer a — der Touch-Boden steht jetzt am Haus-Weg
     (`.empty-state__weg`, grund.css), also fuer ALLE Leer-Zeilen statt nur
     fuer diese eine. Diese Fassung war von den vierzehn die einzige, die ihn
     ueberhaupt hatte. */
}

/* =========================================================================
   ABSCHNITT B — DER ANATOMIE-PASS VOM 31.07.
   Bis zum 21.08.2026 der Rumpf dieser Datei. Er ersetzt Abschnitt A nicht,
   er korrigiert ihn — darum steht er dahinter, wie in der Kaskade zuvor.
   ========================================================================= */

/* =========================================================================
   REFERENZ-ANATOMIE-PASS CHAT · 31.07. — Namensraum ao-
   Quelle des Zielbildes: docs/design/referenzen/Portaluikomplett/
     «ChatGPT Image 29. Juli 2026, 13_25_27.png»       (Chat-Spalte im Ganzen)
     «ChatGPT Image 29. Juli 2026, 13_25_33 (2).png»   (Chat als eigener Schirm)

   EINSETZEN: Diesen Block als GANZES an das ENDE von public/style.css
   haengen — NACH dem bestehenden ao-Block (Quelle: patch-agentos-chat.css).
   Er ersetzt ihn nicht, er korrigiert ihn: die Kaskade entscheidet, darum
   muss er dahinter stehen (Memory project_css_cascade_mobile). Danach die
   Service-Worker-VERSION in public/sw.js hochzaehlen und ueber
   ./scripts/jetzt-ausliefern.sh ausliefern.

   Warum ein zweiter Pass und kein Neuschnitt des alten Blocks: der alte
   Block traegt weiterhin alles, was die Referenz nicht anfasst — Zugang,
   Lage-Streifen, Chips, Tapflaechen-Boeden. Ein Neuschnitt haette das
   mitkopieren muessen; ein Pass zeigt genau die Differenz.

   WAS IM NEBENEINANDER ANDERS WAR (und hier repariert wird):

     1. RAHMEN. Im Bild ist die Chat-Spalte EIN umrandetes Panel mit tuerkis
        getoenter Kante, innen ein eigener Kopf mit Trennlinie. Bei uns
        schwamm sie als .panel ohne diese Ordnung.
     2. DICHTE. Die Referenz laeuft auf 12.5–13px Fliesstext und engen
        Abstaenden; unser Stand lag durchgehend eine Stufe darueber. Jede
        Groessenregel hier SENKT bewusst.
     3. ZWEI SEITEN. Assistent links ohne Blase, Mensch rechts in einer
        tuerkis gefuellten Blase mit Uhrzeit und Haken. Vorher sahen beide
        Seiten identisch aus.
     4. MISSIONEN. Im Bild eine Karte IM Gespraech: CAPS-Label, darunter
        Zeilen aus Zeichen · Titel · Subzeile · duennem Balken.
     5. EINGABE. Ein gerahmtes Feld, darunter links die Zeichenreihe, rechts
        der tuerkise Senden-Knopf.

   TUERKIS IST HIER FARBE, NICHT SCHMUCK: gefuellt ist genau das, was der
   Mensch selbst gesagt hat, was laeuft und was sendet.

   NACHTRAG 03.08. — KEIN SCHEIN. Dieser Kopf sagte an zwei Stellen «mit
   Schein», und zwei Regeln setzten ihn um (Balken und Senden-Knopf). Das Wort
   stammte aus der Beschreibung, nicht aus dem Bild. Owner-Befund, woertlich:
   «wenn du das Referenzbild anschaust, hat es kein Glueh. Die ganze App hat
   kein Glueh.» Am Bild nachgemessen statt geglaubt — zwei senkrechte
   Pixelschnitte durch 13_25_27.png:

     Missionsbalken, x=700 : Grund y390 = 14,26,33 · Balken y393-395 =
       19,172,160 · y397 = 13,10,21. Zwei Pixel unter dem Balken ist es
       DUNKLER als daneben. Ein Leuchtradius haette genau dort angehoben.
     Senden-Knopf, x=862   : Grund y763 = 13,21,29 · fuenf Pixel ueber der
       Oberkante y770 = 12,26,33 · Flaeche y800 = 8,69,73 · Glyphe y790 =
       81,235,236. Kein Hof, harte Kante, gedaempfte Fuellung mit heller
       Glyphe — genau die Fuellung, die hier steht.

   Beide box-shadow-Regeln sind darum entfernt. Die Aussage traegt die
   FUELLUNG, wie bei jedem Balken im Haus (.stat__bar > i, docs/design/grund.css).
   ========================================================================= */

/* Die getoente Kante der Referenz — dieselbe Sprache wie in der Zentrale
   (docs/design/patch-zentrale.css, Rahmen-und-Farbe-Pass). */
.ao { --ao-kante: rgba(var(--accent-rgb), .16); }

/* Nur fuer Vorleseprogramme: die tuerkise Blase sagt mit den Augen «das war
   ich», nicht mit Worten. Wer sie nicht sieht, braucht das Wort. */
.ao-nurlese {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%);
  white-space: nowrap; border: 0;
}

/* --- 1. Die Chat-Spalte als gerahmtes Panel ------------------------------ */
.ao-head { align-items: center; }
.ao-head h1 { font-size: 17px; font-weight: 600; color: var(--text-secondary); }

/* Das Verhaeltnis der Referenz: die Chat-Spalte ist keine Restflaeche, die
   Kontext-Spalte keine Randnotiz (13_25_33 (2): rund 56 zu 44). Vorher stand
   die Kontext-Spalte bei 288–340px — die Chat-Spalte lief damit auf ueber
   1000px auf, und eine Missionszeile zog ihren Balken einen Meter weit. Genau
   das liest sich als «aufgeblasen». */
.ao-raster { grid-template-columns: minmax(0, 1fr) minmax(300px, 400px); }

.ao-chat {
  background: var(--surface);
  border: 1px solid var(--ao-kante);
  border-radius: var(--radius-card);
  padding: 0;
  gap: 0;
  overflow: hidden;
}
.ao-chat__kopf {
  display: flex; align-items: center; gap: 10px;
  padding: 12px 15px;
  border-bottom: 1px solid var(--border);
}
.ao-chat__titel {
  margin: 0; font-size: 15px; font-weight: 650; letter-spacing: -.01em;
  color: var(--text-primary);
}
.ao-chat__einstellung { margin-left: auto; }

/* --- 2. Der Verlauf ------------------------------------------------------ */
/* Der alte Block haengte den Inhalt mit `margin-top:auto` an die Unterkante.
   Die Referenz laeuft von OBEN: erst die Missions-Karte, dann das Gespraech,
   darunter Luft bis zur Eingabe. */
.ao-verlauf { padding: 14px 15px 4px; }
.ao-verlauf > :first-child { margin-top: 0; }
.ao-strom { display: flex; flex-direction: column; }

/* Das Lesemass der Referenz. Im Bild ist die Chat-Spalte schmal; bei uns kann
   sie auf einem 27-Zoll-Schirm auf tausend Pixel aufgehen — dann steht in
   einer Missionszeile der Titel links und die Frist einen halben Meter weiter
   rechts, und der Balken zieht sich ueber die ganze Strecke. Genau das liest
   der Owner als «aufgeblasen». Der Strom, die Karten und die Eingabe teilen
   sich darum EIN Mass und stehen mittig darin — die Spalte bleibt breit, der
   Inhalt bleibt lesbar. */
.ao-lauf, .ao-strom, .ao-werkzeugwahl, .ao-eingabe__rahmen, .ao-hinweis,
.ao-verlauf > [data-slot="gruss"] {
  max-width: 760px; margin-inline: auto; width: 100%;
}

/* --- 3. Missions-Karte im Verlauf (Referenz 13_25_27) -------------------- */
.ao-lauf {
  flex: 0 0 auto;
  margin-bottom: 14px; padding: 12px 13px 13px;
  background: var(--surface-2);
  border: 1px solid var(--ao-kante);
  border-radius: var(--radius-card);
}
.ao-lauf__kopf { display: flex; align-items: center; gap: 8px; margin-bottom: 10px; }
.ao-lauf__label {
  margin: 0; font-size: 11px; font-weight: 600; letter-spacing: .08em;
  text-transform: uppercase; color: var(--text-secondary);
}
/* Die Zeilen liegen in EINEM Kasten mit inneren Trennlinien — nicht als
   lose Reihe. Genau das gibt dem Bild seine Ordnung. */
.ao-lauf__liste { border: 1px solid var(--border); border-radius: var(--radius-card); overflow: hidden; }
.ao-lauf__liste .ao-mission + .ao-mission { border-top: 1px solid var(--border); }
/* ENTFERNT: .ao-lauf .ao-leer (padding 9px 2px 0, font-size 12px) — eine
   Sonderfassung der Sonderfassung. Eine Bauart heisst: EIN Mass. */

.ao-mission {
  display: grid; grid-template-columns: auto minmax(0, 1fr);
  gap: 0 11px; align-items: start;
  margin: 0; padding: 10px 12px;
  border: 0; border-radius: 0;
}
.ao-mission:hover { background: rgba(var(--tint-rgb), .04); }
.ao-mission__ic {
  display: grid; place-items: center;
  width: 30px; height: 30px; border-radius: 9px;
  background: rgba(var(--tint-rgb), .06);
  border: 1px solid var(--border);
  color: var(--text-tertiary);
}
.ao-mission__ic svg { width: 15px; height: 15px; }
.ao-mission__ic--arbeit {
  background: var(--accent-soft); border-color: var(--accent-line); color: var(--accent);
}
.ao-mission__ic--blockiert {
  background: rgba(var(--warn-rgb), .12); border-color: rgba(var(--warn-rgb), .30);
  color: var(--warn-strong);
}
.ao-mission__leib { display: grid; gap: 4px; min-width: 0; }
.ao-mission__kopf { gap: 8px; }
.ao-mission__titel { font-size: 13px; }
.ao-mission__zeile {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 10px; min-width: 0;
}
.ao-mission__schritt {
  font-size: 11.5px; color: var(--text-secondary); min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ao-mission__frist { margin-left: 0; flex: 0 0 auto; font-size: 11.5px; }
.ao-mission .ao-chip { font-size: 11px; }

/* Der duenne Balken der Referenz — ein Abschnitt je offenem Schritt, ueber
   die volle Breite. FLACH: hier standen zwei Regeln mit `0 0 9px`; der
   Pixelschnitt im Kopf dieses Blocks zeigt, dass das Bild keinen Hof hat.
   Was der Abschnitt sagt, sagt seine Fuellung — .ao-takt__i--arbeit traegt
   `background: var(--accent)` und --blockiert `var(--warn)` aus der Grundlage
   (Abschnitt A dieses Blattes). Die Aussage bleibt, der Schmuck faellt weg. */
.ao-takt { display: flex; gap: 3px; width: 100%; margin-top: 3px; }
.ao-takt__i { flex: 1 1 0; width: auto; height: 3px; border-radius: 2px; }
.ao-mission .ao-takt__text { font-size: 11.5px; color: var(--text-tertiary); }

/* --- 4. Zwei Seiten ------------------------------------------------------ */
.ao-nachricht { display: flex; align-items: flex-start; gap: 11px; padding: 9px 0; }
.ao-nachricht__leib { flex: 1 1 auto; min-width: 0; display: grid; gap: 4px; }
.ao-nachricht__kopf { margin-bottom: 0; }
/* Der Name des Assistenten steht im Bild in Weiss, nicht in Tuerkis — das
   Tuerkis gehoert dem Zeichen und der eigenen Blase. */
.ao-nachricht--agent .ao-nachricht__wer { color: var(--text-primary); font-size: 13px; }
.ao-nachricht--agent .ao-nachricht__zeichen {
  width: 36px; height: 36px;
  background: transparent; border: 1px solid var(--accent-line); color: var(--accent);
}
.ao-nachricht--agent .ao-nachricht__zeichen svg { width: 17px; height: 17px; }
.ao-nachricht__text { font-size: 13px; line-height: 1.55; }
.ao-nachricht--gruss .ao-nachricht__text { color: var(--text-secondary); }

/* Die eigene Antwort: rechts, tuerkis gefuellt, mit der Ecke unten rechts —
   die Form, an der ein Gespraech als Gespraech lesbar wird. */
.ao-nachricht--du { justify-content: flex-end; }
.ao-blase {
  max-width: 78%; min-width: 0;
  display: grid; gap: 3px;
  padding: 10px 13px 7px;
  background: rgba(var(--accent-rgb), .30);
  border: 1px solid rgba(var(--accent-rgb), .34);
  /* Die Ecke unten rechts bleibt spitz — so zeigt die Blase auf den, der spricht (Referenz 13_25_27). */
  border-radius: var(--radius-card) var(--radius-card) 0 var(--radius-card);
}
.ao-blase .ao-nachricht__text { color: var(--text-primary); }
.ao-blase__fuss { display: flex; align-items: center; justify-content: flex-end; gap: 6px; }
.ao-blase__fuss .ao-nachricht__zeit { color: rgba(233, 242, 242, .72); font-size: 11px; }
.ao-blase__haken { display: inline-flex; color: var(--accent-bright); }
.ao-blase__haken svg { width: 15px; height: 15px; }

/* --- 5. Auftragskarte im Verlauf (Referenz 13_25_33 (2)) ----------------- */
.ao-karte {
  margin-top: 10px; padding: 11px 12px 12px; gap: 7px;
  background: var(--surface);
  border-color: var(--ao-kante);
  border-radius: var(--radius-card);
}
.ao-karte__label {
  font-size: 11px; font-weight: 600; letter-spacing: .08em;
  text-transform: uppercase; color: var(--text-tertiary);
}
.ao-karte__kopf { gap: 9px; }
.ao-karte__ic {
  display: grid; place-items: center; flex: 0 0 auto;
  width: 28px; height: 28px; border-radius: 8px;
  background: var(--accent-soft); border: 1px solid var(--accent-line); color: var(--accent);
}
.ao-karte__ic svg { width: 15px; height: 15px; }
.ao-karte__titel { font-size: 13px; font-weight: 600; }
.ao-karte__grund { font-size: 12.5px; }
.ao-ziel { font-size: 12px; }
.ao-ziel__wert { font-size: 11.5px; }
.ao-karte__wirkung { font-size: 12px; gap: 5px 14px; padding-top: 8px; }
.ao-karte__fertig, .ao-karte__nichts, .ao-karte__fehler { font-size: 12.5px; }
.ao-karte__schluessel { font-size: 11px; }

/* --- 6. Eingabezeile ----------------------------------------------------- */
/* Ein gerahmtes Feld, darunter die Zeichenreihe und der Senden-Knopf. Es
   stehen NUR Zeichen da, die wirklich etwas tun: Anhang, Erwaehnung, Code
   und Mikrofon des Prototyps haetten bei uns keine Funktion — eine Tuer, die
   nicht aufgeht, ist schlimmer als keine (docs/design/EINHEIT.md 1.8). */
.ao-eingabe { display: block; padding: 4px 15px 15px; }
.ao-eingabe__rahmen {
  padding: 9px 11px 8px;
  background: var(--surface-inset);
  border: 1px solid var(--ao-kante);
  border-radius: var(--radius-card);
}
.ao-eingabe__rahmen:focus-within { border-color: var(--accent-line); }
.ao-eingabe .ao-eingabe__feld {
  display: block; width: 100%;
  padding: 5px 3px; min-height: 44px; max-height: 150px; resize: none;
  background: transparent; border: 0; box-shadow: none;
  font: inherit; font-size: 13px; line-height: 1.5; color: var(--text-primary);
}
.ao-eingabe .ao-eingabe__feld:focus,
.ao-eingabe .ao-eingabe__feld:hover {
  outline: none; background: transparent; border: 0; box-shadow: none;
}
.ao-eingabe__leiste {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  margin-top: 2px;
}
.ao-eingabe__zeichen { display: flex; align-items: center; gap: 6px; }

.ao-ic {
  display: grid; place-items: center;
  width: 34px; height: 34px; padding: 0;
  background: transparent; border: 0; border-radius: var(--radius-card);
  color: var(--text-tertiary); cursor: pointer;
  transition: color var(--transition), background var(--transition);
}
.ao-ic svg { width: 18px; height: 18px; }
.ao-ic:hover { color: var(--text-primary); background: rgba(var(--tint-rgb), .06); }
.ao-ic:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.ao-ic[aria-expanded="true"] { color: var(--accent); background: var(--accent-soft); }

/* Gefuellt, aber gedaempft — und ohne Hof. Die Fuellung hier ergibt ueber dem
   dunklen Grund rund 10,75,80; das Bild misst an derselben Stelle 8,69,73 mit
   heller Glyphe darauf (Schnitt im Kopf dieses Blocks). Sie bleibt also. Der
   `box-shadow: 0 0 14px` daneben stand in keinem Bild und ist entfernt. */
.ao-eingabe__senden {
  display: grid; place-items: center;
  width: 52px; min-height: 44px; padding: 0;
  border: 1px solid rgba(var(--accent-rgb), .45); border-radius: var(--radius-card);
  background: linear-gradient(180deg, rgba(var(--accent-rgb), .38), rgba(var(--accent-rgb), .20));
  color: var(--accent-bright); cursor: pointer;
  transition: filter var(--transition);
}
.ao-eingabe__senden svg { width: 19px; height: 19px; }
.ao-eingabe__senden:hover:not(:disabled) { filter: brightness(1.15); }
.ao-eingabe__senden:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.ao-eingabe__senden:disabled { cursor: not-allowed; }
/* Wartezustand als Zustand, nicht als Textwechsel: der Papierflieger bleibt. */
.ao-eingabe__senden.is-laeuft { opacity: .6; animation: ao-puls 1.1s ease-in-out infinite; }
@keyframes ao-puls { 50% { opacity: .28; } }
@media (prefers-reduced-motion: reduce) {
  .ao-eingabe__senden.is-laeuft { animation: none; }
}

/* Die Werkzeugwahl — die Breite der Tuer, bedienbar statt nur nachlesbar. */
.ao-werkzeugwahl {
  margin-bottom: 9px; padding: 11px 12px;
  background: var(--surface-2);
  border: 1px solid var(--ao-kante); border-radius: var(--radius-card);
}
.ao-werkzeugwahl[hidden] { display: none; }
.ao-werkzeugwahl__kopf {
  display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; margin-bottom: 8px;
}
.ao-werkzeugwahl__hinweis { font-size: 11px; color: var(--text-tertiary); }
.ao-werkzeugwahl__liste {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 6px;
}
.ao-werkzeugwahl__knopf {
  display: grid; gap: 2px; text-align: left;
  padding: 9px 11px; min-height: 44px;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-card);
  color: inherit; cursor: pointer; font: inherit;
}
.ao-werkzeugwahl__knopf:hover { border-color: var(--accent-line); background: var(--surface-hover); }
.ao-werkzeugwahl__knopf:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.ao-werkzeugwahl__titel { font-size: 12.5px; font-weight: 600; color: var(--text-primary); }
.ao-werkzeugwahl__grenze { font-size: 11px; color: var(--text-tertiary); }

/* --- 6b. Anhaenge (Owner-Wunsch 21a) ------------------------------------- */
/* Die Chips der gewaehlten Dateien ueber der Eingabezeile — und dieselben
   Chips in der Blase, dort mit kleiner Bildvorschau (befristeter Link). */
.ao-anhangwahl {
  display: flex; flex-wrap: wrap; gap: 6px; align-items: center;
  padding: 6px 2px 0;
}
.ao-anhang {
  display: inline-flex; align-items: center; gap: 6px;
  max-width: 100%; padding: 4px 8px;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-card);
  font-size: 12px; color: var(--text-secondary);
}
.ao-anhang__zeichen { display: inline-flex; width: 14px; height: 14px; }
.ao-anhang__zeichen svg { width: 100%; height: 100%; }
.ao-anhang__name {
  max-width: 180px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ao-anhang__weg {
  display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; margin: -2px -4px -2px 0;
  border: 0; background: none; border-radius: var(--radius-card);
  color: var(--text-tertiary); font-size: 14px; line-height: 1; cursor: pointer;
}
.ao-anhang__weg:hover { background: var(--surface-hover); color: var(--text-primary); }
.ao-anhangwahl__fehler { font-size: 12px; color: var(--danger, #c0392b); }
.ao-blase__anhaenge { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 6px; }
.ao-nachricht--du .ao-anhang { background: rgba(255, 255, 255, .12); border-color: transparent; color: inherit; }
.ao-anhang--bild { padding: 4px; }
.ao-anhang__bild {
  display: block; width: 72px; height: 54px; object-fit: cover;
  border-radius: var(--radius-card); background: var(--surface-hover);
}

/* --- 7. Benutzte Werkzeuge und Quellen (Referenz 13_25_33 (2)) ----------- */
/* Im Bild stehen unter jeder Antwort drei Reihen aus Kacheln: verwendete
   Agenten, angewandte Tools, angehaengter Kontext. Bei uns zwei — Quellen und
   Werkzeuge —, weil es die dritte Sache nicht gibt: der Chat haengt keine
   Dateien an. Erfundene Reihen fuellen hier nichts. */
.ao-benutzt { display: grid; gap: 6px; margin-top: 9px; }
.ao-benutzt__reihe { display: grid; gap: 4px; }
.ao-benutzt__label {
  font-style: normal; font-size: 11px; font-weight: 600; letter-spacing: .08em;
  text-transform: uppercase; color: var(--text-tertiary);
}
.ao-benutzt__liste { display: flex; flex-wrap: wrap; gap: 5px; }
.ao-benutzt__stueck {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 9px 5px 6px;
  background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--radius-card);
  font-size: 11.5px; color: var(--text-secondary);
}
.ao-benutzt__ic {
  display: grid; place-items: center;
  width: 20px; height: 20px; border-radius: 6px;
  background: var(--accent-soft); color: var(--accent);
}
.ao-benutzt__ic svg { width: 12px; height: 12px; }
.ao-benutzt__modell { font-size: 11px; color: var(--text-tertiary); }

/* Fehlen die Zugangsdaten des Anbieters, steht das dort, wo sonst das
   Gespraech beginnt — eine gestaltete Zeile, kein toter Kasten. */
.ao-hinweis {
  display: flex; align-items: flex-start; gap: 11px;
  margin-bottom: 12px; padding: 11px 13px;
  background: rgba(var(--warn-rgb), .07);
  border: 1px solid rgba(var(--warn-rgb), .26); border-radius: var(--radius-card);
}
.ao-hinweis[hidden] { display: none; }
.ao-hinweis__ic {
  display: grid; place-items: center; flex: 0 0 auto;
  width: 28px; height: 28px; border-radius: 8px;
  background: rgba(var(--warn-rgb), .13); color: var(--warn-strong);
}
.ao-hinweis__ic svg { width: 15px; height: 15px; }
.ao-hinweis__text { display: grid; gap: 2px; min-width: 0; }
.ao-hinweis__text b { font-size: 12.5px; color: var(--text-primary); }
.ao-hinweis__text i {
  font-style: normal; font-size: 11.5px; line-height: 1.5; color: var(--text-secondary);
}

/* Die gesperrte Tuer (#/chat ohne Freischaltung). Ein Satz, wer es aendert,
   und sonst nichts — nie ein Chat als Attrappe. */
.ao-zu {
  display: flex; align-items: flex-start; gap: 13px;
  max-width: 620px; padding: 18px 19px;
  border: 1px solid var(--ao-kante); border-radius: var(--radius-card);
}
.ao-zu__ic {
  display: grid; place-items: center; flex: 0 0 auto;
  width: 38px; height: 38px; border-radius: 11px;
  background: var(--accent-soft); border: 1px solid var(--accent-line); color: var(--accent);
}
.ao-zu__ic svg { width: 19px; height: 19px; }
.ao-zu__text { display: grid; gap: 5px; min-width: 0; }
.ao-zu__titel {
  margin: 0; font-size: 15px; font-weight: 650; letter-spacing: -.01em;
  color: var(--text-primary);
}
.ao-zu__satz { margin: 0; font-size: 12.5px; line-height: 1.55; color: var(--text-secondary); }

/* --- 8. Kontext-Spalte und Lage: dieselbe Dichte ------------------------- */
.ao-kontext { padding: 14px 15px; gap: 14px; }
.ao-kontext__kopf { display: flex; align-items: center; gap: 10px; }
.ao-kontext__kopf h2 { font-size: 13px; letter-spacing: .04em; color: var(--text-secondary); }
.ao-kontext__leib { display: grid; gap: 14px; min-width: 0; }
/* Der Schalter gehoert dem Handy: am grossen Bildschirm steht die Spalte
   offen daneben und braucht ihn nicht. */
.ao-kontext__schalter { display: none; }
.ao-block__titel { font-size: 12px; }
.ao-feld b { font-size: 12px; }
.ao-zahl b { font-size: 20px; }
.ao-werkzeug__titel { font-size: 12.5px; }

/* Die Ausfuehrung — im Bild «LIVE STATUS» mit Phase und Prozentzahl. Die
   Prozentzahl hat dort keine Quelle; hier stehen die drei Stufen, die eine
   Handlung wirklich durchlaeuft, als Balken mit drei Abschnitten. */
.ao-stand__leib { display: grid; gap: 5px; }
.ao-stand__titel { font-size: 12.5px; font-weight: 600; color: var(--text-primary); }
.ao-stand__schritt { font-size: 11.5px; color: var(--text-secondary); }
.ao-stand__wert { font-size: 11.5px; color: var(--text-tertiary); font-variant-numeric: tabular-nums; }
.ao-stand__wert--fertig { color: var(--accent-strong); }
.ao-stand__fehler { font-size: 11.5px; color: var(--bad-strong); }
.ao-stand__leib.is-laeuft .ao-takt__i--arbeit { animation: ao-puls 1.1s ease-in-out infinite; }
@media (prefers-reduced-motion: reduce) {
  .ao-stand__leib.is-laeuft .ao-takt__i--arbeit { animation: none; }
}

.ao-lage { padding: 11px 15px; font-size: 12px; border-color: var(--ao-kante); }
.ao-lage__ic { width: 26px; height: 26px; }

/* =========================================================================
   Tablet und Handy — eigener Block NACH den Basisregeln dieses Passes.
   ========================================================================= */
@media (max-width: 1000px) {
  /* MUSS hier stehen: die einspaltige Regel des alten Blocks steht VOR diesem
     Pass — eine gleich starke Regel danach schlaegt sie, auch aus einem
     @media heraus (Memory project_css_cascade_mobile). Ohne diese Zeile stand
     das Raster am Handy wieder zweispaltig und die Eingabe lag unter der
     Kontext-Spalte. */
  .ao-raster { grid-template-columns: minmax(0, 1fr); }
  .ao-verlauf { max-height: 52vh; }
  /* Am Handy zuerst der Verlauf, die Ausfuehrung als Blatt darunter: der Kopf
     wird zur Zeile, auf die man tippt, der Rumpf klappt auf. Zugeklappt steht
     die Chat-Spalte allein — genau die Gestalt, die Block B fuer Faelle,
     Pool und Standorte gesetzt hat. */
  .ao-kontext { padding: 0; gap: 0; }
  .ao-kontext__kopf { padding: 13px 15px; min-height: 44px; }
  .ao-kontext__kopf h2 { flex: 1 1 auto; }
  .ao-kontext__schalter {
    display: grid; place-items: center;
    width: 44px; height: 44px; margin: -8px -10px -8px 0; padding: 0;
    background: transparent; border: 0; border-radius: var(--radius-card);
    color: var(--text-tertiary); cursor: pointer;
  }
  .ao-kontext__schalter svg { width: 18px; height: 18px; transition: transform var(--transition); }
  .ao-kontext__schalter:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
  .ao-kontext__leib { display: none; padding: 0 15px 15px; }
  .ao-kontext.is-offen .ao-kontext__kopf { border-bottom: 1px solid var(--border); }
  .ao-kontext.is-offen .ao-kontext__kopf h2 { color: var(--text-primary); }
  .ao-kontext.is-offen .ao-kontext__schalter { color: var(--accent); }
  .ao-kontext.is-offen .ao-kontext__schalter svg { transform: rotate(180deg); }
  .ao-kontext.is-offen .ao-kontext__leib { display: grid; padding-top: 14px; }
}

@media (max-width: 640px) {
  .ao-chat__kopf { padding: 11px 13px; }
  .ao-chat__titel { font-size: 14px; }
  .ao-verlauf { padding: 12px 13px 4px; }
  .ao-eingabe { padding: 4px 13px 13px; }
  .ao-blase { max-width: 88%; }
  .ao-mission { padding: 10px; }
  /* Am Handy teilen sich Schritt und Frist keine Zeile mehr: nebeneinander
     blieb vom Schritt «Offerte erfassen · 1 …» uebrig. Der Schritt bekommt
     die Zeile, die Frist rueckt rechts darunter. */
  .ao-mission__zeile { flex-wrap: wrap; row-gap: 1px; }
  .ao-mission__schritt { flex: 1 1 100%; }
  .ao-mission__frist { margin-left: auto; }
  .ao-werkzeugwahl__liste { grid-template-columns: minmax(0, 1fr); }
}

/* Der Tapflaechen-Boden gilt auf jedem Touch-Geraet, nicht nur unter 640px
   (Memory project_tablet_touch_breakpoint: 768/1024px sind die Bruchzone). */
@media (max-width: 1024px), (pointer: coarse) {
  .ao-ic { width: 44px; height: 44px; }
  .ao-eingabe__senden { width: 56px; min-height: 44px; }
  .ao-mission { min-height: 44px; padding: 12px 10px; }
  .ao-werkzeugwahl__knopf { min-height: 44px; }
  .ao-anhang__weg { width: 44px; height: 44px; margin: -12px -10px -12px 0; }
}

/* ============================================================
   Patch-Integration — Namensraum ck-; Quelle: docs/design/patch-cockpit.css
   Der Block wird bei Integration als GANZES ersetzt, nie editiert.
   Cockpit + Mein Tag nach Owner-Referenz (Team Cockpit, Welle 31.07.).
   ============================================================ */
/* =========================================================================
   Der Tag des Teams — der Umschalter «Team» auf «Heute» (#/m/my-leads).

   STAND 01.08.2026 (Karte, Positionen 1 und 6): Diese Datei trug bis heute
   ZWEI Flächen — das Lead-Cockpit `#/m` und «Mein Tag» `#/m/today`. Beide sind
   zu: das Cockpit war die zweite Fassung der Zentrale, «Team heute» ist der
   Umschalter «Team» auf «Heute» geworden. Alle Regeln, die nur sie benutzt
   haben, sind mit ihnen entfernt — namentlich die Namensräume `ck-kacheln`,
   `ck-mini`, `ck-karte`, `ck-chip`, `ck-runden`, `ck-tabelle`, `ck-wer`,
   `ck-akt`, `kz-tile`, `kz-akt__*`, `kz-leer`, `kz-mini--zwei`, die
   mitgenutzten `.stalling-row`, `.flow-*`, `.trend-card` und `.goal-bar__fill`,
   sowie `mt-person*` und `mt-zahl` (der Aktivitäts-Abschnitt des Team-Tags —
   sein Ort ist «Verlauf» und die Team-Übersicht). Keine dieser Klassen hat
   noch einen Verwender in `public/src` (mechanisch geprüft, Klasse für Klasse).

   W14.1 (12.08.2026) — DAS FÜHRUNGS-COCKPIT KEHRT ZURÜCK (Verlust 19). Die vier
   Instrumente (Zielerreichung, erwarteter Wert, Verlauf, Was liegen bleibt) sind
   jetzt in EINER Fläche zusammengeführt: `#/m/goals` (public/src/views/
   manager-goals.js, nur Führung — Gesetz 21). Dafür kommen die Namensräume
   `ck-ziel*`, `ck-forecast*` und `ck-trend*` als Abschnitt 5 unten zurück; die
   Balken lesen `.soll-ist__bar` NICHT mehr (eigene `ck-ziel__bar`), das Ist
   steht als GEZÄHLT neben der HOCHGERECHNETEN Zahl (Zwei-Zahlen-Kanon).

   Was bleibt, ist die Anatomie der Owner-Referenz für den verbliebenen Inhalt
   (`docs/design/referenzen/Portaluikomplett/ChatGPT Image 29. Juli 2026,
   13_25_27.png`): jeder Abschnitt ein Panel auf gehobener Fläche mit türkis
   getönter Kante und 14px Radius · Symbol-Quadrat an Kachel und Abschnittskopf ·
   dichte Grade (Zahl 22px, Label CAPS 10.5px/.08em, Subzeile 11.5px) ·
   leuchtende Balken · Listen als ruhige Zeilen mit Trennlinien.

   BEREICHSFARBEN: der Wurzelknoten der View trägt `class="ck gz"` — die sieben
   Bereichstöne haben EINE Quelle (public/style.css, Block «patch-zentrale.css»);
   sie hier ein zweites Mal zu definieren wäre die Wurzel des nächsten
   Farbbruchs. Wiederverwendet statt nachgebaut: .panel, .stat, .stat__bar,
   .badge, .ghost-btn.
   ========================================================================= */

/* --- 0. Die Kante der Referenz ------------------------------------------ */
/* Türkis getönt, nicht grau: das ist die Farbwahrheit der Vorlage. Eine
   Variable, damit ein späterer Owner-Entscheid EINE Zeile ist. */
.ck {
  --ck-kante: rgba(var(--accent-rgb), .16);
  --ck-schein: 0 0 9px rgba(var(--accent-rgb), .45);
}

/* --- 1. Jeder Abschnitt ein Panel --------------------------------------- */
/* FLACH STATT KASTEN (Owner «Widget», 2026-08-13): fuenf umrandete Panels
   untereinander waren die letzte geschlossene Kasten-Sammlung der Software
   (gemessen im Breitenscan 13.08.: /m/goals war die einzige Flaeche von 22,
   die nach dem Wurzel-Schnitt noch Kaesten trug). Gliederung jetzt wie
   ueberall: Versalien-Kopf (`.ck-panel__titel`, gleich darunter) und eine
   Haarlinie zwischen den Abschnitten. 17px = 16px + die 1px des Rahmens. */
.ck .ck-panel {
  background: transparent;
  border: 0;
  border-top: 1px solid var(--border);
  border-radius: 0;
  padding: 17px 0;
}
.ck .ck-panel:first-child { border-top: 0; padding-top: 0; }

/* --- 2. Panel-Kopf: Zeichen · Abschnittslabel · Tür --------------------- */
/* Die Referenz führt ihre Abschnitte als gesperrte Versalien («PROJEKT
   OVERVIEW», «AKTIVE AGENTEN», «SYSTEM PERFORMANCE»). Gross geschrieben wird
   in der CSS, nicht im DOM: der Titel bleibt vorlesbar, durchsuchbar und
   kopierbar — und die Prüfung liest weiter denselben Text. */
.ck .panel__header { align-items: center; margin-bottom: 12px; gap: 12px; }
.ck .ck-titel { display: flex; align-items: center; gap: 9px; min-width: 0; }
.ck .ck-titel .gz-ic { --gz-ic-gr: 24px; }
.ck .ck-panel h3 {
  display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; min-width: 0;
  font-size: 11px; font-weight: 600; letter-spacing: .08em;
  text-transform: uppercase; color: var(--text-secondary);
}
/* Der Zusatz am Titel bleibt gemischt geschrieben — gesperrte Versalien tragen
   in diesem System genau eine Aufgabe, das Abschnittslabel (EINHEIT.md 1.5). */
.ck .ck-panel h3 .panel__hint {
  text-transform: none; letter-spacing: 0; font-weight: 500;
  font-size: 11.5px; color: var(--text-tertiary);
}
/* «Alle anzeigen →» wie in der Referenz: der Pfeil sitzt am Wort. */
.ck .ck-mehr { display: inline-flex; align-items: center; gap: 6px; }
.ck .ck-mehr svg { width: 13px; height: 13px; }

/* --- 3. Kachel-Anatomie ------------------------------------------------- */
/* Zeichen · GROSSE Zahl · CAPS-Label · graue Subzeile · schlanker Balken. */
.ck .ck-kachel {
  display: flex; flex-direction: column; align-items: flex-start;
  gap: 4px; padding: 13px 15px;
  background: var(--surface); border: 1px solid var(--ck-kante); border-radius: var(--radius-card);
}
.ck .ck-kachel .gz-ic { --gz-ic-gr: 26px; margin-bottom: 6px; }
.ck .ck-kachel .stat__value {
  font-size: 22px; font-weight: 650; letter-spacing: -.5px; line-height: 1.1;
}
/* Rot steht an der Zahl, die warnt — sparsam, wie in der Referenz. Die Farbe
   setzt die View zusätzlich als Attribut: ein Beweis, der nur mit angehängter
   Datei grün wird, wäre kein Beweis. Sobald der Patch in style.css steht, darf
   das Attribut fallen — diese Regel ist dann sein Zuhause. */
.ck .ck-kachel .stat__value.is-warn { color: var(--bad-strong); }
.ck .ck-kachel .stat__label {
  font-size: 11px; font-weight: 600; letter-spacing: .08em;
  text-transform: uppercase; color: var(--text-secondary);
  /* Kein `nowrap` mit Auslassungspunkten: «WV ÜBERFÄLLIG» als «WV ÜBER…»
     ist genau das Billige, das hier verschwinden soll. Die Zeile bricht um,
     die Kacheln bleiben durch das Raster gleich hoch. */
  white-space: normal; overflow: visible; text-overflow: clip; line-height: 1.35;
}
.ck .ck-kachel .stat__sub { font-size: 11.5px; line-height: 1.35; }
.ck .ck-kachel .stat__bar { align-self: stretch; margin-top: auto; height: 3px; }
.ck .ck-kachel--klein { padding: 11px 13px; }
.ck .ck-kachel--klein .gz-ic { --gz-ic-gr: 22px; margin-bottom: 4px; }
.ck .ck-kachel--klein .stat__value { font-size: 19px; letter-spacing: -.3px; }

/* --- 4. Leerfall -------------------------------------------------------- */
/* ENTFERNT, nicht ersetzt: .ck .ck-leer · .ck .ck-leer__weg (+ :hover, :focus-visible)
   GEFALLEN 21.08.2026 — die Leer-Zeile des Hauses ist EINE Form:
   `.empty-state.empty-state--zeile` + `.empty-state__weg` in docs/design/grund.css.
   Der Helfer, der sie baute, stand zeichengleich auch in views/zentrale.js
   unter dem Namen `gz-leer` — zwei Namen, EIN Satz. */

/* --- 5. Führungs-Cockpit (W14.1): die vier Instrumente in EINER Fläche ---- */
/* Die kleine graue Subzeile des Cockpits bekommt im .ck-Raum ein Zuhause —
   bis hierher erbte `gz-sub` nur (dieselbe Rolle wie `.stat__sub`). */
.ck .gz-sub { font-size: 11.5px; line-height: 1.4; color: var(--text-secondary); }
.ck .gz-sub i { font-style: normal; color: var(--text-tertiary); }

/* Der Kopf trägt Titel + die Frage des Monatsendes, die Monatswahl rechts. */
.ck .ck-kopf .panel__header { align-items: flex-start; }
.ck .ck-kopf h2 { font-size: 19px; font-weight: 650; letter-spacing: -.2px; margin: 0; }
.ck .ck-kopf__frage { margin: 4px 0 0; max-width: 60ch; }
.ck .ck-titel > div { min-width: 0; }

/* Erwarteter Wert + Verlauf teilen sich eine Reihe. */
.ck-raster { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; margin: 14px 0; }

/* Zielerreichung: je Ziel eine Zeile mit Balken, zwei Zahlen und Status. */
.ck-ziel-gruppe { margin-top: 12px; }
.ck-ziel-gruppe:first-child { margin-top: 6px; }
.ck-ziel-gruppe__kopf {
  font-size: 11px; font-weight: 600; letter-spacing: .08em; text-transform: uppercase;
  color: var(--text-tertiary); margin-bottom: 8px;
}
.ck-ziel { padding: 8px 0; }
.ck-ziel + .ck-ziel { border-top: 1px solid var(--border); }
.ck-ziel__kopf { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 6px; }
.ck-ziel__label { font-size: 13px; font-weight: 600; color: var(--text-primary); }
/* Der Balken zeigt das GEZÄHLTE Ist; die Marke sitzt auf ihm (nicht verdeckt),
   wo die Hochrechnung landet. Das Füllstück wird beschnitten, die Ebene mit der
   Marke nicht. */
.ck-ziel__bar { position: relative; height: 8px; border-radius: 999px; background: var(--surface-3); }
.ck-ziel__bar > i { display: block; height: 100%; border-radius: 999px; overflow: hidden; transition: width .3s ease; }
.ck-ziel__marke {
  position: absolute; top: -3px; width: 2px; height: 14px; border-radius: 2px;
  background: var(--text-primary); opacity: .55; transform: translateX(-1px);
}
.ck-ziel__zahlen { display: flex; flex-wrap: wrap; gap: 4px 16px; margin-top: 6px; font-size: 12px; }
.ck-ziel__zahlen span { color: var(--text-secondary); }
.ck-ziel__zahlen i { font-style: normal; font-size: 11px; color: var(--text-tertiary); }
.ck-ziel__wert { color: var(--text-primary); font-variant-numeric: tabular-nums; }

/* Erwarteter Wert (Forecast): eine grosse Zahl, darunter die Rechnung offen. */
.ck-forecast { display: flex; flex-direction: column; gap: 8px; }
.ck-forecast__zahl { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.ck-forecast__wert { font-size: 24px; font-weight: 650; letter-spacing: -.5px; color: var(--text-primary); font-variant-numeric: tabular-nums; }
.ck-forecast__rechnung, .ck-forecast__rest { margin: 0; }
.ck-forecast__rechnung b { color: var(--text-primary); font-variant-numeric: tabular-nums; }
.ck-forecast__rest b { color: var(--text-secondary); font-variant-numeric: tabular-nums; }

/* Verlauf: Label · Kurve (füllt) · aktueller Wert + Δ-Chip. */
.ck-trend { display: grid; grid-template-columns: auto 1fr auto; align-items: center; gap: 12px; padding: 7px 0; }
.ck-trend + .ck-trend { border-top: 1px solid var(--border); }
.ck-trend__label { font-size: 12.5px; font-weight: 600; color: var(--text-secondary); min-width: 9ch; }
.ck-trend__kurve { display: block; min-width: 0; color: var(--accent); }
.ck-trend__kurve .sparkline { height: 26px; width: 100%; }
.ck-trend__kurve--leer { color: var(--text-tertiary); font-size: 11px; }
.ck-trend__wert { display: inline-flex; align-items: center; gap: 8px; font-variant-numeric: tabular-nums; }
.ck-trend__jetzt { font-size: 14px; font-weight: 650; color: var(--text-primary); }
.ck-trend__delta { padding: 1px 7px; border-radius: var(--radius-badge); font-size: 11px; font-weight: 600; }

/* Ziele setzen: der Editor sitzt im Cockpit-Panel; die goal-* Klassen bleiben. */
.ck-editor .goal-cards { margin-top: 4px; }
.ck-gesperrt h2 { font-size: 18px; margin: 0 0 8px; }

/* =========================================================================
   DER TAG DES TEAMS
   Oben die sechs Tageszahlen als Kachelzeile, darunter die Wiedervorlagen als
   ruhige Panel-Rows. Vorher waren es drei rahmenlose Blöcke mit gleichförmigen
   Zeilen und keiner einzigen Kennzahl obenauf — «endlose Listen» im Wortsinn.
   ========================================================================= */
.ck .mt-kacheln {
  display: grid; grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: 10px; margin-bottom: 16px;
}
/* Termin- und Wiedervorlage-Zeilen: Zeit links als Anker, Firma als Titel,
   Chip rechts, Menschen darunter. Eine Zeile, drei Spuren — keine Kästchen. */
.ck .mt-zeile {
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center; gap: 12px;
  width: 100%; padding: 10px 0; text-align: left;
  background: none; border: 0; border-radius: var(--radius-card); color: inherit; font: inherit; cursor: pointer;
}
.ck .mt-zeile + .mt-zeile { border-top: 1px solid var(--border); }
.ck .mt-zeile:hover { background: var(--surface-2); }
.ck .mt-zeile:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.ck .mt-zeile__zeit {
  display: grid; justify-items: center; gap: 1px; min-width: 58px;
  font-variant-numeric: tabular-nums;
}
.ck .mt-zeile__zeit b { font-size: 14px; font-weight: 650; color: var(--text-primary); }
.ck .mt-zeile__zeit i { font-style: normal; font-size: 11px; font-weight: 600; letter-spacing: .08em; text-transform: uppercase; color: var(--text-tertiary); }
.ck .mt-zeile--spaet .mt-zeile__zeit b,
.ck .mt-zeile--spaet .mt-zeile__zeit i { color: var(--bad-strong); }
.ck .mt-zeile__leib { display: grid; gap: 2px; min-width: 0; }
.ck .mt-zeile__titel {
  font-size: 13px; font-weight: 600; color: var(--text-primary);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ck .mt-zeile__sub { display: flex; flex-wrap: wrap; gap: 2px 10px; font-size: 11.5px; color: var(--text-secondary); }
.ck .mt-zeile__sub .mt-rolle { font-size: 11px; font-weight: 600; letter-spacing: .08em; text-transform: uppercase; color: var(--text-tertiary); }
.ck .mt-zeile__ende { display: flex; align-items: center; gap: 8px; flex: 0 0 auto; }
.ck .mt-gruppe {
  display: flex; align-items: center; gap: 8px;
  margin: 14px 0 2px; font-size: 11px; font-weight: 600; letter-spacing: .08em;
  text-transform: uppercase; color: var(--text-tertiary);
}
.ck .mt-gruppe:first-child { margin-top: 0; }
.ck .mt-gruppe svg { width: 13px; height: 13px; }
.ck .mt-gruppe__zahl { color: var(--text-secondary); font-variant-numeric: tabular-nums; }
.ck .mt-gruppe--spaet { color: var(--bad-strong); }

/* --- 5. Tablet: das Raster faltet, die Reihen rücken zusammen ----------- */
@media (max-width: 1240px) {
  .ck .mt-kacheln { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

/* --- 6. Handy 390px ----------------------------------------------------- */
@media (max-width: 640px) {
  .ck .ck-panel { padding: 14px; }
  .ck .mt-kacheln { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
  .ck .mt-zeile { grid-template-columns: auto minmax(0, 1fr); row-gap: 6px; }
  .ck .mt-zeile__ende { grid-column: 2; }
  .ck .mt-zeile__titel { white-space: normal; }
  /* W14.1 — Cockpit am Handy: die zwei Spalten falten, die Zahlen rücken enger. */
  .ck-raster { grid-template-columns: 1fr; gap: 10px; margin: 10px 0; }
  .ck .ck-kopf .panel__header { flex-wrap: wrap; gap: 10px; }
  .ck-ziel__zahlen { gap: 3px 12px; }
  .ck-forecast__wert { font-size: 21px; }
}

/* --- 7. Tapflächen-Boden ------------------------------------------------ */
/* Gilt auf JEDEM Touch-Gerät, nicht nur unter 640px: 768/1024px sind die
   Bruchzone (Memory project_tablet_touch_breakpoint). */
@media (max-width: 1024px), (pointer: coarse) {
  .ck .ck-kachel,
  .ck .mt-zeile { min-height: 44px; }
  /* .ck .ck-leer__weg ist raus: der Touch-Boden steht am Haus-Weg
     (`.empty-state__weg`, grund.css) und gilt damit fuer jede Leer-Zeile. */
  .ck .ck-mehr { min-height: 44px; display: inline-flex; align-items: center; }
}

/* ============================================================
   Patch-Integration — Namensraum lx-; Quelle: docs/design/patch-chrome.css
   Der Block wird bei Integration als GANZES ersetzt, nie editiert.
   Seitenleiste + Kopfzeile nach Owner-Referenz (Team Chrome, Welle 31.07.).
   ============================================================ */
/* =========================================================================
   Die Schale — Seitenleiste und Kopfzeile.
   Quelle: docs/design/patch-chrome.css   ·   Markup: public/src/components/app-chrome.js

   Referenz (Bild gegen Bild):
   docs/design/referenzen/Portaluikomplett/ChatGPT Image 29. Juli 2026, 13_25_27.png
   Gesetz: docs/design/EINHEIT.md §1.1/§1.2 (Wortmarke + Beiname), §3.1–§3.5
   (eine Navigation, Kopfzeile, aktive Marke, Schnellaktionen).

   Was die Referenz zeigt und was hier gebaut wird:
     1. Wortmarke `LoopX13` mit `Agent OS` darunter, danach eine Trennlinie
     2. ruhige Hauptpunkte, Symbol + Wort; der aktive als türkis getönte PILLE
        mit eigener Kante — nicht als Balken am linken Rand
     3. Kasten «System-Status»: CAPS-Label, Zustandssatz, Rechenweg, Balken
        mit Türkis-Schein
     4. Kasten «Schnellaktionen»: CAPS-Label, Zeilen mit Kreis-Symbol
     5. Profilzeile: Initialen-Kreis, Name, Rolle, Einklapp-Chevron
     6. Kopfzeile: Suchfeld links-mittig mit Tastenkürzel, rechts Glocke
        (mit Zähler) und Konto

   Dieselbe Sprache wie docs/design/patch-zentrale.css (Rahmen-und-Farbe-Pass):
   Kästen auf var(--surface), Kante rgba(var(--accent-rgb), .16), Radius 14px,
   CAPS-Label 10.5px/.08em, Balken mit Türkis-Schein. Präfix `lx-` für alles
   Neue; bestehende Klassen (.nav-tab, .sidebar__*, .stat__bar) werden benutzt
   und hier gezielt überschrieben — diese Datei wird an style.css ANGEHÄNGT und
   steht darum nach allen Basisregeln (Memory project_css_cascade_mobile).
   ========================================================================= */

.sidebar, .lx-top { --lx-kante: rgba(var(--accent-rgb), .16); }

/* ---------- 0. Die Leiste selbst ---------------------------------------- */
/* Die Referenz ist DICHT: schmale Zeilen, wenig Luft, feine Kanten. Die
   Kästen und die Profilzeile sitzen unten, die Navigation nimmt den Rest. */
.sidebar { gap: 0; padding: 0; }
.sidebar__top {
  padding: 0 14px; min-height: 68px; align-items: center;
  border-bottom: 1px solid var(--border); margin-bottom: 12px;
}
.sidebar__nav { gap: 1px; padding: 0 10px; flex: 0 0 auto; }
.sidebar__kaesten {
  display: flex; flex-direction: column; gap: 10px;
  margin-top: 14px; padding: 14px 10px 0;
  border-top: 1px solid var(--border);
}
/* 08.09.2026 · AM SCHREIBTISCH IST DIESES FACH LEER — ALSO STEHT ES NICHT DA.
   Es traegt genau zwei Dinge: die Suchzeile (`.lx-suchzeile`, ab 901 px aus —
   dort traegt der Kopf die Suche) und die Assistenten-Zeile
   (`.lx-agent-zeile`, ab 901 px aus — dort steht sein Knopf im Kopf). Solange
   der Kasten «Schnellaktionen» dazwischen stand, war das Fach am Rechner
   trotzdem gefuellt. Er ist fort; gemessen blieben 15 px reine Haarlinie mit
   14 px Luft und NICHTS darunter — genau der leere Rahmen, den
   `sidebarMarkup` fuer die Aussenrollen schon von Hand vermeidet. */
@media (min-width: 901px) { .sidebar__kaesten { display: none; } }
.sidebar__footer {
  margin-top: auto; padding: 10px; border-top: 1px solid var(--border);
  display: block;
}

/* ---------- 1. Wortmarke (EINHEIT §1.1/§1.2) ---------------------------- */
.lx-marke {
  display: flex; align-items: center; gap: 10px; min-width: 0;
  text-decoration: none; color: var(--text-primary);
}
.lx-marke__signet { flex: none; width: 34px; height: 20px; color: var(--accent); }
.lx-marke__text { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
/* «LoopX13» bleibt EINZEILIG (§1.1: nie zweizeilig umgebrochen). */
.lx-marke__wort {
  font-size: 12.5px; font-weight: 700; line-height: 1;
  letter-spacing: -.01em; white-space: nowrap; color: var(--text-secondary);
}
.lx-marke__wort em { font-style: normal; color: var(--accent); }
/* «Agent OS» ist der Beiname der Innenseite (§1.2) — korrekt geschrieben,
   nicht als gesperrte Versalien, aber mit dem Gewicht der Referenz: er trägt
   den Block, die Wortmarke steht klein darüber. */
.lx-marke__bei {
  font-size: 19px; font-weight: 600; line-height: 1.05;
  letter-spacing: -.02em; color: var(--text-primary); white-space: nowrap;
}
/* Die Wortmarke ist ein LINK (zur Zentrale) — am Finger also ein Ziel und
   kein Bild. Ihre Höhe entstand bisher aus der Summe zweier Zeilen und lag
   bei 33 px (E1d-Kleinteil, Rundgang 08.08.). */
@media (max-width: 1024px), (pointer: coarse) {
  .lx-marke { min-height: 44px; }
}

/* ---------- 2. Die Hauptpunkte ------------------------------------------ */
.sidebar .nav-tab {
  gap: 10px; padding: 8px 11px; min-height: 36px; border-radius: var(--radius-button) /* ein wählbarer Punkt ist ein Knopf, keine Karte (v395) */;
  border: 1px solid transparent; font: 500 13.5px/1 inherit;
}
.sidebar .nav-tab:hover { background: rgba(var(--tint-rgb), .05); color: var(--text-primary); }
/* Der aktive Punkt ist die GEFÜLLTE Türkis-Pille der Referenz (13_25_27,
   «Cockpit»: satte Füllung, dunkle Schrift). Die getönte Fassung davor war
   im Nebeneinander kaum vom Hover zu unterscheiden — Material-Pass 31.07.,
   dritter Nebeneinander-Beleg.
   Der Hof, den derselbe Pass mitbrachte, ist am 03.08. entfernt: Schnitt
   durch 13_25_27.png bei x=520 zeigt unter der Pille 2,12,18 gegen den
   Grund 3,12,18 — kein angehobenes Pixel. Füllung ja, Schein nein. */
.sidebar .nav-tab.active {
  background: var(--accent);
  border-color: transparent;
  color: var(--on-accent);
}
.sidebar .nav-tab.active .nav-tab__icon { color: var(--on-accent); }
.sidebar .nav-tab__icon { width: 18px; height: 18px; }
.sidebar .nav-tab__icon svg { width: 18px; height: 18px; }

/* ---------- 3. Kasten «Schnellaktionen» (EINHEIT §3.5) ------------------ */
/* Karte 01.08., Position 7: Hier stand darüber der Kasten «System-Status». Er
   zeigte auf JEDER der 28 Flächen denselben Nicht-Satz «Noch nicht gemessen» —
   und dieselbe Aussage stand noch zweimal daneben (Zentrale-Spalte, eigene
   Fläche). Sie hat jetzt genau einen Ort: die Systemlage. Mit dem Kasten sind
   `.lx-lage*` entfernt; kein Verwender mehr in public/src. */
/* 08.09.2026 · UND HIER STAND DER KASTEN «SCHNELLAKTIONEN» (`.lx-schnell*`,
   8 Regeln plus 4 Geräte-Regeln weiter unten). Er ist fort — Owner 07.09.:
   «Die Schnellaktionen links an der Seite: Die nehmen die Hälfte ein.»
   Gemessen auf der Fundament-Bühne, Kasten gegen `.sidebar__nav` (die Türen):
       Admin   1440 px   215 x 226 px   ·   Türen 235 x 359 px
       Berater 1440 px   215 x 191 px   ·   Türen 235 x  79 px
       Berater  390 px   247 x 231 px   ·   Türen 267 x  89 px
   Es geht nichts verloren: derselbe Katalog (QUICK_ITEMS) steht weiter im
   «+»-Knopf bzw. am Ziel «Neu» der Daumenleiste und in der Befehlssuche.
   Das Markup ist in components/app-chrome.js § 3 begründet. */

/* ---------- Der Assistent in der Seitenleiste (nur Handy) ----------------
   Am Desktop steht sein Knopf im Kopf (`.lx-top__agent`) — dort ist Platz,
   und die Referenz zeigt die Werkzeuge oben rechts. Am Handy traegt der Kopf
   nur Identitaet und Konto, also zieht der Assistent hierher: in die
   Seitenleiste, die unten ueber «Mehr» aufgeht. Er steht dort als Zeile mit
   Symbol UND Wort wie jeder Hauptpunkt, nicht als unerklaerter Blitz.
   AUS am Desktop — sonst gaebe es ihn zweimal sichtbar (EINHEIT §3.1). */
.lx-agent-zeile { display: none; }
@media (max-width: 900px) {
  .lx-agent-zeile {
    display: flex; align-items: center; gap: 10px; width: 100%;
    min-height: 44px; padding: 8px 10px;
    border: 1px solid var(--lx-kante); border-radius: var(--radius-card);
    background: var(--surface); color: var(--text-secondary);
    font: 550 13px/1 inherit; text-align: left; cursor: pointer;
  }
  .lx-agent-zeile.is-offen { color: var(--accent); border-color: var(--accent-line); }
  .lx-agent-zeile:active { background: var(--surface-hover); }
  .lx-agent-zeile__ic {
    display: inline-flex; align-items: center; justify-content: center; flex: none;
    width: 24px; height: 24px; border-radius: var(--radius-badge);
    border: 1px solid var(--border); color: var(--text-tertiary);
  }
  .lx-agent-zeile__ic svg { width: 13px; height: 13px; }
  .lx-agent-zeile.is-offen .lx-agent-zeile__ic { border-color: var(--accent-line); color: var(--accent); }
}

/* ---------- 4. Profilzeile ---------------------------------------------- */
.lx-profil { display: flex; align-items: center; gap: 4px; }
.lx-profil__wer {
  flex: 1; min-width: 0; display: flex; align-items: center; gap: 10px;
  min-height: 44px; padding: 5px 6px; border: 0; border-radius: var(--radius-card);
  background: transparent; color: inherit; cursor: pointer; text-align: left;
  font: inherit;
}
.lx-profil__wer:hover { background: rgba(var(--tint-rgb), .05); }
.lx-avatar {
  display: inline-flex; align-items: center; justify-content: center; flex: none;
  width: 34px; height: 34px; border-radius: 999px;
  background: var(--accent); color: var(--on-accent);
  font: 700 12.5px/1 inherit; letter-spacing: .02em;
}
.lx-avatar--klein { width: 32px; height: 32px; font-size: 12px; }
.lx-profil__text { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.lx-profil__text strong {
  font: 600 13px/1.2 inherit; color: var(--text-primary);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.lx-profil__rolle {
  font-size: 11.5px; color: var(--text-secondary);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.lx-profil__klapp {
  flex: none; display: inline-flex; align-items: center; justify-content: center;
  width: 34px; height: 44px; border: 0; border-radius: var(--radius-card);
  background: transparent; color: var(--text-tertiary); cursor: pointer;
}
.lx-profil__klapp:hover { background: rgba(var(--tint-rgb), .05); color: var(--text-primary); }
.lx-profil__klapp-ic { display: inline-flex; width: 16px; height: 16px; transform: rotate(180deg); }
.lx-profil__klapp-ic svg { width: 16px; height: 16px; }

/* ---------- 5. Die Kopfzeile (EINHEIT §3.2) ----------------------------- */
/* Sie sitzt im Inhaltsbereich und zieht sich über dessen Polsterung hinaus an
   die Kanten — so läuft sie wie in der Referenz von der Seitenleiste bis zum
   rechten Rand. Sie klebt oben; die Zweitebene (#subnav) scrollt darunter weg.
   Der Seitenrand des Inhalts steht an ZWEI Stellen in style.css (Zeile 198 und
   1096, zwei verschiedene Werte). Er wird hier EINMAL gespiegelt, damit die
   Kopfzeile nicht raten muss — ein geratener Wert ragte am Handy 14px über den
   Bildschirm hinaus. `scripts/_chrome_ui_test.mjs` misst die Spiegelung nach:
   die Kopfzeile MUSS bei 1400px wie bei 390px exakt an beiden Kanten sitzen. */
.main-shell { --lx-rand: clamp(28px, 2.5vw, 56px); }   /* = style.css:198 */
@media (max-width: 720px) { .main-shell { --lx-rand: 14px; } }  /* = style.css:1096 */

.lx-top {
  /* `top` folgt dem SICHTBAREN Fenster, nicht dem Layout-Fenster: verschiebt
     iOS beides gegeneinander (Tastatur, Adressleiste, Pinch), stand die
     Kopfzeile sonst über dem sichtbaren Rand und schnitt die Reiterzeile
     darunter waagrecht durch (c1 B9, c3 B10, c5 B25). Ohne den Beobachter ist
     `--vv-oben` 0 — dann ist das exakt das bisherige `top: 0`. */
  position: sticky; top: var(--vv-oben, 0px); z-index: 30;
  display: flex; align-items: center; gap: 14px;
  min-height: 68px;
  margin: -20px calc(-1 * var(--lx-rand, 28px)) 18px;
  padding: max(0px, var(--sat)) clamp(20px, 2vw, 32px) 0;
  border-bottom: 1px solid var(--border);
  background: var(--topbar-bg); backdrop-filter: blur(18px);
}
.lx-top[hidden] { display: none; }

/* Suchfeld: Input-Optik, aber ein Knopf — er öffnet die Palette (⌘K). */
.lx-top__suche {
  display: flex; align-items: center; gap: 10px;
  width: min(420px, 46%); min-height: 38px; padding: 8px 12px;
  background: var(--surface-inset); border: 1px solid var(--border);
  border-radius: var(--radius-card); color: var(--text-tertiary); cursor: pointer;
  font: 500 13px/1 inherit; text-align: left;
  transition: border-color var(--transition), background var(--transition), color var(--transition);
}
.lx-top__suche:hover { border-color: var(--line-strong); background: var(--surface-hover); color: var(--text-secondary); }
.lx-top__suche-ic { display: inline-flex; flex: none; width: 15px; height: 15px; }
.lx-top__suche-ic svg { width: 15px; height: 15px; }
.lx-top__suche-text { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lx-top__kbd {
  flex: none; font: 500 10.5px/1 inherit; color: var(--text-tertiary);
  border: 1px solid var(--border); border-radius: var(--radius-card); padding: 4px 6px;
  background: rgba(var(--tint-rgb), .03);
}

/* WO BIN ICH? — nur fuer Ohren, auf JEDER Breite (Nachschnitt 18.08.).
   Das Feld traegt `aria-live` und sagt Vorleseprogrammen den Flaechenwechsel
   an, den kein Reiter meldet. SICHTBAR war es bis heute am Rechner, und dort
   war es die dritte Ortsangabe auf demselben Bildschirm: gemessen auf
   `#/v/offers` stand «Offerten» in der Kopfzeile, als aktiver Reiter darunter,
   im Ortsschild darunter und als Titel darunter — VIERMAL dasselbe Wort.
   EINHEIT §3.1 verbietet einen zweiten Satz Navigationspunkte, BEREICHE §11
   die Doppelung, und die Owner-Referenz (`Portaluikomplett/ChatGPT Image
   29. Juli 2026, 13_25_57 (4).png`) traegt oben den PFAD und keinen zweiten
   Ortsnamen. Der Ort steht ab jetzt an genau EINER sichtbaren Stelle: im
   Ortsschild (`components/ortsschild.js`).
   Die Regel stand bis heute im Handy-Block darunter — Kommentar und Code
   sagten dort seit dem 08.08. Verschiedenes («Am Desktop bleibt das Feld
   leer»), und der Code gewann. */
.lx-top__wo {
  position: absolute; width: 1px; height: 1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}

/* Rechte Gruppe, durch eine Haarlinie abgesetzt wie in der Referenz. */
.lx-top__rechts {
  margin-left: auto; display: flex; align-items: center; gap: 6px;
  padding-left: 14px; border-left: 1px solid var(--border);
}

/* Die Glocke behält ihre Klassen aus components/notifications.js (zwei
   ausgelieferte Prüfläufe greifen sie darüber). In der Kopfzeile wird sie zum
   quadratischen Symbolknopf mit Zähler-Punkt — die Wortzeile blendet aus. */
.lx-top .sidebar__search {
  width: 40px; min-width: 40px; height: 40px; min-height: 40px;
  margin: 0; padding: 0; justify-content: center; position: relative;
  background: transparent; border-color: transparent; color: var(--text-secondary);
}
.lx-top .sidebar__search:hover { background: rgba(var(--tint-rgb), .06); border-color: transparent; color: var(--text-primary); }
.lx-top .sidebar__search-ic { width: 19px; height: 19px; }
.lx-top .sidebar__search-ic svg { width: 19px; height: 19px; }
.lx-top .sidebar__search-label { display: none; }
.lx-top .lx-bell__count {
  position: absolute; top: 3px; right: 2px; margin: 0;
  min-width: 16px; padding: 0 4px; font-size: 11px; line-height: 16px;
  border: 2px solid var(--surface-1);
}

.lx-top__konto {
  display: inline-flex; align-items: center; justify-content: center;
  width: 40px; height: 40px; padding: 0; border: 0; border-radius: 999px;
  background: transparent; cursor: pointer;
}
.lx-top__konto:hover { background: rgba(var(--tint-rgb), .06); }

/* ---------- «Neu» am Schreibtisch (08.09.2026) --------------------------
   DIE ANDERE HAELFTE DER LOESCHUNG des Kastens «Schnellaktionen». Gemessen:
   ab 1024 px ist der schwebende «+» aus (grund.css:5451, `@media (min-width:
   901px) { .qc { display: none; } }`) und das Ziel «Neu» am Daumen ebenfalls —
   der geloeschte Kasten war dort der EINZIGE sichtbare Weg zu «Neuer Lead /
   Kunde / Offerte / Termin / Aufgabe». Dieser Griff ist derselbe Weg an dem
   einen Ort, den die Referenz fuer Werkzeuge kennt (EINHEIT §3.2, rechte
   Gruppe): dieselbe runde 40-px-Bauart wie Glocke und Konto daneben.
   UNTER 901 px ist er aus — dort tragen Daumenleiste bzw. «+» den Weg, und
   zwei sichtbare «+» auf einem Bild waeren genau die Doppelung, die dieser
   Bau beendet. */
.lx-top__neu { display: none; }
@media (min-width: 901px) {
  .lx-top__neu {
    display: inline-flex; align-items: center; justify-content: center;
    width: 40px; height: 40px; padding: 0; border: 0; border-radius: 999px;
    background: transparent; color: var(--text-secondary); cursor: pointer;
  }
  .lx-top__neu:hover { background: rgba(var(--tint-rgb), .06); color: var(--text-primary); }
  .lx-top__neu[aria-expanded="true"] { background: rgba(var(--tint-rgb), .10); color: var(--text-primary); }
  .lx-top__neu-ic { display: inline-flex; }
  .lx-top__neu-ic svg { width: 19px; height: 19px; }
  /* Das Menue haengt am Griff statt am schwebenden Knopf. Es ist DASSELBE
     Menue (`#qc-menu`, components/quick-create.js) — kein zweites Markup,
     keine zweite Liste; nur seine Huelle steht hier oben statt unten rechts,
     und nur solange sie offen ist. Angehaengt an `aria-expanded` des Griffs,
     das `toggleMenu` ohnehin schon setzt (`anker`). */
  body:has(.lx-top__neu[aria-expanded="true"]) .qc {
    display: block; top: 72px; right: 18px; bottom: auto;
  }
  body:has(.lx-top__neu[aria-expanded="true"]) .qc__fab { display: none; }
  body:has(.lx-top__neu[aria-expanded="true"]) .qc__menu { position: static; bottom: auto; }
}

/* ---------- 6. Eingeklappt (Desktop) ------------------------------------ */
@media (min-width: 901px) {
  body.sidebar-collapsed .sidebar__top { justify-content: center; padding: 0 8px; }
  body.sidebar-collapsed .lx-marke__text { display: none; }
  body.sidebar-collapsed .sidebar__nav,
  body.sidebar-collapsed .sidebar__kaesten { padding-left: 8px; padding-right: 8px; }
  body.sidebar-collapsed .sidebar .nav-tab { justify-content: center; padding: 8px; }
  body.sidebar-collapsed .lx-profil { flex-direction: column; gap: 2px; }
  body.sidebar-collapsed .lx-profil__wer { justify-content: center; width: 100%; }
  body.sidebar-collapsed .lx-profil__text { display: none; }
  body.sidebar-collapsed .lx-profil__klapp { width: 100%; height: 34px; }
  body.sidebar-collapsed .lx-profil__klapp-ic { transform: rotate(0); }
}

/* Die Wortmarke im Kopf ist eine NUR-HANDY-Zutat: am Desktop traegt die
   Seitenleiste sie, und zweimal dieselbe Marke auf einem Bildschirm ist
   Rauschen. Die Zeile steht bewusst AUSSERHALB des @media-Blocks — stuende
   sie darin, haette das Element am Desktop gar keine Regel und erschiene als
   unformatierter Block links im Kopf (derselbe Desktop-Schaden wie bei
   `.cp__zurueck`, docs/design/patch-konfigurator.css). */
.lx-top__marke { display: none; }

/* ---------- 7. Handy ----------------------------------------------------- */
/* ===========================================================================
   DER HANDY-KOPF TRAEGT IDENTITAET UND KONTO — sonst nichts.
   ---------------------------------------------------------------------------
   Owner-Entscheid 08.08. am eigenen Referenzbild
   (`docs/design/referenzen/Portaluikomplett/ChatGPT Image 29. Juli 2026,
   13_25_27.png`, iPhone links): dort steht oben die Wortmarke und rechts das
   Konto. Keine Werkzeugleiste, kein Titel, keine Kaesten um Symbole. Die
   Suche ist ein Feld IN der Flaeche, die Bereiche liegen unten am Daumen.

   GEMESSEN, was hier vorher stand (390x620, `#/v/offers`):
     Hamburger 44 im Kasten · Suche 44 im Kasten · Titel «Offerten» 117 ·
     Assistent 40 · Glocke 40 · Konto 40
   Sechs Griffe in 52 px Hoehe — und «Offerten» stand DREIMAL auf einem
   Bildschirm: im Kopf, im aktiven Reiter darunter, und als Seitentitel.

   WAS FAELLT UND WOHIN ES GEHT (nichts verschwindet):
     Hamburger  → die Navigation steht unten; «Mehr» oeffnet dieselbe
                  Seitenleiste. Der Knopf bleibt im Baum, nur unsichtbar —
                  ein programmatischer .click() braucht keine Sichtbarkeit.
     Titel      → der aktive Reiter darunter sagt dasselbe Wort.
     Suche      → Feld in der Flaeche (`.vk-suche`), dort wo gesucht wird.
     Assistent  → Zeile in der Seitenleiste (`.lx-agent-zeile`), unter «Mehr».
     Kaesten    → die Referenz kennt keine Rahmen um Kopfsymbole.
   Es bleiben Wortmarke, Glocke MIT Abzeichen (die Zahl der Ungelesenen steht
   sonst nirgends) und Konto.

   Am Desktop aendert sich kein Pixel: jede Regel hier haengt am Handy-
   Breakpoint, und `.lx-top__marke` ist oben ausserhalb abgeschaltet.
   =========================================================================== */
@media (max-width: 900px) {
  /* Der Hamburger faellt. Er lag `fixed` oben links und zwang der Kopfzeile
     60 px Innenabstand auf, in denen nichts stehen durfte.
     ⚠️ NUR, WENN ES DIE DAUMENLEISTE WIRKLICH GIBT. `unterleisteMarkup`
     liefert bei WENIGER ALS ZWEI Tueren nichts zurueck — die Rolle «partner»
     hat genau eine. Ohne diese Bedingung waere bei ihr der Hamburger weg UND
     keine Leiste da: die Seitenleiste mit den Schnellaktionen waere am Handy
     unerreichbar. Beim Durchlesen des eigenen Entwurfs gefunden, bevor ein
     Bild entstand — dieselbe Mechanik nutzen schon Toasts und der
     Plus-Knopf (style.css:12837). */
  body:has(#lx-unten .lx-unten) .sidebar-toggle { display: none; }
  .lx-top {
    /* Der Zug nach oben bleibt: `.main-shell` reserviert am Handy
       `64px + var(--sat)` (style.css:325), und der Kopf holt sich diesen
       Platz zurueck, damit er buendig am oberen Rand sitzt.
       Der untere Abstand faellt von 12 auf 0 — die Reiterzeile darunter
       traegt ihre eigene Trennlinie, ein Spalt dazwischen macht aus zwei
       Ebenen zwei Leisten. */
    margin: calc(-1 * (64px + var(--sat))) calc(-1 * var(--lx-rand, 14px)) 0;
    padding-left: 12px; padding-right: 12px;
    min-height: calc(52px + var(--sat));
    gap: 8px;
  }
  /* Die Kopfzeile SETZT ihre Höhe, die Reiterzeile darunter LIEST sie — genau
     dieselbe Regel wie am Boden (Block «Boden-Geometrie»). Nur wenn es die
     Kopfzeile wirklich gibt: im Papier-/Anmeldemodus wird sie `hidden`. */
  body:has(.lx-top:not([hidden])) { --kopf-h: calc(52px + var(--sat)); }
  /* Identitaet links — dieselbe Wortmarke wie in der Seitenleiste, aus
     demselben Bauteil (`markeMarkup`, app-chrome.js). Keine zweite Wahrheit. */
  .lx-top__marke { display: flex; align-items: center; flex: 1 1 auto; min-width: 0; }
  .lx-top__marke .lx-marke__bei { font-size: 17px; }
  /* Owner 06.08., dritte Meldung zum Handy: «auf dem Smartphone ist die
     Lösung immer noch scheisse.» Am Bild gemessen (#/m/pool, #/m/my-leads):
     Kopfzeile 128 px, darunter Titel und Werkzeugkasten — der INHALT begann
     erst bei 650 von 844 px. Auf seiner eigenen Referenz (iPhone links in
     `13_25_27.png`) ist der Kopf EINE Zeile und darunter steht sofort die
     Arbeit.
     Der Balken «Befehl eingeben oder fragen …» ist am Handy der grösste
     Einzelposten und zugleich der nutzloseste: er öffnet die Befehlspalette,
     die für eine Tastatur gebaut ist.
     08.08.: Er wurde zur Lupe — und war damit ein Symbol ohne Wort in einem
     Kasten, den die Referenz nicht kennt. Jetzt faellt er ganz. Gesucht wird
     in der Flaeche, in der die Treffer stehen (`.vk-suche`); die Palette
     bleibt ueber die Tastatur erreichbar, kostet aber keinen Griff mehr im
     Kopf. */
  .lx-top__suche { display: none; }
  /* `.lx-top__wo` ist seit dem 18.08. auf JEDER Breite nur noch fuer Ohren da
     (Basisregel weiter oben) — hier stand bis dahin die Handy-Fassung. */
  /* Der Assistent zieht in die Seitenleiste (unter «Mehr») — ein Blitz ohne
     Wort im Kopf ist genau das unerklaerte Zeichen, das hier nicht hingehoert.
     Seine Abschaltung steht NICHT hier, sondern beim Knopf selbst
     (style.css, Block «Der Assistent als Seitenpanel»): dort wird er ohne
     @media auf `inline-flex` gesetzt, und die spaetere Regel gewinnt. */
  /* Keine Haarlinie und kein Kasten mehr: rechts stehen nur noch zwei Dinge,
     und die Referenz trennt sie nicht ab. */
  .lx-top__rechts { padding-left: 0; border-left: 0; gap: 2px; }

  /* 18 px Luft unter der Reiterzeile sind am Desktop ein Absatz und am Handy
     ein Drittel einer Karte. Gemessen 08.08. auf 390×620: von 620 px lagen
     18 px zwischen dem letzten Navigationselement und dem ersten Inhalt,
     ohne dass dort etwas steht. Die Reiterzeile trägt unten eine Linie —
     die Trennung ist damit schon gezeichnet, der Abstand wiederholt sie nur.
     Am Desktop bleiben die 18 px unangetastet.

     UND SIE KLEBT (09.08.): Navigation darf nicht unter Navigation
     verschwinden. Die Kopfzeile klebt, die Reiterzeile lag im normalen Fluss —
     beim ersten Scrollen (spätestens wenn Safari seine Adressleiste einklappt)
     schob sie sich zur Hälfte unter den Kopf und blieb dort: «Offerten Kunden
     Rechnungen Post Wissen» waagrecht mittig durchgeschnitten, nur die untere
     Hälfte der Buchstaben sichtbar (c1 B9, c5 B25). Jetzt sitzt sie fest unter
     dem Kopf — `--kopf-h` kommt aus derselben Quelle wie seine `min-height`.
     Die Ruhelage ändert sich dadurch NICHT (sticky nimmt nichts aus dem
     Fluss); es ändert sich nur, was beim Scrollen passiert.
     Die Randüberzieher sind dieselbe Mechanik wie bei `.lx-top`: ohne sie
     deckte der Streifen nur die Breite der Reiter (`width: fit-content`), und
     der Inhalt liefe daneben sichtbar durch. */
  .subnav {
    margin-bottom: 8px;
    position: sticky; top: var(--kopf-h, 0px); z-index: 29;
    width: auto; max-width: none;
    margin-left: calc(-1 * var(--lx-rand, 14px));
    margin-right: calc(-1 * var(--lx-rand, 14px));
    padding-left: var(--lx-rand, 14px);
    padding-right: var(--lx-rand, 14px);
    background: var(--topbar-bg); backdrop-filter: blur(18px);
  }
}
@media (max-width: 420px) {
  .lx-top__suche-text { font-size: 12.5px; }
}

/* ---------- Vorschau: eine fremde Rolle ansehen -------------------------
   Masterplan Welle 3, Punkt 13. Wer eine fremde Fläche ansieht, muss es
   JEDERZEIT sehen und mit einem Griff herauskommen — sonst hält er sie für
   seine eigene und wundert sich, warum die Hälfte fehlt. */
.lx-vorschau {
  position: sticky; top: 0; z-index: 60;
  display: flex; align-items: center; justify-content: center; gap: 14px;
  flex-wrap: wrap;
  padding: 8px 16px calc(8px);
  background: var(--warn-soft, rgba(245, 180, 60, .14));
  border-bottom: 1px solid var(--warn-strong, #f5b43c);
  color: var(--text-primary);
  font-size: 12.5px; line-height: 1.3;
}
.lx-vorschau__wort b { font-weight: 650; }
.lx-vorschau__raus {
  padding: 6px 12px; min-height: 32px;
  border: 1px solid var(--warn-strong, #f5b43c); border-radius: var(--radius-button);
  background: transparent; color: var(--text-primary);
  font: inherit; font-size: 12px; cursor: pointer;
}
.lx-vorschau__raus:hover { background: rgba(245, 180, 60, .12); }
.lx-vorschau__wahl { display: grid; gap: 6px; }
.lx-vorschau__wahl .ghost-btn { width: 100%; justify-content: flex-start; }
/* Der Durchgriff des Eigentuemers (27.08.): erst die Flaeche, dann WESSEN.
   Dieselbe Bauform wie die Rollenwahl darueber — eine Form fuer eine Sache. */
.lx-vorschau__ziel { display: grid; gap: 6px; margin-top: 8px; }
.lx-vorschau__ziel select {
  width: 100%; min-height: 40px; padding: 8px 10px;
  border: 1px solid var(--border); border-radius: var(--radius-button);
  background: var(--surface-1, transparent); color: var(--text-primary); font: inherit;
}
.lx-vorschau__ziel .ghost-btn { width: 100%; justify-content: center; }
.lx-vorschau__laeuft {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  flex-wrap: wrap; margin: 0 0 10px; padding: 8px 10px;
  border: 1px solid var(--warn-strong, #f5b43c); border-radius: var(--radius-button);
  background: var(--warn-soft, rgba(245, 180, 60, .12));
  font-size: 12.5px; line-height: 1.35;
}
.lx-vorschau__laeuft .ghost-btn { flex: 0 0 auto; }
/* Kein eigener Touch-Floor: grund.css:789-793 gibt JEDEM `select` und JEDEM
   `.ghost-btn` seine 44 px — und zwar unter `(max-width:1024px),
   (pointer:coarse)`, also auch auf dem Tablet und auf jedem Finger-Geraet.
   Der erste Entwurf schrieb ihn hier bei 900 px noch einmal ab: dreimal
   dieselbe Wahrheit, und auf einem iPad haette KEINE davon gegriffen
   (Memory «Tablet Touch Breakpoint»). Was bleibt, ist die eine Aussage, die
   das Haus nicht schon kennt — der Kasten wird auf schmal zur Spalte. */
@media (max-width: 900px) {
  .lx-vorschau { padding: 7px 12px; font-size: 12px; gap: 8px; }
  .lx-vorschau__raus { min-height: 44px; }
  .lx-vorschau__laeuft { flex-direction: column; align-items: stretch; }
}

/* ---------- Installations-Fuehrung (P13, 09.08.) -------------------------
   Dieselbe Bauform wie das Vorschau-Band darueber — oben angeheftet, eine
   Zeile, rechts der Weg hinaus. NICHT dieselbe Farbe: das Vorschau-Band warnt
   («du siehst gerade eine fremde Rolle»), dieser Streifen bietet nur etwas an.
   Ein Angebot in Warnfarbe waere gelogen, darum die ruhige Flaeche des
   Systems. Er erscheint hoechstens einmal je Geraet (utils/installation.js). */
/* NICHT klebend — anders als das Vorschau-Band darueber. Zwei Elemente mit
   `sticky; top: 0` liegen beim Scrollen uebereinander, und beide koennen
   gleichzeitig da sein (Owner in der Rollen-Vorschau auf einem Geraet ohne
   installierte App). Ein einmaliger Hinweis darf mitscrollen; eine Warnung,
   in welcher Rolle man gerade sieht, darf es nicht. */
.lx-install {
  position: relative; z-index: 59;
  display: flex; align-items: center; justify-content: flex-end; gap: 10px;
  flex-wrap: wrap;
  padding: 8px 16px;
  background: var(--surface-2, var(--surface));
  border-bottom: 1px solid var(--border);
  color: var(--text-secondary);
  font-size: 12.5px; line-height: 1.3;
}
/* Symbol und Satz bleiben zusammen in EINER Zeile, die Knoepfe wandern nach
   rechts und brechen erst um, wenn der Satz sonst zerquetscht wuerde. Ohne
   diese Verteilung stand auf 390 px das Symbol allein in der ersten Zeile und
   der Streifen war dreizeilig — gemessen am Bild, 09.08. */
.lx-install__ic { display: inline-flex; flex: none; line-height: 0; color: var(--accent-strong); }
.lx-install__ic svg { width: 16px; height: 16px; }
.lx-install__wort { flex: 1 1 200px; min-width: 0; color: var(--text-primary); }
.lx-install__tu, .lx-install__weg {
  flex: none;
  padding: 6px 12px; min-height: 32px;
  border-radius: var(--radius-button);
  background: transparent;
  font: inherit; font-size: 12px; cursor: pointer;
}
.lx-install__tu { border: 1px solid var(--accent); color: var(--text-primary); }
.lx-install__tu:hover { background: var(--surface-hover); }
.lx-install__weg { border: 1px solid var(--border); color: var(--text-secondary); }
.lx-install__weg:hover { background: var(--surface-hover); }
@media (max-width: 900px) {
  .lx-install { padding: 7px 12px; font-size: 12px; gap: 8px; }
  .lx-install__tu, .lx-install__weg { min-height: 44px; }
}

/* ---------- Die Leiste am Daumen (nur Handy) ----------------------------
   Owner 06.08.: auf seiner Referenz (iPhone links in `13_25_27.png`) liegt die
   Navigation UNTEN — fünf feste Ziele, alle mit dem Daumen erreichbar. Bei uns
   lag sie oben links im Hamburger: zwei Griffe und eine Handbewegung über den
   ganzen Bildschirm, jedes Mal. Es sind DIESELBEN Türen wie in der
   Seitenleiste — kein zweites Menü, keine zweite Wahrheit. */
#lx-unten { display: none; }
@media (max-width: 900px) {
  #lx-unten { display: block; }
  /* DIE LEISTE SETZT IHRE HÖHE — jede Fläche liest sie über `--boden-h`.
     68px sind GEMESSEN, nicht gerechnet (Playwright, 390px, sichere Zone 0:
     1px Kante + 6px + 55px Ziel + 6px). Die sichere Zone kommt in `--boden-h`
     einmal dazu, nicht hier — sonst zählte sie doppelt.
     Nur wenn es die Leiste wirklich gibt: `unterleisteMarkup` liefert bei
     weniger als zwei Türen nichts zurück (Rolle «partner»), dann bleibt der
     Boden frei — dieselbe Bedingung, die schon den Hamburger stehen lässt. */
  body:has(.lx-unten) { --nav-h: 68px; }
  .lx-unten {
    position: fixed; left: 0; right: 0; z-index: 40;
    /* Der SICHTBARE Boden, nicht der Fensterboden (siehe `.so2-mobilebar`). */
    bottom: var(--vv-unten, 0px);
    /* `minmax(0, 1fr)` und NICHT `1fr` — gemessen am 18.08.2026, 390px:
       `1fr` ist die Kurzform von `minmax(auto, 1fr)`, und `auto` ist die
       min-content-Breite des nicht umbrechenden Wortes. Die Spalten wuchsen
       damit ueber den Rahmen hinaus (fuenf Plaetze = 440px in einem 390px-
       Fenster), «Mehr» stand 50px ausserhalb — und «Mehr» ist am Handy der
       EINZIGE Weg in die Seitenleiste, weil der Hamburger dort per CSS aus
       ist. Das `text-overflow: ellipsis` weiter unten kam nie zum Zug, weil
       nichts es je zwang. Mit `minmax(0, 1fr)`: 380px, alle fuenf drin, jedes
       Wort sauber gekuerzt, 76px je Platz. Der Fehler bestand schon vor den
       neun Bereichen (410px bei vier Woertern) — er wurde nur nie sichtbar
       genug, um jemandem aufzufallen. */
    display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr);
    padding: 6px 4px calc(6px + var(--sab));
    border-top: 1px solid var(--border);
    background: var(--topbar-bg); backdrop-filter: blur(18px);
  }
  .lx-unten__ziel {
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: 3px; min-height: 48px; padding: 5px 2px;
    border: 0; background: transparent; color: var(--text-tertiary);
    font: 500 10.5px/1.1 inherit; text-decoration: none; cursor: pointer;
    border-radius: var(--radius-button);
  }
  .lx-unten__ziel.active { color: var(--accent-strong); }
  .lx-unten__ziel:active { background: rgba(var(--tint-rgb), .06); }
  .lx-unten__ic { display: inline-flex; width: 21px; height: 21px; }
  .lx-unten__ic svg { width: 21px; height: 21px; }
  .lx-unten__wort {
    max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  /* Die Leiste liegt ÜBER dem Inhalt — die Seite braucht darunter Luft, sonst
     verdeckt sie die letzte Zeile jeder Liste. Diese Luft steht seit 09.08. an
     EINER Stelle (`.main-shell { padding-bottom: calc(32px + var(--boden-abstand)) }`)
     und rechnet aus `--nav-h`/`--leiste-h`/`--fab-h` oben. Was hier stand —
     70 · 140 px für die Schale, 78 px für den Knopf, 82 · 146 px für die
     Toasts — waren fünf Zahlen für dieselbe Geometrie.
     Eine Cockpit-Fläche misst sich an der Fensterhöhe und zieht denselben
     Boden ab; ohne den Abzug stünde ihr Fuss unter der Leiste. */
  .cp { height: calc(100svh - var(--boden-h)); }
}

/* ---------- Handy: der Inhalt beginnt oben, nicht in der Mitte ----------
   Owner 06.08., dritte Meldung zum selben Thema: «auf dem Smartphone ist die
   Lösung immer noch scheisse.» Am Bild gemessen (#/m/pool, 390 px): der erste
   Lead stand bei 650 von 844 px — 77 % der Höhe waren Rahmen. Nach dem
   geschrumpften Kopf noch 441 px (52 %). Es sind drei Posten, und alle drei
   sind an EINER Stelle zu räumen, statt in sechzig Ansichten.

   Seine Referenz (iPhone links in `13_25_27.png`) zeigt die Zielform: eine
   Kopfzeile, darunter sofort Inhalt, unten eine Leiste am Daumen. */
@media (max-width: 900px) {
  /* 1. Die Titelzeile ist am Handy die DRITTE Nennung desselben Wortes —
        Kopfzeile, Reiterleiste, Überschrift sagen alle «Pool». Zwei genügen. */
  .admin-page__head h1 { display: none; }
  .admin-page__head { margin-bottom: 0; }
  .admin-page__head:has(> h1:only-child) { display: none; }
  /* Ein Kopf mit Hinweistext oder Aktionen bleibt — dort steht mehr als der
     Name der Fläche. */
  .admin-page__head:has(.admin-page__hint) { display: block; margin-bottom: 12px; }
  /* HIER STAND DIE AUSNAHME `.admin-page__head.lx-kopf--umfang h1` (W11.4,
     11.08.2026) — sie hielt den Titel «Alles von heute» am Handy sichtbar, weil
     er dort Inhalt war und nicht Beschriftung. Am 18.08. ist sie mit ihrem Grund
     gefallen: `views/manager-today.js` ist keine Fläche, sondern der Team-Umfang
     IN der Fläche «Heute» (`views/advisor-leads.js`), und die trägt ihren Namen
     seit Welle 8 selbst. Der Umfang heisst jetzt in der Bauart «Kastenkopf»
     (`ck-titel` + `<h3>`), und ein `<h3>` fällt am Handy nie weg — es braucht
     keine Ausnahme mehr. Verlust 11 bleibt zu: der Name steht auf jeder Breite.
     Hausregel 7, ersetzen statt daneben. */

  /* 2. Der Werkzeugkasten war der grösste Einzelposten: Suche, Filter und
        Aktionen stapeln sich am Handy zu ~230 px, bevor die erste Zeile kommt.
        Er wird zwei flache Zeilen statt vier gestapelter Blöcke — die Suche
        oben, die Handlungen darunter waagrecht scrollbar. */
  .filters-panel { padding: 8px 10px; }
  .filters-toolbar { flex-wrap: nowrap; flex-direction: column; align-items: stretch; gap: 8px; }
  .filters-group, .filters-actions {
    display: flex; flex-direction: row; flex-wrap: nowrap;
    align-items: center; gap: 8px;
    overflow-x: auto; scrollbar-width: none; padding-bottom: 1px;
  }
  /* Das Suchfeld traegt sein Label ueber dem Eingabefeld — am Handy ist das
     eine Zeile fuer ein Wort, das der Platzhalter schon sagt, und sie schiebt
     den Filter-Knopf in die naechste Zeile. */
  /* ⚠️ ZWEI FASSUNGEN DERSELBEN REGEL — und die zweite hob die erste auf.
     Bis zum 25.08.2026 stand fuenf Zeilen weiter unten ein zweites
     `.filters-group .field--search { flex: 1 1 auto; min-width: 0 }`: gleicher
     Waehler, gleiche Spezifitaet, spaeter — es gewann immer, und der Boden von
     110 px hier war tot. Folge, gemessen auf dem iPad hochkant (768 px):
     `label.field--search` war 0 x 44 px. Das SUCHFELD DES POOLS war nicht da.
     Unter 721 px fiel es nicht auf, weil dort eine schaerfere Regel aus
     grund.css (`.filters-panel .filters-group .field--search`, 0,3,0) den
     Boden von 110 px zurueckholt — dieser Block gilt aber bis 900 px. Das
     Fenster 721-900 px hat schlicht nie jemand angesehen; es ist genau die
     Breite eines iPads hochkant. Der Breiten-Waechter
     (scripts/_jede_breite_test.mjs) misst es seither.
     Jetzt gibt es EINE Fassung, mit Boden. Der Kasten rollt waagrecht
     (`overflow-x: auto` darueber) — was neben dem Feld nicht mehr Platz hat,
     ist erreichbar, nicht weg. */
  .filters-group .field--search {
    flex: 1 1 auto; min-width: 110px; display: block;
  }
  .filters-group .field--search input { width: 100%; }
  .filters-group::-webkit-scrollbar,
  .filters-actions::-webkit-scrollbar { display: none; }
  .filters-group > *, .filters-actions > * { flex: 0 0 auto; }
  /* «SUCHE» über dem Suchfeld ist eine Zeile für ein Wort, das der
     Platzhalter schon sagt. */
  .filters-group .field--search > span { display: none; }
  /* 3. Eine Listenzeile brauchte 185 px, weil fünf Spalten untereinander
        fallen. Zwei Zeilen genügen: Name oben, Ort und Zahl darunter. */
  .kp-row {
    grid-template-columns: 22px minmax(0, 1fr) auto;
    gap: 1px 10px; padding: 9px 11px; align-items: center;
  }
  .kp-row__name { grid-column: 2; grid-row: 1; font-size: 14px; }
  .kp-row__ort { grid-column: 2; grid-row: 2; font-size: 11.5px; }
  .kp-row__screens { grid-column: 3; grid-row: 1 / span 2; align-self: center; }
  .kp-row__grenze { grid-column: 2 / -1; grid-row: 3; }
}

/* Touch-Boden (Memory project_tablet_touch_breakpoint): jede Zeile und jeder
   Knopf der Schale bleibt mindestens einen Daumen gross. */
@media (max-width: 1024px), (pointer: coarse) {
  .sidebar .nav-tab { min-height: 44px; }
  .lx-top__suche { min-height: 44px; }
  .lx-top .sidebar__search { width: 44px; min-width: 44px; height: 44px; min-height: 44px; }
  .lx-top__konto { width: 44px; height: 44px; }
  /* 08.09.: derselbe Boden fuer «Neu». Er steht ab 901 px, das iPad quer
     (1024 px) faellt also in BEIDE Blöcke — und dort ist der Finger das Mass.
     Ohne diese Zeile mass er 40 x 40 px; der Breiten-Waechter hat ihn genau
     dort gemeldet (`_jede_breite_test.mjs`, «griff» @ 1024). */
  .lx-top__neu { width: 44px; height: 44px; }
  .lx-profil__klapp { width: 44px; }
}

/* Bewegung ist Zustand, nie Deko. */
@media (prefers-reduced-motion: reduce) {
  .sidebar .nav-tab, .lx-top__suche { transition: none; }
}


/* Connected workspaces: one stable navigation and a short local toolbar. */
.workspace-shell .sidebar { background: var(--surface-1); }
.workspace-shell .sidebar__top { min-height: 84px; padding: 0 22px; margin-bottom: 24px; }
.workspace-shell .sidebar__nav { gap: 6px; padding: 0 12px; }
.workspace-shell .sidebar .nav-tab { min-height: 46px; gap: 12px; padding: 10px 13px; font-size: 13px; font-weight: 550; }
.workspace-shell .sidebar .nav-tab--utility { margin-top: 28px; }
.workspace-shell .sidebar .nav-tab.active { background: var(--accent-soft); color: var(--accent-strong); border-color: transparent; }
.workspace-shell .sidebar .nav-tab.active .nav-tab__icon { color: currentColor; }
:root[data-theme="light"] .workspace-shell .sidebar {
  --surface-1: #193632; --surface-hover: #244640; --surface: #21423c;
  --text-primary: #eff4e9; --text-secondary: #c6d6ce; --text-tertiary: #abbfb4;
  --text: #eff4e9; --accent: #c8dcbd; --accent-soft: #c8dcbd; --accent-strong: #183c32;
  --border: rgba(227, 237, 221, .16); --tint-rgb: 227, 237, 221; --on-accent: #183c32;
}
:root[data-theme="light"] .workspace-shell .sidebar .nav-tab.active { color: #183c32; }
:root[data-theme="light"] .workspace-shell .sidebar .lx-marke__wort em { color: #c8dcbd; }
.workspace-shell .sidebar .lx-marke__wort { font-size: 17px; color: var(--text-primary); }
.workspace-shell .sidebar .lx-marke__bei { font-size: 12px; margin-top: 5px; font-weight: 450; color: var(--text-secondary); }
.workspace-shell .lx-top { border-bottom-color: var(--border); }
.workspace-shell .lx-ort-halter { margin-block: 8px 6px; }
.subnav.subnav--workspace { display: block; overflow: visible; padding: 0; border: 0; background: transparent; margin-bottom: 20px; z-index: 21; }
.subnav.subnav--workspace[hidden] { display: none; }
.workspace-tabs { display: flex; align-items: center; gap: 12px; min-width: 0; border-bottom: 1px solid var(--border); }
.workspace-tabs__primary { display: flex; flex: 1 1 auto; min-width: 0; gap: 4px; }
.workspace-tabs .subnav__tab { display: inline-flex; align-items: center; min-height: 44px; padding: 8px 12px; font-size: 13px; font-weight: 550; border: 0; border-radius: 0; text-decoration: none; text-transform: none; letter-spacing: 0; white-space: nowrap; background: transparent; color: var(--text-secondary); }
.workspace-tabs .subnav__tab.active { color: var(--accent-strong); box-shadow: inset 0 -2px var(--accent); }
.workspace-tabs .subnav__tab:hover { background: var(--accent-soft); color: var(--text-primary); }
.workspace-menu { position: relative; flex: 0 0 auto; margin-left: auto; }
.workspace-menu > summary { display: flex; align-items: center; gap: 8px; min-height: 44px; padding: 6px 10px; cursor: pointer; list-style: none; color: var(--text-secondary); font-size: 12px; font-weight: 550; }
.workspace-menu > summary::-webkit-details-marker { display: none; }
.workspace-menu > summary svg { width: 14px; height: 14px; flex: none; transition: transform var(--transition); }
.workspace-menu[open] > summary svg { transform: rotate(180deg); }
.workspace-menu > summary:focus-visible, .workspace-tabs a:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.workspace-menu__body { position: absolute; right: 0; top: calc(100% + 8px); width: min(340px, calc(100vw - 32px)); max-height: min(60dvh, 600px); overflow: auto; display: grid; gap: 12px; padding: 10px; background: var(--surface-inset); border: 1px solid var(--border); border-radius: var(--radius-card); box-shadow: var(--shadow-lg); z-index: 30; }
.workspace-menu__group { display: grid; gap: 2px; }
.workspace-menu__group > span { padding: 8px 10px 2px; color: var(--text-tertiary); font-size: 11px; font-weight: 550; }
.workspace-menu__body .subnav__tab { width: 100%; min-height: 40px; white-space: normal; border-radius: var(--radius-button); box-shadow: none; }
.workspace-menu__body .subnav__tab.active { background: var(--accent-soft); color: var(--accent-strong); }
.workspace-shell .primary-btn, .workspace-shell .ghost-btn, .workspace-shell .panel__title,
.workspace-shell .view-toggle__btn, .workspace-shell .seg__btn { text-transform: none; letter-spacing: 0; }
.workspace-shell .primary-btn, .workspace-shell .ghost-btn { font-size: 13px; font-weight: 600; }
.workspace-shell .panel__title { font-size: 15px; font-weight: 650; }
.contact-insights { margin:0 0 16px; border:1px solid var(--border); border-radius:var(--radius-card); background:var(--surface-inset); }
.contact-insights > summary { padding:12px 16px; min-height:44px; font-size:13px; color:var(--text-secondary); font-weight:550; cursor:pointer; }
.contact-insights[open] { padding:0 16px 16px; }
.contact-insights[open] > summary { margin-inline:-16px; }
.contact-insights .sp-day-link { margin:0 0 14px; }
@media (max-width: 1100px) {
  .workspace-tabs__primary > [data-priority="3"] { display: none; }
}
@media (max-width: 720px) {
  .workspace-shell .sidebar__top { min-height: 68px; margin-bottom: 14px; }
  .workspace-shell .sidebar .nav-tab { min-height: 48px; }
  .subnav.subnav--workspace { margin: 0 0 14px; position: relative; top: auto; }
  .workspace-tabs { gap: 2px; }
  .workspace-tabs__primary > [data-priority="2"] { display: none; }
  .workspace-tabs .subnav__tab { padding-inline: 8px; font-size: 12px; }
  .workspace-menu > summary { font-size: 12px; padding-inline: 6px; }
  .workspace-menu > summary > span { max-width: 112px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .workspace-shell .lx-unten__wort { font-size: 11px; }
}
@media (max-width: 430px) {
  .workspace-tabs__primary > [data-priority="1"] { display: none; }
  .workspace-tabs__primary:has(.active) > a:not(.active) { display: none; }
  .workspace-tabs__primary > a.active { display: inline-flex; }
}
@media (prefers-reduced-motion: reduce) { .workspace-menu > summary svg { transition: none; } }

/* Each destination appears once in the visible workspace navigation. */
.workspace-menu__body [data-menu-priority] { display:none; }
.workspace-menu__group:not(:has(a:not([data-menu-priority]))) > span { display:none; }
.workspace-menu:not(:has(a:not([data-menu-priority]))) { display:none; }
@media(max-width:1100px) {
 .workspace-menu__body [data-menu-priority="3"] { display:inline-flex; }
 .workspace-menu:has([data-menu-priority="3"]) { display:block; }
}
@media(max-width:720px) {
 .workspace-menu__body [data-menu-priority="2"] { display:inline-flex; }
 .workspace-menu:has([data-menu-priority="2"]) { display:block; }
}
@media(max-width:430px) {
 .workspace-menu__body [data-menu-priority="1"] { display:inline-flex; }
 .workspace-menu:has([data-menu-priority="1"]) { display:block; }
 .workspace-tabs:has(.workspace-tabs__primary .active) .workspace-menu__body [data-menu-priority] { display:inline-flex; }
 .workspace-tabs:has(.workspace-tabs__primary .active) .workspace-menu__body [data-menu-priority].active { display:none; }
}

.customer-profile { display:grid;grid-template-columns:minmax(0,1.8fr) minmax(250px,1fr);gap:28px;margin-top:8px; }
.customer-profile__work>section,.customer-profile__context>section { padding:20px 0;border-bottom:1px solid var(--border); }
.customer-profile h2,.customer-documents h2 { font-size:20px;line-height:1.3;margin:0; }
.customer-profile header,.customer-documents header { display:flex;align-items:center;justify-content:space-between;gap:16px;margin-bottom:14px; }
.customer-profile p,.customer-documents p { max-width:70ch;font-size:14px;line-height:1.6;color:var(--text-secondary); }
.customer-profile__list,.customer-document-list { list-style:none;padding:0;margin:0; }
.customer-profile__list li+li,.customer-document-list li+li { border-top:1px solid var(--border); }
.customer-profile__list a,.customer-profile__list button { width:100%;display:flex;align-items:center;justify-content:space-between;gap:16px;padding:14px 0;background:none;border:0;text-align:left;text-decoration:none;color:var(--text-primary);cursor:pointer; }
.customer-profile__list strong,.customer-profile__list small { display:block; }.customer-profile__list small { margin-top:5px;color:var(--text-secondary);font-size:12px; }
.customer-profile__list b { white-space:nowrap;font-size:14px;font-variant-numeric:tabular-nums; }
.customer-profile__context { padding:0 20px;background:var(--surface-inset);border-radius:var(--radius-card);align-self:start; }
.customer-profile__context>section:last-child { border:0; }
.customer-profile__contact { display:grid;gap:10px;margin:16px 0; }
.customer-profile__contact a { display:flex;align-items:center;gap:10px;color:var(--accent-strong);font-size:14px;overflow-wrap:anywhere; }
.customer-profile svg,.customer-documents svg { width:18px;height:18px;flex:none; }
.customer-profile dl { display:grid;gap:14px;margin:18px 0; }.customer-profile dt { font-size:12px;color:var(--text-secondary); }.customer-profile dd { margin:3px 0 0;font-size:20px;font-weight:650;font-variant-numeric:tabular-nums; }
.customer-profile__journey { display:flex;align-items:center;justify-content:space-between;gap:8px;padding:24px 0; }
.customer-profile__journey button { min-height:56px;background:none;border:0;color:var(--text-primary);cursor:pointer;text-align:left; }.customer-profile__journey span,.customer-profile__journey strong { display:block; }.customer-profile__journey span { margin-top:6px;font-size:12px;color:var(--text-secondary); }
.customer-documents { padding-top:20px; }.customer-documents [data-cd-search] { display:flex;gap:8px;max-width:620px;margin:20px 0; }.customer-documents [data-cd-search] label { flex:1; }.customer-documents input { width:100%;min-height:44px; }
.customer-document-list li { display:flex;align-items:center;justify-content:space-between;gap:20px;padding:16px 0; }.customer-document-list li>div { display:flex;gap:12px;min-width:0; }.customer-document-list strong { overflow-wrap:anywhere; }.customer-document-list small { display:block;color:var(--text-secondary);margin-top:6px; }.customer-documents [data-cd-pages] { display:flex;align-items:center;justify-content:flex-end;gap:10px;padding:20px 0; }.customer-documents [data-cd-pages]>span { margin-right:auto; }.customer-documents [data-cd-preview]:not([hidden]) { padding:20px 0;border-top:1px solid var(--border); }
.customer-profile button:focus-visible,.customer-profile a:focus-visible,.customer-documents button:focus-visible { outline:2px solid var(--accent);outline-offset:3px; }
@media(max-width:820px){ .customer-profile { grid-template-columns:1fr;gap:16px; }.customer-profile__context { display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:20px; }.customer-profile__context>section { border:0; } }
@media(max-width:520px){ .customer-profile__context { grid-template-columns:1fr;gap:0;padding:0 16px; }.customer-profile header,.customer-documents header { align-items:flex-start;flex-wrap:wrap; }.customer-profile__journey { flex-wrap:wrap; }.customer-document-list li { align-items:flex-start;flex-direction:column;gap:10px; }.customer-profile__list a,.customer-profile__list button { gap:8px; }.customer-profile h2,.customer-documents h2 { font-size:18px; } }

/* Location selection stays compact and returns from the same record. */
.location-register__primary{display:grid;grid-template-columns:minmax(220px,1fr) minmax(100px,150px) minmax(120px,160px) auto;align-items:end;margin-bottom:12px}
.location-register__extra{padding:16px;background:var(--surface);border:1px solid var(--border);margin-bottom:12px}
.location-register__extra[hidden]{display:none}
.location-register__selection{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin-bottom:16px}
.location-register__selection .ghost-btn{min-height:36px;font-size:13px;padding:6px 10px}
.location-register__selection .text-btn{min-height:36px}
.location-register__return{margin-bottom:16px}
@media(max-width:720px){.location-register__primary{grid-template-columns:1fr 1fr}.location-register__primary>.field:first-child{grid-column:1/-1}.location-register__primary>[data-more-filters]{grid-column:1/-1}.location-register__extra{display:grid;grid-template-columns:1fr 1fr}.location-register__extra>[data-slot=ansichten]{grid-column:1/-1}}

/* Connected entity profiles: one anatomy, original work paths and date-only booking evidence. */
.profile-layout { display:grid;grid-template-columns:minmax(220px,.78fr) minmax(0,2fr);gap:28px;align-items:start;margin-top:8px; }
.profile-context { min-width:0;padding:20px;background:var(--surface-inset);border:1px solid var(--border);border-radius:var(--radius-card); }
.profile-context>section { padding:20px 0;border-bottom:1px solid var(--border); }
.profile-context>section:first-child { padding-top:0; }.profile-context>section:last-child { border-bottom:0;padding-bottom:0; }
.profile-work { min-width:0; }.profile-work>section,.profile-work>.profile-section,.profile-campaigns { padding:20px 0;border-bottom:1px solid var(--border); }
.profile-work>section:first-child { padding-top:0; }
.profile-layout h2 { margin:0;font-size:19px;line-height:1.3;letter-spacing:-.025em; }
.profile-layout header { display:flex;align-items:center;justify-content:space-between;gap:14px;margin-bottom:14px; }
.profile-layout p { margin:10px 0;font-size:14px;line-height:1.55;color:var(--text-secondary); }
.profile-layout svg,.profile-return svg { width:18px;height:18px;flex:none; }
.profile-layout a:focus-visible,.profile-layout button:focus-visible { outline:2px solid var(--accent);outline-offset:3px; }
.profile-identity__mark { width:48px;height:48px;display:grid;place-items:center;background:var(--accent-soft);color:var(--accent-strong);border-radius:14px;font-size:19px;font-weight:650;margin-bottom:14px; }
.profile-identity__contact { display:grid;gap:12px;margin:18px 0; }
.profile-identity__contact>a,.profile-identity__contact>span { display:flex;align-items:flex-start;gap:9px;font-size:13px;overflow-wrap:anywhere;min-width:0; }
.profile-identity__contact>a { color:var(--accent-strong);text-decoration:none; }
.profile-context dl { display:grid;gap:12px;margin:16px 0; }.profile-context dt { font-size:12px;color:var(--text-secondary); }.profile-context dd { margin:4px 0 0;font-size:21px;font-weight:650;font-variant-numeric:tabular-nums; }
.profile-context .ghost-btn { white-space:normal;text-align:left; }.profile-context>.ghost-btn { margin-top:14px; }
.profile-context .pd2-card__body { padding:0; }
.profile-links { display:grid;gap:6px;margin-top:12px; }.profile-links button { display:flex;align-items:center;gap:10px;min-height:44px;text-align:left;padding:8px 0;border:0;background:none;color:var(--text-primary);cursor:pointer; }.profile-links button svg:last-child { margin-left:auto; }
.profile-group { --group-tone:var(--text-secondary);display:inline-flex;align-items:center;gap:8px;padding:7px 9px;margin:4px 4px 0 0;border:1px solid var(--border);border-radius:7px;color:var(--text-primary);font-size:13px;line-height:1.35;text-decoration:none;overflow-wrap:anywhere; }
.profile-group i { width:8px;height:8px;border-radius:50%;background:var(--group-tone);flex:none; }
.profile-group[data-color=green] { --group-tone:#398754; }.profile-group[data-color=yellow] { --group-tone:#b89117; }.profile-group[data-color=orange] { --group-tone:#cc782d; }.profile-group[data-color=red] { --group-tone:#c95856; }.profile-group[data-color=blue] { --group-tone:#4a83b3; }.profile-group[data-color=purple] { --group-tone:#9465b3; }
.profile-locations { display:grid;gap:0; }.profile-location { display:flex;align-items:center;justify-content:space-between;gap:14px;padding:16px 0;color:var(--text-primary);text-decoration:none;border-top:1px solid var(--border); }
.profile-location>span:first-child { display:grid;grid-template-columns:24px 1fr;gap:5px 9px;flex:1;min-width:0; }.profile-location>span:first-child svg { grid-row:span 2; }.profile-location>span:first-child small { grid-column:2; }
.profile-location>span:nth-child(2) { text-align:right;font-size:12px; }.profile-location b { font-size:18px;font-variant-numeric:tabular-nums; }.profile-location small { display:block;color:var(--text-secondary);font-size:12px;line-height:1.4; }.profile-location strong { overflow-wrap:anywhere;font-size:14px; }
.profile-location:hover,.profile-timeline button:hover,.profile-appointments a:hover { background:var(--surface-inset); }
.profile-time-controls { display:flex;align-items:end;gap:8px;flex-wrap:wrap; }.profile-time-controls label { display:grid;gap:6px;font-size:12px;color:var(--text-secondary); }.profile-time-controls input { min-width:0;max-width:160px;min-height:40px;color:var(--text-primary);color-scheme:light dark; }
.profile-back-icon { display:flex;transform:rotate(180deg); }.profile-return { display:inline-flex;margin:0 0 16px;gap:10px; }.profile-return svg { transform:rotate(180deg); }
.profile-campaign-filters { display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px;margin-top:12px; }.profile-campaign-filters label { flex:1;min-width:0; }.profile-campaign-filters input,.profile-campaign-filters select { width:100%;min-height:40px;min-width:0; }
.profile-timeline-axis { display:flex;justify-content:space-between;font-size:11px;color:var(--text-secondary);margin:16px 0 6px;padding-left:37%;font-variant-numeric:tabular-nums; }
.profile-timeline { margin:0;padding:0;list-style:none; }.profile-timeline li { border-top:1px solid var(--border); }
.profile-timeline button { display:grid;grid-template-columns:minmax(130px,1fr) minmax(130px,1.5fr) 18px;gap:9px 16px;align-items:center;width:100%;border:0;background:none;color:var(--text-primary);padding:14px 4px;text-align:left;cursor:pointer;transition:background-color 140ms; }
.profile-timeline__identity { grid-column:1;grid-row:span 2;min-width:0; }.profile-timeline strong { display:block;font-size:14px;overflow-wrap:anywhere; }.profile-timeline small { display:block;font-size:12px;color:var(--text-secondary);margin-top:5px; }
.profile-timeline__track { position:relative;height:19px;background:var(--surface-inset);border-radius:3px;overflow:hidden;background-image:repeating-linear-gradient(90deg,transparent 0,transparent calc(25% - 1px),var(--border) calc(25% - 1px),var(--border) 25%); }
.profile-timeline__track i { position:absolute;top:4px;height:11px;background:var(--accent-strong);border-radius:3px; }.profile-timeline__track i[data-state=hold],.profile-timeline__track i[data-state=unverified_hold] { background:#b89117; }.profile-timeline__track i[data-state=expired],.profile-timeline__track i[data-state=cancelled] { background:var(--text-tertiary);opacity:.45; }
.profile-timeline__dates { font-size:11px;color:var(--text-secondary);grid-column:2;grid-row:2;font-variant-numeric:tabular-nums; }.profile-timeline__status { font-size:11px;color:var(--text-secondary);grid-column:1 / 3;grid-row:3; }.profile-timeline button>svg { grid-column:3;grid-row:1 / 4; }
.profile-campaign-pager { display:flex;justify-content:flex-end;align-items:center;gap:10px;margin-top:14px;font-size:12px; }
.profile-empty { padding:24px 0; }.profile-empty strong { font-size:15px; }.profile-empty p { max-width:54ch; }
.profile-stage-summary { display:grid;gap:8px;grid-template-columns:repeat(4,minmax(0,1fr)); }.profile-stage-summary button { display:grid;grid-template-columns:1fr auto;gap:9px;padding:12px;border:1px solid var(--border);border-radius:8px;background:var(--surface);color:var(--text-primary);cursor:pointer;text-align:left; }.profile-stage-summary span { font-size:12px; }.profile-stage-summary strong { font-variant-numeric:tabular-nums; }.profile-stage-summary i { grid-column:1/-1;height:4px;border-radius:2px;background:var(--surface-inset); }.profile-stage-summary b { display:block;height:100%;background:var(--accent-strong);border-radius:2px; }
.profile-appointments { list-style:none;padding:0;margin:0; }.profile-appointments a { display:flex;align-items:center;gap:16px;color:var(--text-primary);text-decoration:none;padding:14px 0;border-top:1px solid var(--border); }.profile-appointments time { font-size:12px;color:var(--text-secondary);max-width:110px; }.profile-appointments span { flex:1; }.profile-appointments strong,.profile-appointments small { display:block; }.profile-appointments small { margin-top:5px;color:var(--text-secondary);font-size:12px; }
@media(max-width:900px) { .profile-layout { grid-template-columns:minmax(200px,.8fr) minmax(0,1.5fr);gap:18px; }.profile-stage-summary { grid-template-columns:repeat(2,minmax(0,1fr)); }.profile-context { padding:16px; } }
@media(max-width:680px) { .profile-layout { grid-template-columns:1fr;gap:24px; }.profile-context { display:grid;grid-template-columns:1fr; }.profile-work header { align-items:flex-start;flex-wrap:wrap; }.profile-time-controls { display:grid;grid-template-columns:36px minmax(0,1fr) minmax(0,1fr) 36px;gap:8px; }.profile-time-controls label { min-width:0; }.profile-time-controls input { width:100%;max-width:none;padding:8px 4px;font-size:13px; }.profile-time-controls button[data-campaign-shift] { min-width:0;padding:9px; }.profile-time-controls button[type=submit] { grid-column:2 / 4;justify-self:stretch; }.profile-campaign-filters { flex-wrap:wrap; }.profile-campaign-filters label { flex-basis:100%; }.profile-timeline button { grid-template-columns:1fr 18px;gap:8px; }.profile-timeline__identity { grid-row:1; }.profile-timeline__track { grid-column:1;grid-row:2; }.profile-timeline__dates { grid-column:1;grid-row:3; }.profile-timeline__status { grid-column:1;grid-row:4; }.profile-timeline button>svg { grid-column:2;grid-row:1 / 5; }.profile-timeline-axis { padding-left:0; }.profile-location { flex-wrap:wrap; }.profile-location>span:nth-child(2) { max-width:105px; }.profile-layout h2 { font-size:18px; } }
@media(prefers-reduced-motion:reduce) { .profile-timeline button { transition:none; } }

.profile-context-toggle { display:none; }
@media(max-width:680px) {
 .profile-context-toggle { display:flex;align-items:center;justify-content:space-between;gap:12px;width:100%;padding:13px 16px;border:1px solid var(--border);border-radius:9px;background:var(--surface-inset);color:var(--text-primary);text-align:left;font-size:14px;cursor:pointer; }
 .profile-layout:not(.is-context-open)>.profile-context { display:none; }
 .is-context-open>.profile-context-toggle svg { transform:rotate(90deg); }
}

/* Campaign selection and the original booking share one work surface. */
.campaign-workspace { container-type:inline-size; }
.campaign-workspace > header { display:flex;justify-content:space-between;align-items:center;gap:16px;margin-bottom:16px; }
.campaign-workspace h2 { margin:0;font-size:20px; }
.campaign-workspace > header > span { color:var(--text-secondary);font-size:13px; }
.campaign-filter-panel { margin-bottom:18px; }
.campaign-filter-panel > summary { display:flex;align-items:center;gap:12px;min-height:44px;cursor:pointer;list-style:none;border-bottom:1px solid var(--border);padding:8px 0; }
.campaign-filter-panel > summary::after { content:'+';margin-left:auto;font-size:20px; }
.campaign-filter-panel[open] > summary::after { content:'−'; }
.campaign-filter-panel > summary::-webkit-details-marker { display:none; }
.campaign-filter-panel > summary > span { color:var(--text-secondary);font-size:12px;line-height:1.5; }
.campaign-filter-panel[open] .campaign-work-filters { padding-top:12px; }
.campaign-filter-panel .campaign-work-filters { margin-bottom:0; }
.campaign-work-filters { display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:10px;margin-bottom:18px; }
.campaign-work-filters label { min-width:0; }
.campaign-work-filters input,.campaign-work-filters select { width:100%;min-width:0;min-height:44px;font:inherit;font-size:13px;box-sizing:border-box; }
.campaign-work-filters select { overflow:hidden;text-overflow:ellipsis; }
.campaign-work-dates { grid-column:1/-1;display:flex;align-items:end;gap:10px;flex-wrap:wrap; }
.campaign-work-dates label { display:grid;gap:4px;font-size:12px; }
.campaign-work-dates > label:first-child { min-width:160px; }
.campaign-work-dates > span { align-self:center;font-size:12px; }
.campaign-work-dates[data-all-time=true] label:has(input),.campaign-work-dates[data-all-time=true] button { display:none; }
.campaign-desk { display:grid;grid-template-columns:minmax(230px,.75fr) minmax(0,1.65fr);align-items:start;gap:22px; }
.campaign-desk > section { min-width:0; }
.campaign-desk__list { border:1px solid var(--border);border-radius:10px;overflow:hidden; }
.campaign-desk__list ol { list-style:none;margin:0;padding:0;max-height:600px;overflow:auto;overscroll-behavior:contain; }
.campaign-desk__list li + li { border-top:1px solid var(--border); }
.campaign-desk__list button[data-customer-campaign] { display:grid;gap:5px;width:100%;padding:14px;text-align:left;font:inherit;color:var(--text-primary);background:var(--surface);border:0;border-left:3px solid transparent;cursor:pointer;transition:background-color 140ms; }
.campaign-desk__list button[data-customer-campaign]:hover { background:var(--surface-inset); }
.campaign-desk__list button[data-customer-campaign][aria-pressed=true] { background:var(--accent-soft);border-left-color:var(--accent-strong); }
.campaign-desk__list strong { font-size:14px;overflow-wrap:anywhere; }
.campaign-desk__list button > span { color:var(--text-secondary);font-size:12px; }
.campaign-desk__list button[data-state=confirmed] > span { color:var(--accent-strong); }
.campaign-desk__list small { color:var(--text-secondary);font-size:12px;line-height:1.45;font-variant-numeric:tabular-nums; }
.campaign-desk__list nav:not(:empty) { display:flex;gap:8px;justify-content:space-between;align-items:center;flex-wrap:wrap;padding:10px;border-top:1px solid var(--border);font-size:12px; }
.campaign-desk__detail > p { margin:0 0 12px;font-size:12px;line-height:1.5; }
.campaign-desk__detail .vk-panel { margin:0; }
.campaign-desk__detail .vk-zeile { flex-wrap:wrap; }
.campaign-desk__detail .vk-zeile__leib { min-width:120px; }
.campaign-desk__detail .vk-zeile__rechts { margin-left:auto; }
.campaign-desk__detail .vk-unter { margin-left:0; }
.campaign-selected-delivery { color:var(--text-secondary);font-size:12px; }
.campaign-selected-delivery:not(:has(span:not(:empty))) { display:none; }
.campaign-desk [data-delivery-booking-target]:focus-visible,.campaign-desk__list button:focus-visible { outline:2px solid var(--accent);outline-offset:-2px; }
@container (max-width:760px) {
 .campaign-work-filters { grid-template-columns:repeat(2,minmax(0,1fr));gap:8px; }
 .campaign-desk { grid-template-columns:1fr;gap:16px; }
 .campaign-desk__list ol { max-height:220px; }
 .campaign-desk__list button[data-customer-campaign] { padding:10px 12px;gap:3px; }
 .campaign-work-dates { display:grid;grid-template-columns:repeat(2,minmax(0,1fr)); }
 .campaign-work-dates > label:first-child { min-width:0; }
 .campaign-work-dates:not([data-all-time=true]) > label:first-child { grid-column:1/-1; }
 .campaign-work-dates > span { text-align:right; }
 .campaign-workspace > header { margin-bottom:12px; }
 .campaign-desk__detail .vk-zeile__rechts { margin-left:0;align-items:flex-start; }
}
@media(prefers-reduced-motion:reduce) { .campaign-desk__list button[data-customer-campaign] { transition:none; } }
@container(min-width:761px) { .campaign-filter-panel[open] > summary { display:none; } .campaign-filter-panel[open] .campaign-work-filters { padding-top:0; } }

/* Original campaigns at the shared work-area entrance. */
.campaign-register { max-width:1360px;margin:0 auto;container-type:inline-size;color:var(--text-primary); }
.campaign-register__heading { display:flex;align-items:center;justify-content:space-between;gap:20px;margin-bottom:24px; }
.campaign-register__heading h1 { font-size:clamp(26px,3vw,36px);letter-spacing:-.035em;line-height:1.15;margin:4px 0 10px; }
.campaign-register__heading p { margin:0;color:var(--text-secondary);font-size:14px; }
.campaign-register__search { display:flex;gap:12px;margin-bottom:14px; }
.campaign-register__search > label:first-child { flex:1;min-width:0; }
.campaign-register__search input,.campaign-register__search select { width:100%;min-height:42px;border:1px solid var(--border);border-radius:8px;background:var(--surface);color:var(--text-primary);padding:10px 12px;font:inherit;font-size:14px; }
.campaign-register__filters { grid-template-columns:repeat(4,minmax(0,1fr));align-items:end; }
.campaign-register__filters .campaign-work-dates { grid-column:span 3; }
.campaign-register__error { padding:14px;border:1px solid var(--border);border-left:3px solid var(--error);border-radius:8px; }
.campaign-register__quick { display:grid;grid-template-columns:repeat(4,minmax(0,1fr));border:1px solid var(--border);border-radius:10px;overflow:hidden;margin:18px 0; }
.campaign-register__quick button { display:flex;align-items:baseline;gap:12px;text-align:left;padding:16px;background:var(--surface);border:0;color:var(--text-primary);cursor:pointer;font:inherit;transition:background-color 150ms; }
.campaign-register__quick button + button { border-left:1px solid var(--border); }
.campaign-register__quick strong { font-size:26px;line-height:1;font-variant-numeric:tabular-nums;font-weight:650; }
.campaign-register__quick span { font-size:12px;line-height:1.4;color:var(--text-secondary); }
.campaign-register__quick button:hover,.campaign-register__quick button[aria-pressed=true] { background:var(--accent-soft); }
.campaign-register__chart { margin:0 0 20px;padding:18px 20px 12px;border:1px solid var(--border);border-radius:10px;background:var(--surface); }
.campaign-register__chart figcaption { display:flex;justify-content:space-between;align-items:baseline;gap:12px;margin-bottom:12px;font-size:13px; }
.campaign-register__chart figcaption span { color:var(--text-secondary);font-size:12px; }
.campaign-register__chart svg { display:block;width:100%;height:122px;overflow:visible; }
.campaign-register__chart-axis { display:flex;justify-content:space-between;gap:6px;color:var(--text-secondary);font-size:11px;margin-bottom:10px; }
.campaign-register__booked,.campaign-register__reserved,.campaign-register__axis { fill:none;vector-effect:non-scaling-stroke;stroke-width:2;stroke:var(--accent-strong); }
.campaign-register__reserved { stroke:var(--text-secondary);stroke-dasharray:4 4;stroke-width:1.5; }
.campaign-register__axis { stroke:var(--border);stroke-width:1; }
.campaign-register__dot { fill:var(--accent-strong); }
.campaign-register__legend { display:flex;align-items:center;gap:12px;flex-wrap:wrap;color:var(--text-secondary);font-size:11px; }
.campaign-register__legend small { margin-left:auto;font-size:11px; }
.campaign-register__chart-data { margin-top:10px;font-size:12px; }
.campaign-register__chart-data summary { cursor:pointer;color:var(--text-secondary); }
.campaign-register__chart-data table { margin-top:10px;width:100%;font-variant-numeric:tabular-nums; }
.campaign-register__chart-data th,.campaign-register__chart-data td { padding:5px;text-align:right;border-bottom:1px solid var(--border); }
.campaign-register__chart-data th:first-child,.campaign-register__chart-data td:first-child { text-align:left; }
.campaign-register__chart-data button { border:0;background:none;color:var(--accent-strong);font:inherit;text-decoration:underline;cursor:pointer;padding:4px; }
.campaign-register__list-head { display:flex;justify-content:space-between;align-items:center;gap:12px;margin-bottom:10px; }
.campaign-register__list-head h2 { margin:0;font-size:16px; }
.campaign-register__rows { list-style:none;margin:0;padding:0;border:1px solid var(--border);border-radius:10px;overflow:hidden;background:var(--surface); }
.campaign-register__rows > li + li { border-top:1px solid var(--border); }
.campaign-register__row { display:grid;grid-template-columns:minmax(160px,1.3fr) minmax(180px,1fr) minmax(155px,.8fr) 16px;gap:18px;align-items:center;padding:16px 18px;color:inherit;text-decoration:none;transition:background-color 150ms; }
.campaign-register__row:hover { background:var(--surface-inset); }
.campaign-register__identity,.campaign-register__period,.campaign-register__states { display:grid;gap:5px;min-width:0;font-size:13px;overflow-wrap:anywhere; }
.campaign-register__identity strong { font-size:15px; }
.campaign-register__identity > span,.campaign-register__period small,.campaign-register__states > span { color:var(--text-secondary);font-size:12px; }
.campaign-register__states strong { font-size:12px;font-weight:600; }
.campaign-register__row[data-state=confirmed] .campaign-register__states strong { color:var(--accent-strong); }
.campaign-register__row[data-state=expired] .campaign-register__states strong,.campaign-register__row[data-state=cancelled] .campaign-register__states strong { color:var(--text-secondary); }
.campaign-register__period { font-variant-numeric:tabular-nums; }
.campaign-register__arrow { color:var(--accent-strong);font-size:19px; }
.campaign-register__group { background:var(--surface-inset);padding:10px 18px;font-size:12px;font-weight:650; }
.campaign-register a:focus-visible,.campaign-register button:focus-visible { outline:2px solid var(--accent-strong);outline-offset:-2px; }
@container (max-width:760px) {
 .campaign-register__heading { align-items:flex-start;margin-bottom:18px;gap:10px; }
 .campaign-register__heading > button { font-size:12px;padding:8px; }
 .campaign-register__search { flex-wrap:wrap;gap:8px; }
 .campaign-register__search > label:first-child { flex-basis:100%; }
 .campaign-register__search select { min-height:36px;font-size:12px;padding:6px 10px; }
 .campaign-register__filters { grid-template-columns:repeat(2,minmax(0,1fr)); }
 .campaign-register__filters .campaign-work-dates { grid-column:1/-1; }
 .campaign-register__quick { grid-template-columns:repeat(2,minmax(0,1fr));margin:12px 0; }
 .campaign-register__quick button { padding:12px;gap:10px; }
 .campaign-register__quick button:nth-child(3) { border-left:0; }
 .campaign-register__quick button:nth-child(n+3) { border-top:1px solid var(--border); }
 .campaign-register__quick strong { font-size:23px; }
 .campaign-register__chart { padding:12px;margin-bottom:16px; }
 .campaign-register__chart figcaption { align-items:flex-start;flex-direction:column;gap:3px;margin-bottom:4px; }
 .campaign-register__chart svg { height:92px; }
 .campaign-register__legend { gap:5px 10px; }
 .campaign-register__legend small { margin-left:0;flex-basis:100%; }
 .campaign-register__row { grid-template-columns:minmax(0,1fr) minmax(110px,.7fr) 12px;gap:10px;padding:14px 12px; }
 .campaign-register__identity { grid-column:1/3; }
 .campaign-register__arrow { grid-column:3;grid-row:1/3; }
 .campaign-register__period { font-size:11px; }
 .campaign-register__states { text-align:right; }
}
@media (prefers-reduced-motion:reduce) { .campaign-register__row,.campaign-register__quick button { transition:none; } }

/* One selected original, shared with the customer and campaign workspaces. */
.material-work { max-width:1360px;margin:0 auto;container-type:inline-size;color:var(--text-primary); }
.material-work__heading { display:flex;align-items:center;justify-content:space-between;gap:20px;margin-bottom:22px; }
.material-work__heading h1 { font-size:32px;letter-spacing:-.035em;line-height:1.15;margin:4px 0 10px; }
.material-work__heading p { margin:0;font-size:14px;color:var(--text-secondary); }
.material-work__toolbar { display:flex;gap:12px;margin-bottom:14px; }
.material-work__toolbar > label:first-child { flex:1;min-width:0; }
.material-work__toolbar > button { flex-shrink:0;font-size:12px; }
.material-work input,.material-work select { min-height:42px;padding:10px 12px;width:100%;min-width:0;border:1px solid var(--border);border-radius:8px;background:var(--surface);color:var(--text-primary);font:inherit;font-size:14px; }
.material-work__states { display:flex;gap:6px;flex-wrap:wrap;margin:0 0 12px; }
.material-work__state { min-height:42px;display:flex;align-items:center;gap:12px;padding:9px 12px;border:1px solid var(--border);border-radius:8px;background:var(--surface);color:var(--text-secondary);font:inherit;font-size:12px;cursor:pointer; }
.material-work__state strong { font-size:14px;color:var(--text-primary);font-variant-numeric:tabular-nums; }
.material-work__state[aria-pressed=true] { background:var(--accent-soft);color:var(--accent-strong);border-color:var(--accent-strong); }
.material-work__filters { border-bottom:1px solid var(--border);margin-bottom:14px;padding-bottom:12px; }
.material-work__filters > summary { cursor:pointer;font-size:13px;font-weight:600; }
.material-work__filters > summary span { font-size:12px;font-weight:400;color:var(--text-secondary);margin-left:12px; }
.material-work__filters form { display:grid;grid-template-columns:1.2fr 1fr 1fr 1.2fr auto;gap:12px;align-items:end;margin-top:14px; }
.material-work__filters label { display:grid;gap:6px;font-size:12px;min-width:0; }
.material-work__starts { display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:16px;margin:0 0 20px; }
.material-work__starts button { display:grid;grid-template-columns:1fr auto;gap:9px;background:none;border:0;color:var(--text-secondary);font:inherit;font-size:12px;text-align:left;cursor:pointer;padding:8px 0; }
.material-work__starts button strong { color:var(--text-primary);font-size:18px;font-variant-numeric:tabular-nums; }
.material-work__starts button[aria-pressed=true] { color:var(--accent-strong); }
.material-work__bar { grid-column:1/-1;display:block;height:4px;background:var(--border);border-radius:3px;overflow:hidden; }
.material-work__bar i { display:block;height:100%;background:var(--accent-strong);transition:width 180ms ease-out; }
.material-work__layout { display:grid;grid-template-columns:minmax(260px,.8fr) minmax(0,1.4fr);gap:22px;align-items:start; }
.material-work__selection { border:1px solid var(--border);border-radius:10px;background:var(--surface);min-width:0;overflow:hidden; }
.material-work__selection > summary { padding:14px 16px;cursor:pointer;font-size:13px; }
.material-work__selection > summary span { display:block;font-size:12px;color:var(--text-secondary);margin-top:5px; }
.material-work__rows { list-style:none;margin:0;padding:0;max-height:min(58svh,660px);overflow:auto;overscroll-behavior:contain;scrollbar-gutter:stable; }
.material-work__rows > li { border-top:1px solid var(--border); }
.material-work__row { display:grid;gap:7px;text-align:left;padding:15px 16px;width:100%;border:0;border-left:1px solid transparent;background:none;color:var(--text-secondary);font:inherit;font-size:12px;cursor:pointer;overflow-wrap:anywhere;transition:background-color 150ms; }
.material-work__row > span:first-child { display:grid;gap:5px; }
.material-work__row strong { color:var(--text-primary);font-size:14px; }
.material-work__row small { font-size:11px; }
.material-work__row-status { color:var(--accent-strong);font-weight:600; }
.material-work__row:hover { background:var(--surface-inset); }
.material-work__row[aria-pressed=true] { border-left-color:var(--accent-strong);background:var(--accent-soft); }
.material-work__group { padding:9px 16px;background:var(--surface-inset);font-size:12px;font-weight:650; }
.material-work__selection nav { display:flex;gap:10px;align-items:center;flex-wrap:wrap;padding:12px;font-size:12px; }
.material-work__selection nav:empty { display:none; }
.material-work__detail { min-width:0;border:1px solid var(--border);border-radius:10px;background:var(--surface);padding:24px; }
.material-work__original h2 { margin:5px 0 10px;font-size:23px;line-height:1.2;letter-spacing:-.02em;overflow-wrap:anywhere; }
.material-work__original p { margin:6px 0;color:var(--text-secondary);font-size:13px; }
.material-work__original > a { display:inline-block;margin-top:9px;font-size:13px; }
.material-work__version { display:flex;justify-content:space-between;gap:12px;align-items:center;margin:20px 0 16px;padding-top:16px;border-top:1px solid var(--border);font-size:12px;color:var(--text-secondary); }
.material-work__version strong { color:var(--text-primary); }
.material-work__outside { padding:12px;background:var(--surface-inset);border:1px solid var(--border);border-radius:8px;font-size:13px;line-height:1.5;margin:16px 0; }
.material-work__detail .material-panel { border:0;padding:0;background:none; }
.material-work button:focus-visible,.material-work a:focus-visible,.material-work summary:focus-visible { outline:2px solid var(--accent-strong);outline-offset:-2px; }
@container (max-width:760px) {
 .material-work__heading { align-items:flex-start;gap:8px;margin-bottom:16px; }
 .material-work__heading h1 { font-size:26px; }
 .material-work__heading > button { font-size:12px;padding:8px; }
 .material-work__toolbar { flex-wrap:wrap;gap:8px; }
 .material-work__toolbar > label:first-child { flex-basis:100%; }
 .material-work__toolbar select { min-height:36px;padding:7px 10px;font-size:12px; }
 .material-work__states { gap:5px; }
 .material-work__state { flex:1 0 29%;justify-content:space-between;padding:8px;font-size:11px;gap:5px; }
 .material-work__filters > summary span { display:block;margin:5px 0 0;font-size:11px; }
 .material-work__filters form { grid-template-columns:repeat(2,minmax(0,1fr)); }
 .material-work__filters label:first-child { grid-column:1/-1; }
 .material-work__filters button { align-self:end; }
 .material-work__starts { gap:10px;margin-bottom:12px; }
 .material-work__starts button { font-size:11px;gap:5px;align-items:center; }
 .material-work__starts button strong { font-size:17px; }
 .material-work__layout { grid-template-columns:minmax(0,1fr);gap:12px; }
 .material-work__detail { padding:16px; }
 .material-work__original h2 { font-size:22px; }
}
@media(prefers-reduced-motion:reduce) { .material-work__row,.material-work__bar i { transition:none; } }
.material-preview { margin:12px 0 18px;padding:12px;border:1px solid var(--border);border-radius:8px;background:var(--surface-inset); }
.material-preview > header { display:flex;align-items:center;justify-content:space-between;gap:12px;margin-bottom:10px;font-size:13px;overflow-wrap:anywhere; }
.material-preview img,.material-preview video { display:block;width:100%;height:auto;max-height:420px;object-fit:contain;background:var(--surface);border-radius:4px; }
.material-preview [data-preview-content] { font-size:13px;color:var(--text-secondary); }

.material-file__open .material-file__preview-label { display:block;margin-top:7px;color:var(--accent-strong);text-decoration:underline;text-underline-offset:3px;font-size:12px; }

/* ============================================================
   Patch-Integration — Namensraum vk-; Quelle: docs/design/patch-verkauf.css
   Der Block wird bei Integration als GANZES ersetzt, nie editiert.
   Verkaufsflächen (Kunden, Detail, Offerten) nach Owner-Referenz
   (Team Verkauf, Welle 31.07.).
   ============================================================ */
/* `.vk-kopf__akt` ist am 19.08.2026 gefallen: mit `sales-offers.js` trug die
   LETZTE Fläche ihren eigenen Kopf. Die Zeilen sind nicht gelöscht, sondern
   umgehängt — auf den Handgriff-Bereich des EINEN Seitenkopfs innerhalb der
   Marke `.vk-kopf`. So bleibt das Handy-Bild genau, wie es war, und es gibt
   trotzdem nur noch eine Hülle.

   NACHTRAG 04.09.2026 — SEIT HEUTE STIMMT ER AUCH. Bis heute war der Satz zu
   früh: die KUNDENAKTE erzeugte die Hülle als einzige weiter (Kleid «kunde» in
   components/akte-kopf.js), und weil die Regeln hier schon weg waren, war ihr
   Handgriff-Bereich ein nackter Block — «Neue Offerte · Bearbeiten» in Zeile
   eins, «Archivieren» in Zeile zwei, gemessen am 390er-Bild. Das Kleid trägt
   jetzt den Namen des Hauses (`lx-seitenkopf__akt`) und erbt damit die Regeln
   unten; die Hülle ist wirklich gefallen. Der Weg war ausdrücklich NICHT, ihr
   hier neue Regeln zu geben: eine wiederbelebte Hülle wäre eine zweite Bauart
   für dieselbe Frage. */
/* =========================================================================
   Verkauf — Kunden (#/v/customers), Kunden-Detail (#/v/customer/:id) und
   Offerten (#/v/offers) in der Sprache der Owner-Referenz
   `docs/design/referenzen/Portaluikomplett/ChatGPT Image 29. Juli 2026,
   13_25_27.png` (Projekt-Karten der «Kommandozentrale») und
   `13_25_56 (3).png` (Detailfläche mit Kachelzeile, Tabs, gerahmten Panels).

   OWNER-URTEIL 31.07. über den Ist-Zustand dieser drei Flächen:
   «billig, overengineered, endlose Listen». Gemessen war das dreimal wahr:
     · drei Tabellen mit 7–9 gleich breiten Spalten, 25 gleichförmige Zeilen
       untereinander — die Referenz zeigt an derselben Stelle 2×2 Karten mit
       Kopf, Balken und Fusszeile;
     · rahmenlose Panels auf flachem Schwarz, während in der Referenz JEDER
       Abschnitt ein umrandeter Kasten auf gehobener Fläche mit türkis
       getönter Kante ist;
     · im Kunden-Detail drei Kennzahl-Streifen mit neun 26px-Zahlen
       übereinander — eine Zahlen-Wand, keine Aussage.

   DIE ANATOMIE, die diese Datei durchsetzt (alles aus der Referenz):
     1. Kachel: Zeichen im Soft-Quadrat · Zahl 22px · CAPS-Label 10.5px/.08em
        · eine Subzeile 11.5px. Nie Zeichen NEBEN dem Label (auf 390px bleibt
        sonst kein Platz fürs Wort).
     2. Karte: Kopf (Zeichen · Titel · Zustands-Chip GANZ RECHTS) · Subzeile ·
        Balken-Held mit Prozentwert (nur wo ein echter Anteil existiert) ·
        Fusszeile mit höchstens drei Angaben, Trennpunkt dazwischen.
     3. Panel: `var(--surface)`, 1px Kante in `rgba(var(--accent-rgb), .16)`,
        Radius 14px, CAPS-Kopf.
     4. Spalten-Gruppen sind EIN Kasten mit inneren Trennlinien — nie drei
        lose Boxen, die «neben aussen» schwimmen.
     5. Der Fortschritt leuchtet: Türkis mit Schein.

   Bausteine aus style.css werden benutzt, nicht ersetzt: .panel, .stat,
   .stat__value/__label/__sub, .stat__bar, .sl-badge, .ghost-btn,
   .primary-btn, .seg, .modal__tab, .pagination. Das Symbol-Quadrat .gz-ic
   stammt aus patch-zentrale.css (dort die Bauart) — hier kommt nur der
   Farbkanal dazu, den diese Fläche braucht. Präfix vk- für alles Eigene.
   Der Orchestrator hängt diese Datei an style.css an; sie steht darum NACH
   allen Basisregeln und darf sie mit gleicher Spezifität stechen
   (Memory project_css_cascade_mobile).
   ========================================================================= */

/* --- 0. Farbkanal + Kante ----------------------------------------------- */
/* Vier ruhige Töne, dieselben Zahlen wie in der Zentrale — damit «Kunde» hier
   dieselbe Farbe hat wie dort. Sie tragen NUR Soft-Felder hinter einem
   Zeichen, nie Text, nie Fläche, nie einen Knopf: Türkis bleibt der EINE
   Akzent für Aktion und Positivwert (EINHEIT.md 1.3). */
.vk {
  --vk-kunde:    246, 155, 118;   /* Koralle — Kundinnen und Kunden */
  --vk-offerte:  122, 178, 255;   /* Blau    — Angebot, Offerte      */
  --vk-geld:     236, 190, 112;   /* Gold    — Rechnung, Guthaben    */
  --vk-standort: 112, 208, 154;   /* Grün    — Standorte, Buchungen  */
  --vk-kante: rgba(var(--accent-rgb), .16);
  --gz-feld: var(--tint-rgb);     /* Rückfall: nie eine tote var()   */
}
.vk .vk-t--kunde    { --gz-feld: var(--vk-kunde); }
.vk .vk-t--offerte  { --gz-feld: var(--vk-offerte); }
.vk .vk-t--geld     { --gz-feld: var(--vk-geld); }
.vk .vk-t--standort { --gz-feld: var(--vk-standort); }
.vk .vk-t--neutral  { --gz-feld: var(--tint-rgb); }

/* Initialen statt Strich-Zeichen — dieselbe Bauart wie .gz-ic, nur mit
   Buchstaben (EINHEIT.md 1.8: Initialen, eine Farbe je Bereich, keine Farbe
   je Person). Ein Kundenname trägt so sein Zeichen, ohne dass eine Farbe
   eine Bedeutung vortäuscht, die sie nicht hat. */
.vk .gz-ic.vk-ini {
  font-size: 11px; font-weight: 650; letter-spacing: .02em;
  font-variant-numeric: normal;
}

/* --- 1. Kopf ------------------------------------------------------------ */
/* EINHEIT.md 1.5: Seitentitel 26px/650/-.02em, gemischte Schreibung, ohne
   Icon. EINHEIT.md 1.6: KEIN Erklärtext darunter — ein Werkzeug erklärt sich
   nicht, es zeigt Funktion (feedback_tool_not_website). */
.vk-kopf {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 12px; flex-wrap: wrap; margin-bottom: 16px;
}
.vk-kopf h1 {
  margin: 0; font-size: 26px; font-weight: 650; letter-spacing: -.02em;
  color: var(--text-primary); min-width: 0;
}
.vk-kopf__zeile { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; min-width: 0; }
.vk-kopf__ort {
  font-size: 13px; font-weight: 500; color: var(--text-tertiary);
  display: inline-flex; align-items: center; gap: 5px;
}
.vk-kopf__ort svg { width: 13px; height: 13px; }
.vk-kopf .lx-seitenkopf__akt { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-left: auto; }

/* Der eigene Brotkrumen-Pfad dieser Flaeche ist am 17.08. ERSETZT worden:
   das Ortsschild zeichnet die Schale seither zentral fuer JEDE Flaeche
   (`components/ortsschild.js`, Tabelle `config/bereiche.js`, Gesetz
   docs/BEREICHE.md §3). Die Klassen `.vk-krume` standen danach noch hier und
   trugen nichts mehr — «Ersetzen statt daneben»; entfernt 18.08. */

/* --- 2. Kachelzeile ----------------------------------------------------- */
/* Auto-fit auf gleiche Anteile: drei oder vier Kacheln füllen dieselbe eine
   Reihe. Wer ein Recht nicht hat, sieht die Kachel gar nicht — eine feste
   Viererreihe hinterliesse dort eine Lücke. */
/* EINE KACHEL-BAUART (25.08.): dieselbe Karte wie `.stat` — Flaeche,
   Haarlinie, Radius 14, `18px 20px`. Offerten und Rechnungen sind
   Nachbarreiter und trugen bis heute verschiedene Kacheln (13/14-Polsterung,
   Wert 22px, Label in gesperrten Versalien gegen 19/20, 26px, gemischt). */
.vk-kacheln {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(0, 1fr));
  gap: 14px; margin-bottom: 14px;
}
.vk-kachel {
  display: flex; flex-direction: column; align-items: flex-start; gap: 5px;
  padding: 18px; min-width: 0;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-card); text-decoration: none; color: inherit;
  transition: background var(--transition), border-color var(--transition);
}
/* ENTFERNT 25.08. (Rueckweg git): `.vk-kachel:first-child { border-left: 0;
   padding-left: 0 }`. Mit eigener Karte beginnt keine Kachel mehr an der
   Seitenkante; die hoehere Spezifitaet stach ausserdem die Geraete-Polsterung
   durch (derselbe Befund wie bei `.stat:first-child`, docs/design/grund.css). */
a.vk-kachel:hover { background: var(--surface-hover); border-color: var(--line-strong); }
.vk-kachel:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.vk-kachel .gz-ic { --gz-ic-gr: 26px; margin-bottom: 5px; }
/* 25.08.: dieselbe Zahl wie ueberall (26px/650/-.5, `.stat__value`). Der
   Sondergrad 22px stammte aus dem Nebeneinander-Beleg vom 31.07., als die
   Kachel keine eigene Karte hatte und vier davon kantenbuendig standen; mit
   Karte und Fuge hat die Zahl ihren Platz. Label 12.5px in gemischter
   Schreibung — gesperrte Versalien tragen genau EINE Aufgabe (EINHEIT §1.5:
   den Tabellenkopf). */
/* DIE ZAHL BRICHT NIE UM (27.08.2026) — und darum springt die Liste nicht.
   GEMESSEN mit `node scripts/_ladezustand_test.mjs` (Desktop 1400px): die
   Kachelzeile war beim Laden 162px hoch und danach 191px, die Liste sprang
   325 → 354px. Ursache in zwei Gliedern, eine Wurzel:
     1. Nach der Antwort erscheint die BEDINGTE sechste Kachel («Abgelaufen»,
        nur bei echtem Rueckstand). Aus fuenf Spalten werden sechs, jede
        Kachel schrumpft 269 → 222px. Das Skelett kann das nicht vorhersehen —
        es weiss vor der Antwort nicht, ob es die Kachel geben wird.
     2. In 222px passt «CHF 24'000.00» bei 26px nicht mehr auf eine Zeile.
        Der Wert bricht um, `stat__value` waechst 29 → 58px, und DAS schiebt
        die ganze Liste.
   Glied 1 ist richtig so (eine Kachel, die monatelang 0 zeigt, ist Laerm).
   Also faellt Glied 2: die Kachelhoehe darf nicht mehr an der Kachelbreite
   haengen. Das ist genau die Entscheidung, die das Haus am 25.08. schon fuer
   das Handy getroffen hat — «eine zerrissene Geldzahl ist schlimmer als eine
   kleinere» (grund.css @420px, patch-vertraege.css). Sie galt bisher nur
   unter 420px; am Rechner brach dieselbe Zahl weiter um.
   Die Groesse folgt der Kachel, nicht dem Fenster (`cqi`): bei sechs Kacheln
   ist die Kachel schmaler, und nur sie weiss das. 26px bleibt der Deckel —
   die Zahl sieht bei fuenf Kacheln aus wie bisher. */
.vk-kachel { container-type: inline-size; }
.vk-kachel .stat__value {
  font-size: clamp(19px, 12cqi, 26px);
  /* Die ZEILE ist so hoch, wie die Zahl bei voller Groesse waere — nicht so
     hoch, wie sie gerade ist. Sonst haette die Schrumpfung den Sprung nur
     kleiner gemacht (gemessen: 162 → 157px statt 162 → 191px), nicht
     beseitigt. Am Handy setzt patch-offertenliste.css beide Werte selbst
     (18px/1.15) und bleibt damit unberuehrt. */
  line-height: calc(26px * 1.12);
  white-space: nowrap;
}
.vk-kachel .stat__label {
  font-size: 12.5px; letter-spacing: 0; text-transform: none;
  color: var(--text-secondary); max-width: 100%;
}
/* DIE ERKLAERZEILE RESERVIERT IHRE HOEHE — ZWEI ZEILEN, IMMER (18.08.2026).
   GEMESSEN, nicht geschaetzt: `node scripts/_ladezustand_test.mjs` war rot mit
   «Kachelzeile vorher 127px · nachher 142px» (Desktop 1400px). Ursache am Bild
   nachgemessen: die Unterzeile der Kachel «Offen» lautet «CHF 8'000.00
   abgelaufen — nicht mehr mitgezaehlt» und BRICHT auf zwei Zeilen; die vier
   Nachbarkacheln brauchen eine. Das Ladeskelett kann diese Hoehe gar nicht
   kennen — sie haengt an den DATEN, die noch unterwegs sind. Ein Skelett, das
   sie raet, waere die zweite Wahrheit, an der die Flaechen bisher gesprungen
   sind (components/skeleton.js, Kopfkommentar).
   Also wird die Hoehe FEST: zwei Zeilen, in der Kachel wie im Skelett. Nichts
   ist geraten — `min-height: 2.6em` sind exakt zwei Zeilenkaesten der
   `line-height: 1.3`, die eine Zeile darueber steht. Am Bild aendert sich
   nichts: die Zeile war schon bisher so hoch wie ihre hoechste Kachel (Grid
   streckt), nur das Skelett war es nicht. `-webkit-line-clamp: 2` haelt die
   Hoehe auch dann, wenn eine kuenftige Unterzeile drei Zeilen braeuchte —
   ohne Deckel waere der Sprung morgen wieder da.
   Am Handy faellt die Unterzeile ganz weg (patch-offertenliste.css,
   patch-handy-verkauf.css `display:none`) — dort wirkt keine der Regeln. */
.vk-kachel .stat__sub {
  font-size: 11.5px; line-height: 1.3; min-height: 2.6em;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
}
.vk-kachel .stat__sub.is-warn { color: var(--warn-strong); }

/* --- 3. Werkzeugleiste -------------------------------------------------- */
/* Suche, Zustands-Chips und Zähler in EINER Zeile, wie in der Referenz
   («Vertrieb suchen …» + Status + «24 Vertriebe»). */
.vk-leiste {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin-bottom: 12px;
}
.vk-suche {
  display: inline-flex; align-items: center; gap: 8px; flex: 1 1 260px;
  min-width: 0; max-width: 420px; height: 36px; padding: 0 12px;
  background: var(--surface-inset); border: 1px solid var(--vk-kante);
  border-radius: var(--radius-card); color: var(--text-secondary);
}
.vk-suche svg { width: 15px; height: 15px; flex: 0 0 auto; }
/* SIE ROLLT, STATT UMZUBRECHEN — auf JEDER Breite, ohne Geraeteblock
   (04.09.2026), wie `.so-toolbar__reihe` in grund.css. Am Schreibtisch ist
   Platz genug, dort rollt nichts: dieselbe Regel, zwei Bilder.
   `flex: 0 0 auto` ist tragend — ohne sie schrumpfen die Griffe auf ihre
   Mindestbreite, statt zu rollen. */
.vk-leiste__reihe {
  display: flex; align-items: center; gap: 10px;
  flex-wrap: nowrap; overflow-x: auto;
  overscroll-behavior-x: contain; scrollbar-width: none;
}
.vk-leiste__reihe::-webkit-scrollbar { width: 0; height: 0; }
.vk-leiste__reihe > * { flex: 0 0 auto; }
.vk-suche input {
  flex: 1; min-width: 0; background: none; border: 0; outline: none;
  color: var(--text-primary); font-size: 13px; font-family: inherit;
}
.vk-suche input::placeholder { color: var(--text-tertiary); }
.vk-suche:focus-within { border-color: var(--accent); }
.vk-zaehler {
  font-size: 11.5px; letter-spacing: .04em; text-transform: uppercase;
  color: var(--text-tertiary); font-variant-numeric: tabular-nums;
  margin-left: auto; white-space: nowrap;
}
/* Filter als ruhige Chips (kein zweiter Knopfstil neben .primary-/.ghost-btn). */
.vk-filter {
  display: inline-flex; align-items: center; gap: 6px; height: 32px;
  padding: 0 12px; border-radius: var(--radius-badge); cursor: pointer;
  background: transparent; border: 1px solid var(--border);
  /* Seit v395 im Segment-Kleid der Referenz (wie .kf-segment, .seg): gesperrte
     Versalien, 11px/650 — am Bild (offerten-1440, 03.09.) standen hier runde
     Pillen in gemischter Schreibung neben Versal-Segmenten derselben Leiste. */
  color: var(--text-secondary); font-size: 11px; font-weight: 650; letter-spacing: .06em; text-transform: uppercase;
  font-family: inherit; white-space: nowrap;
  transition: background var(--transition), border-color var(--transition), color var(--transition);
}
.vk-filter:hover { color: var(--text-primary); border-color: var(--line-strong); }
.vk-filter.is-active {
  background: var(--accent-soft); border-color: var(--accent-line); color: var(--accent-strong);
}
/* `display: inline-flex` sticht das eingebaute `[hidden] { display: none }` —
   ohne diese Zeile stünde ein Filter sichtbar da, den es nicht geben darf. */
.vk-filter[hidden], .vk [hidden] { display: none; }

/* Ruhiger Zustands-Chip: gerahmtes Wort ohne Farbaussage (EINHEIT.md 4.7 —
   nie ein farbiges Wort ohne Rahmen, aber auch nicht jede Karte grün). */
.sl-badge--still { background: rgba(var(--tint-rgb), .07); color: var(--text-secondary); border-color: var(--border); }

/* --- 4. Karten-Raster --------------------------------------------------- */
/* 300px statt 215px: erst ab dieser Breite trägt die Kopfzeile Zeichen,
   vollen Namen UND den Zustands-Chip nebeneinander — genau die Anatomie der
   Referenz-Projektkarte. Ein abgeschnittener Firmenname ist das Billige,
   das hier verschwinden soll. */
/* FLACH STATT KASTEN (Owner «Widget», 2026-08-13): das Raster behaelt seine
   Spaltenzahl (`auto-fill`, unveraendert — die Dichte der Flaeche aendert
   sich nicht), aber die Fuge waechst waagerecht und schrumpft senkrecht. Der
   Grund: die Karte traegt jetzt statt eines Rahmens eine Haarlinie UNTER sich.
   Waagerecht trennt der Abstand (24px), senkrecht die Linie — beides sind
   erlaubte Gruppierungsmittel; ein Rahmen ist keines mehr. */
/* 25.08.: echte Fuge statt 2px. Die Karte traegt seit heute wieder ihre
   eigene Kante — bei 2px Abstand beruehrten sich zwei Kanten und ergaeben
   einen doppelten Strich. */
.vk-raster {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 14px; align-items: stretch;
}
/* Drei feste Zeilen: Kopf · Mitte (Balken oder Chips) · Fuss. Die mittlere
   dehnt sich — dadurch stehen alle Fusszeilen einer Reihe auf einer Linie,
   auch wenn eine Karte weniger zu sagen hat. */
/* DIE OFFERTEN- UND KUNDENKARTE IST WIEDER EINE KARTE (25.08.2026).
   Vom 13.08. bis heute war sie eine Rasterzelle mit einer Haarlinie unten und
   2px Fuge. Sie steht aber in einem DREISPALTIGEN Raster (`.vk-raster`,
   `repeat(auto-fill, minmax(300px, 1fr))`) — eine Haarlinie unten trennt in
   einem Raster gar nichts: sie sagt «hier endet Spalte 1, Zeile 1» und
   schweigt zu links und rechts. Am Bild vom 25.08. («offerten-1400.png»)
   stehen drei Angebote nebeneinander, und nichts sagt, wo eines aufhoert.
   Die Referenz zeigt jede Zeile eines Panels als eigene Flaeche mit Kante
   (docs/design/referenzen/Kundenansichtenportal/«… 13_21_30 (12).png»,
   Block «Aktive Kampagnen»). Owner-Wort 13.08. war «nicht wie ein Widget
   ueber der Flaeche schweben» — der Schatten und die abhebende Stufe bleiben
   weg; was zurueckkommt, ist die Kante. */
.vk-karte {
  display: grid; grid-template-rows: auto 1fr auto; gap: 9px;
  padding: 16px 18px; min-width: 0;
  /* Bezugsrahmen fuer die Fangflaeche der Tuer (patch-kundenkarte-griff.css
     §3): die Karte IST die Tuer, der Name traegt sie nur sichtbar. Ohne
     `position` haenge das Band am Fenster statt an der Karte. */
  position: relative;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-card); color: inherit; text-decoration: none;
  transition: background var(--transition), border-color var(--transition);
}
.vk-karte:hover { background: var(--surface-hover); border-color: var(--line-strong); }
.vk-karte:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.vk-karte.is-still { opacity: .62; }
/* Die Karte IST die Tür — auch dort, wo sie kein <a> ist (Offerte: sie trägt
   eigene Knöpfe, ein <a> um <button> wäre ungültiges Markup). */
article.vk-karte { cursor: pointer; }
.vk-filterreihe { display: inline-flex; align-items: center; gap: 6px; flex-wrap: wrap; }

/* Der Name geht vor: der Kopf darf umbrechen, damit der Chip unter den Namen
   rutscht, statt ihn zu beschneiden («Barbershop Zentral GmbH» fiel bei 4
   Spalten um 21 px, 03.09.). Er bricht NUR um, wenn der Name sonst fällt —
   die Breite des Namens ist die Basis, die Unterzeile zählt nicht mit. */
.vk-karte__kopf { display: flex; align-items: center; gap: 6px 10px; min-width: 0; flex-wrap: wrap; }
.vk-karte__kopf .gz-ic { --gz-ic-gr: 28px; }
.vk-karte__wer { display: grid; gap: 1px; min-width: 0; flex: 1 1 max-content; }
.vk-karte__titel {
  font-size: 13px; font-weight: 600; color: var(--text-primary);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.vk-karte__sub {
  font-size: 11.5px; color: var(--text-secondary);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  /* Zählt nicht zur Kopfbreite — nur der Name entscheidet über den Umbruch.
     (`width: 0; min-width: 100%` fiel unter 1280 px auf 0 px zusammen —
     Breitenprobe 03.09.; Grössen-Eindämmung ist der saubere Weg.) */
  contain: inline-size;
}
/* Der Chip bleibt rechts — in der Namenszeile, wenn Platz ist, sonst darunter. */
.vk-karte__kopf .sl-badge { flex: 0 0 auto; margin-left: auto; }

/* Die Mitte der Karte ist EINE Zeile des Rasters, auch wenn sie Balken UND
   Chip-Reihe trägt — sonst rutschen die Fusszeilen einer Reihe auseinander. */
.vk-karte__mitte { display: grid; gap: 8px; align-content: center; min-width: 0; }

/* Balken-Held: Balken und sein Prozentwert in EINER Zeile, der Wert
   rechtsbündig am Ende — wie an jeder Projektkarte der Referenz. */
.vk-karte__lauf { display: grid; gap: 5px; align-content: center; min-width: 0; }
.vk-karte__balken { display: flex; align-items: center; gap: 10px; min-width: 0; }
.vk-karte__balken .stat__bar { flex: 1 1 auto; min-width: 0; margin-top: 0; }
.vk-karte__pct {
  flex: 0 0 auto; font-size: 11.5px; font-weight: 600; color: var(--text-secondary);
  font-variant-numeric: tabular-nums lining-nums;
}
.vk-karte__wort { font-size: 11.5px; color: var(--text-tertiary); }
/* Wo es keinen echten Anteil gibt, steht statt einer Leerfläche eine
   Tatsache: gemessene Nebenwerte als Wort-Chips (EINHEIT.md 4.3). */
.vk-karte__chips { display: flex; flex-wrap: wrap; gap: 5px; align-content: center; min-width: 0; }
.vk-chip {
  display: inline-flex; align-items: center; padding: 3px 9px;
  border-radius: var(--radius-badge); font-size: 11px; font-weight: 600;
  background: rgba(var(--tint-rgb), .07); color: var(--text-secondary);
  white-space: nowrap;
}
.vk-chip--warn { background: rgba(var(--warn-rgb), .13); color: var(--warn-strong); }

/* Fusszeile: höchstens drei Angaben, Trennpunkt dazwischen. */
.vk-karte__fuss {
  display: flex; flex-wrap: wrap; gap: 3px 8px; font-size: 11px;
  color: var(--text-tertiary); font-variant-numeric: tabular-nums;
  padding-top: 8px; border-top: 1px solid var(--border);
}
.vk-karte__fuss > span + span::before { content: '· '; color: var(--text-secondary); }
.vk-karte__fuss .is-warn { color: var(--warn-strong); }
/* Zeilen-Aktionen in der Karte: klein, rechts, nie über zwei Zeilen laut. */
.vk-karte__akt { display: flex; flex-wrap: wrap; gap: 6px; justify-content: flex-end;
  /* ueber der Fangflaeche der Tuer — sonst schluckt sie «Offerte fuer
     diesen Kunden» (patch-kundenkarte-griff.css §3). */
  position: relative; z-index: 1; }
.vk-karte__akt .ghost-btn,
.vk-karte__akt .primary-btn { min-height: 30px; padding: 4px 11px; font-size: 12px; }
/* 03.09., Owner am Handybild: «sehr überladen, kleine Texte, sehr technisch».
   Die Karte trägt EINE Hauptaktion; alles Weitere liegt hinter «Mehr» —
   aufgeklappt nimmt es die ganze Breite der Aktionszeile. */
.vk-karte__mehr { display: contents; }
.vk-karte__mehr > summary { list-style: none; cursor: pointer; }
.vk-karte__mehr > summary::-webkit-details-marker { display: none; }
.vk-karte__mehr[open] > summary { color: var(--accent); }
.vk-karte__mehr-liste { flex: 1 1 100%; display: flex; flex-wrap: wrap; gap: 6px; justify-content: flex-end; margin-top: 6px; }


/* --- 5. Panels ---------------------------------------------------------- */
/* In der Referenz ist JEDER Abschnitt ein umrandetes Panel auf gehobener
   Fläche mit türkis getönter Kante. Rahmenlos auf flachem Schwarz war der
   Grund, warum Abschnitte «neben aussen» wirkten. */
/* FLACH STATT KASTEN (Owner «Widget», 2026-08-13): der Satz darueber ist der
   Rahmen-Pass vom 31.07. Er ist am 13.08. ausdruecklich verworfen worden —
   «Ich sehe das immer noch als ein Element oben auf dem Hintergrund drauf».
   Der Abschnitt wird jetzt von seinem Versalien-Titel (`.vk-panel__titel`)
   und einer Haarlinie darueber getragen; 14px + 1px Rahmen = 15px Padding
   oben, damit die Hoehe bleibt. */
.vk-panel {
  background: transparent; border: 0; border-top: 1px solid var(--border);
  border-radius: 0; padding: 15px 0; margin-bottom: 0;
}
/* KEINE `:first-child`-Ausnahme — gemessen (Buehne 13.08., #/v/customer/:id):
   jedes `.vk-panel` steckt in einer EIGENEN Huelle, ist also immer das erste
   Kind. Eine `:first-child`-Regel haette schlicht JEDE Linie entfernt und die
   Abschnitte ohne Trennung uebereinander gestapelt. Die Linie ueber dem
   ersten Abschnitt ist ausserdem richtig: sie schliesst den Kopf der Flaeche
   (Titel, Brotkrume, Kennzahlen) gegen den Inhalt ab. */
.vk-panel:last-child { padding-bottom: 0; }
/* `nowrap` statt `wrap` (04.09.2026): am Telefon brach diese Zeile um, und der
   Zeitraum-Schalter stand als eigener 52-px-Block ueber den Zahlen — genau das,
   was die Referenz an dieser Stelle nicht hat. Am Schreibtisch ist Platz genug;
   dort aendert die Zeile nichts. Der Titel darf dafuer schrumpfen (`min-width`
   unten) — ohne das kann ein Flex-Kind nicht unter seine Inhaltsbreite. */
.vk-panel__kopf {
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px; flex-wrap: nowrap; margin-bottom: 8px;
}
/* Die Fussnote unter der ersten Kennzahl-Zeile («Stand … — unabhaengig vom
   gewaehlten Zeitraum»). Sie trug ihre Masse als Inline-Vorgabe im Markup und
   stand als voller Absatz zwischen den beiden Zeilen; jetzt ist sie das, was
   sie ist: die kleine Zeile ueber der zweiten Reihe. EINE Regel, kein
   Geraeteblock — sie ist auf jedem Schirm dieselbe Fussnote. */
.vk-gruppe__stand { margin: 8px 0 4px; font-size: 11px; color: var(--text-tertiary); }
/* CAPS gehört in diesem System dem Abschnittskopf und dem Kachel-Label —
   die Referenz schreibt «PROJEKT OVERVIEW», «AKTIVE MISSIONEN» genau so. */
.vk-panel__titel {
  margin: 0; font-size: 11px; font-weight: 650; letter-spacing: .08em;
  text-transform: uppercase; color: var(--text-secondary);
  display: inline-flex; align-items: center; gap: 8px; min-width: 0;
}
.vk-panel__titel .gz-ic { --gz-ic-gr: 22px; }
/* Die Meta-Angabe steht IM CAPS-Kopf, trägt dessen Sperrung aber nicht mit —
   sonst wären «Stand 12.06.2026» und der Abschnittsname typografisch gleich
   laut. */
.vk-panel__meta {
  font-size: 11.5px; font-weight: 500; letter-spacing: 0; text-transform: none;
  color: var(--text-tertiary); font-variant-numeric: tabular-nums;
}
/* D4 · Verdichtete Kampagnen-Kopfzeile über der Buchungsliste: Zustand +
   Liefergrad auf einen Blick statt nur roher Zeilen. Unter dem CAPS-Kopf,
   wickelt auf dem Handy um. */
.vk-panel__stand {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin: -2px 0 12px; font-size: 12px; color: var(--text-secondary);
  font-variant-numeric: tabular-nums;
}
/* Ein Panel, das nur EINE Zeile trägt (Herkunft), braucht keine Kopfzeile. */
.vk-panel--schmal { padding: 8px 10px; }
.vk-panel--schmal .vk-zeile { background: transparent; padding: 4px 2px; }

/* EIN ABSCHNITT, DER SICH WEGKLAPPT (13.08.2026, Prüfer-Befund «Vernetzung»).
   Ein Abschnitt, der 30 Zeilen Nachschau trägt, darf die Reiter darunter nicht
   aus dem Bild schieben. `<details>` bringt Öffnen, Tastatur und Vorlesen vom
   Browser mit (Muster components/zweite-reihe.js) — hier bekommt es nur das
   Aussehen des Panels: derselbe CAPS-Kopf, dieselbe Haarlinie, kein Kasten.
   Das native Dreieck fällt weg und wird durch einen eigenen Winkel ersetzt,
   der beim Öffnen dreht; die Kopfzeile bleibt eine ganze Tapfläche. */
.vk-falt > summary { cursor: pointer; list-style: none; }
.vk-falt > summary::-webkit-details-marker { display: none; }
.vk-falt > summary::marker { content: ''; }
.vk-falt__kopf { min-height: 44px; align-items: center; }
.vk-falt__kopf::after {
  content: ''; flex: none; width: 7px; height: 7px; margin-left: 2px;
  border-right: 1.5px solid var(--text-tertiary); border-bottom: 1.5px solid var(--text-tertiary);
  transform: rotate(-45deg); transition: transform var(--dur-fast, .12s) var(--ease, ease);
}
.vk-falt[open] > .vk-falt__kopf::after { transform: rotate(45deg); }
.vk-falt > summary:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: var(--radius-button); }
/* Die Summe im Kopf steht links vom Winkel und darf ihn nie wegdrücken. */
.vk-falt__kopf .vk-panel__meta { margin-left: auto; }
@media (prefers-reduced-motion: reduce) { .vk-falt__kopf::after { transition: none; } }

/* Balken und Verlaufskurve nebeneinander — die Kurve NUR, wo die Antwort eine
   echte Reihe hat (mindestens zwei Punkte). */
.vk-verlauf { display: flex; align-items: center; gap: 26px; margin-top: 12px; flex-wrap: wrap; }
.vk-verlauf .vk-karte__lauf { flex: 1 1 240px; }
.vk-spark { display: block; width: 110px; height: 28px; flex: 0 0 auto; align-self: center; color: var(--accent); }
.vk-spark svg { width: 100%; height: 100%; }
.vk-spark svg polygon { opacity: .14; }

/* --- 6. Spalten-Gruppe: EIN Kasten mit Trennlinien ---------------------- */
/* Nicht drei lose Boxen: das ist die Struktur, die im Nebeneinander fehlte. */
/* FLACH STATT KASTEN (Owner «Widget», 2026-08-13): der Kasten aussen faellt,
   die Trennlinien innen bleiben — genau wie beim Fussbereich der Zentrale.
   Was die Gruppe zusammenhaelt, ist ihre Bauform (CAPS-Label ueber Wert) und
   die Linie zwischen den Zellen, nicht ein Rahmen um sie herum.
   12px = 11px + die 1px des alten Rahmens; die erste Zelle beginnt an der
   Spaltenkante wie jede andere erste Zelle im Haus. */
.vk-gruppe {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(0, 1fr));
  gap: 0; background: transparent;
  border: 0; border-radius: 0; overflow: visible;
}
.vk-gruppe__zelle { display: grid; gap: 2px; padding: 12px 14px; min-width: 0; }
.vk-gruppe__zelle:first-child { padding-left: 0; }
.vk-gruppe__zelle + .vk-gruppe__zelle { border-left: 1px solid var(--border); }
.vk-gruppe__label {
  font-size: 11px; font-weight: 650; letter-spacing: .08em;
  text-transform: uppercase; color: var(--text-tertiary);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.vk-gruppe__wert {
  font-size: 17px; font-weight: 650; letter-spacing: -.3px; line-height: 1.2;
  color: var(--text-primary); font-variant-numeric: tabular-nums lining-nums;
}
.vk-gruppe__wert.is-warn { color: var(--warn-strong); }
.vk-gruppe__sub { font-size: 11px; color: var(--text-tertiary); font-variant-numeric: tabular-nums; }

/* Kennzahl-Paare in einer Zeile (Label klein, Wert daneben) — für die
   Nebenwerte, die keine eigene 26px-Zahl verdienen. Genau das hat aus drei
   Kachelstreifen eine Zahlen-Wand gemacht. */
/* SIE ROLLT, STATT UMZUBRECHEN (04.09.2026) — dieselbe Antwort wie bei den
   Kennzahl-Zeilen darüber. Am Telefon brachen die sechs Paare («Bezahlt
   gesamt», «Guthaben offen», «Aktive Buchungen», «Standorte», «Plätze»,
   «Offerten») in VIER Zeilen um und schoben die Reiter-Leiste um rund 90 px
   nach unten. Am Schreibtisch ist Platz genug; dort rollt nichts. */
.vk-werte {
  display: flex; gap: 6px 22px; margin-top: 8px;
  flex-wrap: nowrap; overflow-x: auto;
  overscroll-behavior-x: contain; scrollbar-width: none;
}
.vk-werte::-webkit-scrollbar { width: 0; height: 0; }
.vk-werte__paar { display: inline-flex; align-items: baseline; gap: 7px; min-width: 0; flex: 0 0 auto; }
.vk-werte__label {
  font-size: 11px; font-weight: 650; letter-spacing: .08em;
  text-transform: uppercase; color: var(--text-tertiary); white-space: nowrap;
}
.vk-werte__wert {
  font-size: 13px; font-weight: 600; color: var(--text-primary);
  font-variant-numeric: tabular-nums lining-nums; white-space: nowrap;
}
.vk-neben { font-size: 11px; font-weight: 500; color: var(--text-tertiary); white-space: nowrap; }

/* --- 7. Zeilen in Panels ------------------------------------------------ */
/* Referenz-Aktivitätszeile: Zeichen links, zwei Textzeilen in der Mitte,
   Zustand/Zeit rechts. Kein Tabellenkopf, keine Waisen-Reihe. */
/* FLACH STATT KASTEN (Owner «Widget», 2026-08-13): jede Zeile war eine kleine
   gerundete Kachel auf `--surface-2` — in der Buchungshistorie eines Kunden
   standen so bis zu zehn davon untereinander. Jetzt eine Liste: Zeilen auf
   dem Grund, getrennt durch eine Haarlinie (`.kf-loc`-Idiom). Die Fuge (6px)
   wird zum Innenabstand, die Zeilenhoehe bleibt damit gleich. */
.vk-liste { display: grid; gap: 0; }
.vk-zeile {
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center; gap: 10px; min-width: 0;
  padding: 12px 0; background: transparent; border-radius: 0;
  border-bottom: 1px solid var(--border);
  color: inherit; text-decoration: none;
}
.vk-liste > .vk-zeile:last-child { border-bottom: 0; }
.vk-zeile--tuer { transition: background var(--transition); cursor: pointer; }
.vk-zeile--tuer:hover { background: rgba(var(--tint-rgb), .05); }
.vk-zeile--tuer:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.vk-zeile__leib { display: grid; gap: 2px; min-width: 0; }
.vk-zeile__titel {
  font-size: 12.5px; font-weight: 600; color: var(--text-primary);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.vk-zeile__sub {
  display: flex; flex-wrap: wrap; gap: 3px 8px;
  font-size: 11px; color: var(--text-secondary); font-variant-numeric: tabular-nums;
}
.vk-zeile__sub > span + span::before { content: '· '; color: var(--text-tertiary); }
.vk-zeile__rechts {
  display: flex; align-items: center; gap: 8px; flex: 0 0 auto;
  font-size: 11.5px; color: var(--text-tertiary); font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.vk-zeile__geld { font-size: 12.5px; font-weight: 600; color: var(--text-primary); }
.vk-zeile__rechts .vk-wert.is-schlecht { color: var(--bad-strong); }
.vk-zeile__punkt { width: 7px; height: 7px; border-radius: 50%; flex: 0 0 auto; }

/* --- 7b. Die VARIANTEN eines Kunden ------------------------------------- */
/* Owner 03.09.2026: «zweimal art Gallus AG drin … dann muss es doch ein Profil
   von jeder Offerte/Kunde geben — wie viele Varianten».
   Referenz: `referenzen/Portaluikomplett/ChatGPT Image 29. Juli 2026,
   13_25_57 (4).png` — die Versionen-Liste. Übernommen sind ihre drei
   Qualitäten, nicht ihre Bauteile:
     1. SPALTENRUHE — der Zustands-Chip hat eine feste Mindestbreite, damit
        Nummer und Zeitangabe in JEDER Zeile an derselben Stelle beginnen.
        Ohne sie wandert die Nummer zwischen «Entwurf» und «Teilzahlung» um
        rund 40 px, und aus einer Vergleichsliste wird eine Lesekolonne.
     2. EIN ZUSTAND, LINKS UND FARBIG — die Farbe kommt aus `.sl-badge--*`,
        hier wird nichts eingefärbt.
     3. HERKUNFT RECHTS UND LEISE — Betrag fett und rechtsbündig, «Erstellt
        von …» klein darunter; sie konkurriert nie mit der Sache.
   Die geltende Variante trägt links eine Haarlinie in der Wahl-Farbe des
   Hauses (`--accent-rgb`, «hier/gewählt») — nie eine zweite Farbfläche. */
.vko-var { grid-template-columns: auto minmax(0, 1fr) auto; align-items: start; }
/* Die Chip-Spalte: 92px am Schreibtisch, 78px am Handy — als EINE Regel.
   `clamp()` statt eines zweiten Blocks im Geräte-Block: eine Marke, die an
   zwei Stellen steht, ist eine Marke, die man an einer davon vergisst
   (npm run test:stil:einmalig zählt genau das). */
.vko-var__zustand {
  min-width: clamp(76px, 20vw, 92px); justify-content: center; align-self: center;
  /* Die Einrückung der Fassungskette hängt am Chip, nicht an der Zeile: so
     bleibt die Trennlinie über die volle Breite stehen und die Liste zerfällt
     nicht in Stufen. */
  margin-left: calc(var(--vko-stufe, 0) * 14px);
}
.vko-var.is-gilt { box-shadow: inset 2px 0 0 rgba(var(--accent-rgb), .55); }
.vko-var .vk-zeile__titel {
  display: flex; align-items: baseline; flex-wrap: wrap; gap: 2px 8px;
  min-width: 0; white-space: normal;
}
.vko-var__nr { font-variant-numeric: tabular-nums lining-nums; flex: 0 0 auto; }
.vko-var__sache {
  font-weight: 500; color: var(--text-secondary); min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Das Etikett der Fassung — gesperrte Versalien wie jedes Etikett des Hauses
   (EINHEIT 4.7), auf der Textkante der Zeile darüber. */
.vko-var__fassung {
  display: block; margin-top: 3px;
  font-size: 11px; font-weight: 650; letter-spacing: .1em; text-transform: uppercase;
  color: var(--text-tertiary);
}
/* DIE RECHTE SPALTE — und warum sie EINE Reihe ist.
   Herkunft, Betrag, Weg stehen in dieser Reihenfolge und brechen um, wenn es
   eng wird. Damit die BETRÄGE trotzdem untereinander stehen (die Qualität der
   Referenz, an der man vergleicht statt liest), tragen die beiden RECHTEN
   Zellen eine feste Mindestbreite: was rechts vom Namen steht, ist in jeder
   Zeile gleich breit, also beginnt und endet der Betrag überall an derselben
   Stelle. Am Handy schiebt die bestehende Regel `.vk-zeile__rechts` (weiter
   unten im Geräte-Block) den ganzen Block unter den Leib und nach links —
   dafür braucht es hier keine zweite Regel. */
.vko-var__rechts {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end;
  gap: 4px 10px;
}
.vko-var .vk-zeile__geld { min-width: 92px; text-align: right; }
.vko-var__wer { font-size: 11px; color: var(--text-tertiary); }
.vko-var__weg { min-width: 86px; justify-content: center; }
/* Die Kopfzeile trägt zwei Meta-Angaben; die zweite bekommt einen Trennpunkt,
   damit sie nicht wie eine zweite Überschrift wirkt. */
.vko-var__gilt::before { content: '· '; color: var(--text-tertiary); }

/* --- 7c. Der doppelte Kunde: nennen, auflösen, weiterweisen -------------- */
/* Owner 03.09.2026: «zweimal art Gallus AG drin … das muss doch erkannt
   werden». `.ku-gleiche` (grund.css) NENNT die Namensgleichen — hier kommen
   die zwei Dinge dazu, die das Nennen zur Arbeit machen: der Griff, der sie
   auflöst, und der Weg zum Nachfolger, wenn es schon geschehen ist. */
/* Der Tapflächen-Boden steht in DIESER einen Regel, nicht in einem zweiten
   Geräte-Block: `ghost-btn--xs` ist von Haus aus kleiner als 44px, und 44px
   schaden am Schreibtisch nicht. */
.ku-gleiche__griff { flex: 0 0 auto; min-height: 44px; padding: 6px 12px; }
/* Der Weg zum Nachfolger ist keine WARNUNG — er sagt, wo die Arbeit
   weitergeht. Die Warnfarbe von `.ku-gleiche` (Bernstein = «fehlt/prüfen»)
   wäre dort falsch; die Haarlinie des Hauses ist richtig. */
.ku-gleiche--weiter { border-color: var(--border); }
/* GESPERRTE VERSALIEN SIND EIN ETIKETT, KEIN SATZ (EINHEIT 4.7).
   `.ku-gleiche__satz` ist die Überschrift des Dubletten-Kastens — ein Wort,
   darum in Versalien. Hier steht ein ganzer Satz MIT EINEM NAMEN darin, und
   der Name gehört dem Kunden: «DIESER KUNDE LEBT WEITER IN WACHE MUSTER GMBH»
   schreit und schreibt seine Firma falsch. Am Bild gesehen (Bild 11 des
   Kunden-Archiv-Laufs, 04.09.2026). */
.ku-gleiche__satz--fliess {
  text-transform: none; letter-spacing: normal;
  font-size: 13px; font-weight: 500; color: var(--text-secondary);
}
.ku-gleiche__satz--fliess .ku-gleiche__wer { display: inline; font-weight: 600; }

/* Die Vorschau im Zusammenführen-Kasten (components/app-dialog.js, INHALT-
   Modus). Zahlen untereinander, damit man sie zählt; der Satz darunter sagt,
   was passiert; der Dreh-Griff ganz unten, weil die Richtung die letzte
   Entscheidung ist. */
.ku-zus { display: grid; gap: 10px; margin: 4px 0 12px; }
/* Was wandert, steht in EINEM Satz — dieselbe Form, in der der Kasten
   «Archivieren?» seine Zahlen nennt. Der gehobene Kasten drumherum hebt ihn
   heraus, ohne eine zweite Listenbauart zu erfinden (BEREICHE §10). */
.ku-zus__was {
  margin: 0; padding: 10px 12px;
  border: 1px solid var(--border); border-radius: var(--radius-card);
  background: var(--surface-2);
  font-size: 13px; font-variant-numeric: tabular-nums lining-nums;
}
.ku-zus__was .vk-wert { color: var(--text-primary); font-weight: 600; }
.ku-zus__leer, .ku-zus__laedt, .ku-zus__satz { margin: 0; font-size: 13px; color: var(--text-secondary); }
.ku-zus__fehler { margin: 0; font-size: 13px; color: var(--warn-strong); }
.ku-zus__dreh { justify-self: start; min-height: 44px; padding: 6px 12px; }

/* Angehängter Block unter einer Zeile (Standorte einer Buchung, Material-
   Panel). Eingerückt auf die Textkante der Zeile darüber. */
.vk-unter { display: grid; gap: 4px; padding: 4px 11px 6px 49px; }
.vk-unter__zeile {
  display: flex; flex-wrap: wrap; gap: 3px 10px; min-width: 0;
  font-size: 11.5px; color: var(--text-secondary); font-variant-numeric: tabular-nums;
}
.vk-unter__zeile strong { color: var(--text); font-weight: 600; }
.vk-unter__zeile > *+ *::before { content: '· '; color: var(--text-tertiary); }
.vk-unter__akt { display: block; margin-top: 2px; }

/* Definitionsliste (Stammdaten) — Label links, Wert rechts, feine Linien. */
.vk-daten { display: grid; }
.vk-daten__zeile {
  display: flex; gap: 12px; padding: 8px 0; font-size: 12.5px;
  border-top: 1px solid var(--border);
}
.vk-daten__zeile:first-child { border-top: 0; }
.vk-daten__k {
  width: 150px; flex: 0 0 auto; color: var(--text-tertiary);
  font-size: 11px; font-weight: 650; letter-spacing: .08em; text-transform: uppercase;
  padding-top: 1px;
}
.vk-daten__v { color: var(--text); min-width: 0; overflow-wrap: anywhere; }

/* --- 8. Balken: der Fortschritt trägt seine Aussage in der FARBE --------- */
/* Hier standen bis zum 03.08. dieselben zwei Höfe wie in der Zentrale
   (`0 0 9px` türkis/bernstein). Am Bild widerlegt: Schnitt durch
   docs/design/referenzen/Portaluikomplett/…13_25_27.png bei x=1050 —
   zwei Zeilen unter dem türkisen Balken steht 3,1,9 gegen den Grund 10,20,27.
   DUNKLER, nicht heller. Was bleibt, ist die Aussage: türkis gefüllt, wo es
   läuft (Grundregel style.css:1118), Bernstein im Rückstand (Zeile unten).
   Wächter: _verkauf_ui_test.mjs (Offerten-Balken, Detail-Balken-Held) und
   _stil_integration_test.mjs («Kein farbiger Leucht-Hof»). */
.vk .stat__bar.is-warn > i { background: var(--warn); }

/* --- 9. Leerfall ------------------------------------------------------- */
/* ENTFERNT, nicht ersetzt: .vk-leer · .vk-leer__weg (+ :hover, :focus-visible)
   GEFALLEN 21.08.2026 — die Leer-Zeile des Hauses ist EINE Form:
   `.empty-state.empty-state--zeile` + `.empty-state__weg` in docs/design/grund.css.
   Diese Fassung war die groesste der vierzehn (28 Vorkommen) — ihre Geometrie
   ist die Grundlage der Haus-Form geworden. EINHEIT.md 4.11 gilt unveraendert. */

/* --- 10. Tabs ----------------------------------------------------------- */
/* Die Tab-Reihe der Referenz sitzt auf einer feinen Linie, nicht in einem
   eigenen Kasten (13_25_56 (3)). */
/* Die Huelle kommt seit dem 04.09.2026 vom Haus (`modal__tabs`, grund.css):
   EINE Reihe, Rollweg, verstecktes Rollband, `white-space: nowrap` am Griff,
   farbige Kante am aktiven Reiter. Hier steht nur noch, was die SEITE anders
   braucht als der Dialog:
     padding 0  Die Reiter fluchten mit dem Inhalt. `modal__tabs` setzt
                20 px (und am Telefon 14 px) Seitenpolster fuer den
                Dialograhmen — auf der Seite kaeme das ZUSAETZLICH zum
                Seitenrand der Schale und die Reiter staenden eingerueckt.
     gap 2px    Der Telefon-Block des Hauses setzt `gap: 0`; die Akte
                behaelt ihren Abstand auf jeder Breite.
   `display`, `flex-wrap` und die Grundlinie sind bewusst FORT statt hier
   wiederholt — `flex-wrap: wrap` war die Ursache der drei Reiter-Reihen. */
.vk-tabs {
  padding: 0; gap: 2px; margin-bottom: 14px;
}
.vk-tabs .modal__tab { font-size: 12.5px; }

/* --- 11. Tablet + Handy -------------------------------------------------- */
/* 641 px UNTERGRENZE (04.09.2026): unter 640 px regiert «DIE EINE ZEILE» im
   Block darunter — und die beiden `nth-child`-Trennstriche dieses Blocks
   haetten der rollenden Zeile Kanten mitten hinein gezeichnet. Statt sie unten
   einzeln zurueckzunehmen (und damit jeden Selektor ein zweites Mal zu fuehren)
   bekommt der Block seine Grenze. Zwischen 641 und 1100 px bleibt alles. */
@media (max-width: 1100px) and (min-width: 641px) {
  .vk-kacheln { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  /* ENTFERNT 25.08. (Rueckweg git): `.vk-kachel:nth-child(2n + 1 | n + 3)`.
     Der Rest-Strich kann nicht mehr entstehen — die Kachel ist rundum
     geschlossen und die Fuge trennt in beide Richtungen. `.vk-gruppe__zelle`
     darunter behaelt ihre Regeln: sie ist KEINE Kachel, sondern eine Zelle
     INNERHALB einer Karte. */
  .vk-gruppe { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .vk-gruppe__zelle:nth-child(2n + 1) { border-left: 0; padding-left: 0; }
  .vk-gruppe__zelle:nth-child(n + 3) { border-top: 1px solid var(--border); }
}
@media (max-width: 640px) {
  /* Die Suche behaelt ihre eigene Zeile: `flex: 1 1 260px` liesse sie neben
     der rollenden Reihe auf 260 px schrumpfen, und der Griff, den der Berater
     zuerst braucht, waere der schmalste. */
  .vk-leiste > .vk-suche { flex: 1 1 100%; max-width: none; }
  .vk-kopf h1 { font-size: 22px; }
  /* DIE DREI KOPF-KNOEPFE IN EINER REIHE (04.09.2026). `width: 100%` liess
     sie umbrechen: «Neue Offerte · Bearbeiten» in Zeile eins, «Archivieren»
     in Zeile zwei — 96 px fuer drei Griffe. Sie rollen jetzt wie jede andere
     Nachbar-Reihe am Telefon; keiner faellt weg, keiner wandert in einen
     Reiter. Der Tippboden (44 px) kommt weiter aus dem Touch-Block unten. */
  .vk-kopf .lx-seitenkopf__akt {
    margin-left: 0; width: 100%; gap: 6px;
    flex-wrap: nowrap; overflow-x: auto;
    overscroll-behavior-x: contain; scrollbar-width: none;
  }
  /* …UND SIE PASSEN AUCH WIRKLICH HINEIN. Gemessen 04.09. am Bild 08: mit der
     Haus-Polsterung messen die drei Griffe zusammen rund 410 px, und der
     dritte stand halb angeschnitten am Rand — er waere zwar errollbar
     gewesen, aber ein halbes Wort liest sich als Fehler, nicht als Weg.
     Enger, nicht kleiner: der Tippboden von 44 px bleibt (Touch-Block). */
  .vk-kopf .lx-seitenkopf__akt .primary-btn,
  .vk-kopf .lx-seitenkopf__akt .ghost-btn { padding: 6px 11px; }
  .vk-kopf .lx-seitenkopf__akt::-webkit-scrollbar { width: 0; height: 0; }
  .vk-kopf .lx-seitenkopf__akt > * { flex: 0 0 auto; }
  /* DAS GLEICHE RASTER (05.09.2026) — dieselbe Systemantwort wie beim
     Kennzahlen-Streifen des Hauses (docs/design/grund.css, «DAS GLEICHE
     RASTER»); hier steht sie, weil `.vk-kacheln` ein eigenes Bauteil ist.
     ERSETZT die Rollreihe vom 04.09. (sie stand hier, wo jetzt das Raster
     steht): auf den Offerten stand die dritte Kachel als «CHF 0.0(»
     angeschnitten am Rand (Live-Bild 390 px, 05.09.). Zwei Spalten, gleich
     grosse Kacheln, nichts angeschnitten; eine ungerade letzte nimmt die volle
     Breite statt eine halb leere Reihe zu lassen. Die Feinregeln haengen an
     `.vk-kacheln …`, nicht an `.vk-kachel` allein — eine Kachel ausserhalb
     eines Streifens behaelt ihr Aussehen. */
  .vk-kacheln {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    grid-auto-flow: row;
    gap: 8px; margin-bottom: 8px;
  }
  .vk-kacheln > * { min-width: 0; }
  .vk-kacheln > *:last-child:nth-child(odd) { grid-column: 1 / -1; }
  .vk-kacheln > .vk-kachel { min-height: 44px; padding: 8px 11px; gap: 1px; }
  .vk-kacheln .gz-ic,
  .vk-kacheln .stat__sub:not(.stat__sub--bleibt) { display: none; }
  /* Die Ausnahme des Hauses: eine Unterzeile, die ihre Zahl EINSCHRAENKT,
     schweigt nie (Begruendung und Messung: grund.css bei `.stat-strip`). */
  /* `white-space: normal`: «bis zu CHF 80.00» misst 152 px in einem 88er
     Kasten und lief bis heute stumm ueber die Kante (`.stat__value` traegt
     `nowrap`). Es bricht jetzt an der Luecke — nie mitten in einer Zahl,
     nie mit «…» (Schaden vom 11.08.). */
  .vk-kacheln .stat__value { font-size: 20px; line-height: 1.15; white-space: normal; }
  .vk-kacheln .stat__label { font-size: 11px; letter-spacing: .04em; }
  .vk-raster { grid-template-columns: minmax(0, 1fr); }
  /* Einspaltig gibt es keine Nachbarkarte, an deren Fusszeile sich diese
     ausrichten müsste — die dehnbare Mittelzeile wäre nur Leerraum. */
  .vk-karte { grid-template-rows: auto auto auto; }
  .vk-suche { max-width: none; flex: 1 1 100%; }
  .vk-zaehler { margin-left: 0; }
  /* DAS GLEICHE RASTER, dritte Bauform (04.09.2026, Raster seit 05.09.). Die Kennzahl-GRUPPE der
     Kundenakte stand hier einspaltig: «Umsatz gestellt» und «davon bezahlt»
     als zwei volle Zeilen, darunter «Offen» und «Ueberfaellig» als zwei
     weitere — vier Zeilen fuer vier Zahlen. GEMESSEN am 390er-Bild: die
     Reiter-Leiste der Akte begann bei 892 px, der Berater rollte anderthalb
     Bildschirme durch den Rahmen, bevor er seine Offerten sah. Es ist
     dieselbe Frage wie bei `.vk-kacheln` und `.stat-strip` — also dieselbe
     Antwort, nicht eine dritte. */
  .vk-gruppe {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    grid-auto-flow: row;
    gap: 8px; margin-bottom: 6px;
  }
  .vk-gruppe > * { min-width: 0; }
  .vk-gruppe > *:last-child:nth-child(odd) { grid-column: 1 / -1; }
  /* Die Fuge trennt jetzt in beide Richtungen — die Trennstriche der
     gestapelten Fassung wuerden dem Raster Kanten mitten hinein zeichnen. Sie
     gelten auch aus dem 1100er-Block darueber und werden hier ausdruecklich
     zurueckgenommen (`nth-child`, sonst blieben sie stehen). */
  .vk-gruppe__zelle,
  .vk-gruppe__zelle + .vk-gruppe__zelle {
    min-height: 44px; padding: 8px 11px; gap: 1px;
    background: var(--surface); border: 1px solid var(--border);
    border-radius: var(--radius-card);
  }
  .vk-gruppe .vk-gruppe__label { font-size: 11px; letter-spacing: .04em; }
  /* Umbruch nur an einer Luecke — nie mitten in einer Geldzahl, nie mit «…»
     (Schaden vom 11.08.). Eine Zahl ohne Luecke bekommt statt dessen 120 px. */
  .vk-gruppe .vk-gruppe__wert { font-size: 20px; line-height: 1.15; white-space: normal; }
  .vk-gruppe .vk-gruppe__sub { display: none; }
  /* Der Zeitraum-Schalter wird kompakt, damit er neben das Etikett passt statt
     als eigener Block (52 px) darunter zu stehen. Sein Tippboden von 44 px
     kommt weiter aus dem Touch-Block unten — kleiner wird nur die Polsterung,
     nie die Flaeche. */
  /* …UND ER BRICHT UM STATT ZU ROLLEN — HIER AUSNAHMSWEISE. Der Alt-Kunde
     bietet 2022…2026 und «Alles»; mit `nowrap` lief der Schalter bis 493 px in
     einem 366-px-Kasten (gemessen 04.09.), zwei Zeitraeume standen ausserhalb.
     Ein Rollweg haette sie erreichbar gemacht, aber der Eigentuemer hat am
     23.08. ausdruecklich verlangt, dass JEDER Zeitraum im Bild liegt — auch
     «Alles» (Probe «390px Alt-Kunde» in scripts/_verkauf_ui_test.mjs). Diese
     Zusage wiegt schwerer als die Hoehe, die ein Rollweg spart; sie faellt
     ohnehin nur bei Kunden mit mehreren Jahren an. `min-width: 0` bleibt: ohne
     sie kann ein Flex-Kind nicht unter seine Inhaltsbreite und der Schalter
     sprengte wieder seinen Kasten. */
  /* WER ZUERST NACHGIBT, ENTSCHEIDET ALLES — und es ist das Etikett, nicht der
     Schalter. Gemessen 04.09. an beiden Faellen:
       `0 1 auto`  → bei DREI Zeitraeumen nahm das Etikett dem Schalter 16 px,
                     er brach um: Reiter-Leiste 578 -> 624 px.
       `0 0 auto` + `max-width: 100%`
                   → bei SECHS Zeitraeumen lief er 10 px aus dem Kasten
                     (376 in 366), weil «100%» die ganze Zeile meint und nicht
                     den Platz, der neben dem Etikett uebrig ist.
     Also gibt das Etikett zuerst nach (`flex-shrink: 100`): bei drei behaelt
     der Schalter seine Breite und steht in EINER Zeile, bei sechs schrumpft
     erst das Etikett bis auf null und dann bricht der Schalter INNERHALB
     seines Kastens um — jeder Zeitraum bleibt im Bild. */
  /* DAS ZWEITE ETIKETT SCHWEIGT AM TELEFON. Neben dem Kopfwort «PROFIL» stand
     «· September 2026» — und daneben ein Schalter, dessen erster Knopf MONAT
     heisst. Auf 390 px kostete diese Doppelung alles: der Titel brach auf zwei
     Zeilen, drueckte den Schalter zusammen, und der brach ebenfalls um
     («MONAT QUARTAL» / «JAHR», gesehen im Bild 10 vom 04.09.). Ohne sie steht
     die ganze Kopfzeile in EINER Reihe — und der gewaehlte Zeitraum steht
     weiterhin da, hervorgehoben im Schalter selbst. Am Schreibtisch bleibt
     das Etikett, dort ist Platz.
     NUR dieses eine (`data-slot="kpi-label"`): die Meta-Zeilen anderer Koepfe
     («4 Varianten · Es gilt OFF-2026-0201») sind Auskunft, keine Doppelung. */
  /* «ARCHIVIEREN» ALS SCHMALER TEXTKNOPF (04.09.2026). Die drei Griffe messen
     zusammen rund 406 px und passen damit nicht in 390 — der dritte lief an
     den Rand und stand halb angeschnitten da (Bild 08). Er bleibt im Kopf und
     bleibt vollstaendig lesbar; was faellt, ist sein Rahmen und die Haelfte
     seiner Polsterung. Die Farbe traegt die Bedeutung ohnehin, und der
     Tippboden von 44 px bleibt (Touch-Block unten). In einen Reiter wandert
     er nicht — dort wuerde ihn niemand suchen. */
  .vk-kopf .lx-seitenkopf__akt .ghost-btn--danger { border-color: transparent; background: none; padding: 6px 4px; }
  .vk-panel__kopf [data-slot="kpi-label"] { display: none; }
  .vk-panel__kopf .seg { flex: 0 1 auto; min-width: 0; flex-wrap: wrap; }
  .vk-panel__kopf .seg__btn { padding: 4px 9px; font-size: 11px; letter-spacing: .04em; }
  .vk-daten__zeile { flex-direction: column; gap: 2px; }
  .vk-daten__k { width: auto; }
  /* Am Handy bleiben neben Zeichen und rechter Spalte rund 220px — zu wenig
     für «Coiffure Beispiel 1 AG · Bern». Statt den Namen abzuschneiden,
     bricht die Zeile um: Mobile ist keine Restgrösse. */
  .vk-zeile { grid-template-columns: auto minmax(0, 1fr); row-gap: 4px; align-items: start; }
  .vk-zeile__rechts { grid-column: 1 / -1; justify-content: flex-start; flex-wrap: wrap; white-space: normal; }
  .vk-zeile__sub { white-space: normal; }
  .vk-unter { padding-left: 11px; }
  .vk-karte__akt { justify-content: flex-start; }
}
/* Der Tapflächen-Boden gilt auf JEDEM Touch-Gerät, nicht nur unter 640px
   (Memory project_tablet_touch_breakpoint: 768/1024px sind die Bruchzone). */
@media (max-width: 1024px), (pointer: coarse) {
  .vk-karte, .vk-kachel, .vk-zeile--tuer { min-height: 44px; }
  .vk-filter, .vk-suche { min-height: 44px; }
  /* .vk-leer__weg ist raus: der Touch-Boden steht am Haus-Weg
     (`.empty-state__weg`, grund.css) und gilt damit fuer jede Leer-Zeile. */
  .vk-karte__akt .ghost-btn,
  .vk-karte__akt .primary-btn { min-height: 44px; padding: 6px 14px; }
  .vk-tabs .modal__tab { min-height: 44px; }
}

/* ============================================================
   Patch-Integration — Namensraum handy-; Quelle: docs/design/patch-handy.css
   Der Block wird bei Integration als GANZES ersetzt, nie editiert.
   Handy-Wurzeln (Team Handy, 31.07.): Tastatur-wahre Höhen via
   VisualViewport-Variablen, alle Popover am Bildrand geklemmt, Modale
   scrollen innen. Klemmt bestehende Klassen, baut nichts um.
   ============================================================ */
/* =========================================================================
   Handy-Klemmung — nichts ragt aus dem Bildschirm, nichts liegt unter der
   Tastatur.
   Quelle: docs/design/patch-handy.css
   Markup unveraendert: hier wird KEINE neue Flaeche erfunden, es werden
   bestehende Klassen geklemmt.

   Der Anlass (Owner am iPhone, 31.07.):
     1. Die Befehls-Palette (Cmd-K) war mit offener Tastatur unbedienbar: das
        Suchfeld hing halb ueber dem oberen Bildrand, die Liste begann mitten
        in einem Eintrag, und man kam nicht ans Ende.
     2. Das Fenster «Was ansteht» ragte rechts aus dem Bildschirm, verdeckte
        den Termin-Knopf und schnitt seinen eigenen Text ab
        («Nichts offen. K…»).

   Die zwei Wurzeln — beide gelten fuer mehr als die zwei gemeldeten Stellen:

   WURZEL A · Hoehenmasse, die die Tastatur nicht kennen.
     `vh` ist auf iOS das GROSSE Fenster (Browserleiste weggedacht), `dvh` das
     dynamische — aber auch `dvh` rechnet die Tastatur NICHT ab. Wer seine
     Hoehe aus `vh` nimmt, ist mit offener Tastatur regelmaessig doppelt so
     hoch wie der sichtbare Rest. Deshalb:
       · jedes Hoehenmass eines Scroll-Behaelters oder einer Ueberlagerung
         wird von `vh` auf `dvh` gezogen (am Rechner identisch, am Handy
         kleiner — es kann also nichts schrumpfen, was vorher passte),
       · und die Palette, die als EINZIGE gleichzeitig mit der Tastatur offen
         ist, haengt zusaetzlich am `visualViewport` (die Variablen setzt
         public/src/components/command-palette.js).
     Merksatz aus dem Projektgedaechtnis (project_mobile_ios_dvh): Chromium ist
     fuer die iOS-Leisten blind — der Beweis laeuft in beiden Maschinen.

   WURZEL B · Angehaengte Blaetter ohne Anschlag am Bildrand.
     Ein `position: fixed`-Blatt, dessen `left` vom Anker kommt, laeuft rechts
     hinaus, sobald der Anker rechts sitzt. Die Rechnung gehoert ins Modul
     (notifications.js klemmt jetzt selbst, calendar-people-popover.js und
     partner-list.js taten es bereits) — hier steht der zweite Riegel: auf
     Fingergeraeten spannen die Blaetter von Rand zu Rand, egal was ein Modul
     rechnet. Damit ist die Fehlerklasse auch dann zu, wenn spaeter jemand ein
     neues Blatt ohne Rechnung anhaengt.

   Tapflaechen: der Boden greift ueber `(max-width: 1024px), (pointer: coarse)`
   — die 720px-Grenze allein laesst die Tablet-Bruchzone offen
   (project_tablet_touch_breakpoint).

   Beweis: scripts/_handy_ui_test.mjs (chromium + webkit, 390x844 und 390x390
   sowie mit gefaelschter Tastatur bei stehendem Layout-Fenster).
   ========================================================================= */

/* -------------------------------------------------------------------------
   1. Befehls-Palette (Cmd-K) — Suchfeld oben fest, Liste scrollt darunter
   -------------------------------------------------------------------------
   Vorher: `.cp { position: fixed; inset: 0 }` spannte ueber das LAYOUT-Fenster
   (auf iOS bleibt das 844px hoch, auch wenn nur 390px sichtbar sind), das
   Blatt bekam seinen Abstand von oben und die Liste ihren Deckel aus `vh`.
   Ergebnis: Suchfeld ueber dem Bildrand, Listenende unter der Tastatur.

   Jetzt: die Palette IST das sichtbare Fenster. Die vier Variablen kommen aus
   command-palette.js; ohne JavaScript (oder ohne visualViewport) greifen die
   Rueckfallwerte und alles bleibt wie bisher. */
.cp {
  top: var(--cp-top, 0px);
  left: var(--cp-left, 0px);
  right: auto;
  bottom: auto;
  /* `100%` statt `100vw` als Rueckfall: `100vw` zaehlt die Scrollleiste mit und
     schob die Seite dadurch seitwaerts (09.08., c2 B12/c6 B29). Bei einem
     `position: fixed`-Element ist `100%` genau die Fensterbreite ohne sie. */
  width: var(--cp-w, 100%);
  height: var(--cp-h, 100dvh);
  display: flex;
  flex-direction: column;
  align-items: center;
}

/* Das Blatt ist eine Saeule: Kopf fest, Liste dehnbar. `min-height: 0` ist
   Pflicht — ohne sie weigert sich ein Flex-Kind zu schrumpfen und die Liste
   waechst wieder aus dem Blatt heraus. */
.cp__panel {
  display: flex;
  flex-direction: column;
  min-height: 0;
  max-height: calc(100% - var(--cp-luft, 16px));
  margin: min(14dvh, 120px) 0 0;
  /* Breite jetzt am sichtbaren Fenster, nicht am Layout-Fenster (`100vw`). */
  width: min(600px, calc(100% - 28px));
}

.cp__inputrow {
  flex: 0 0 auto;
  min-height: 48px;
}

/* Die Liste wird zum dehnbaren Teil der Saeule. Ihr Deckel bleibt der alte —
   er begrenzt nur noch das WACHSEN; das SCHRUMPFEN uebernimmt jetzt das Blatt,
   das nie hoeher wird als das sichtbare Fenster. Damit bleibt die Palette am
   Rechner Pixel fuer Pixel dieselbe und passt am Handy trotzdem hinein.
   `overscroll-behavior` haelt das Wischen in der Liste, statt die Seite
   dahinter mitzuziehen. */
.cp__list {
  flex: 1 1 auto;
  min-height: 0;
  max-height: min(52dvh, 420px);
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
}

@media (max-width: 720px) {
  .cp__panel {
    /* Luft oben unter der Statusleiste, unten fuer den Home-Streifen. */
    margin-top: max(12px, var(--sat));
    --cp-luft: calc(24px + var(--sat) + var(--sab));
  }
  .cp__list { max-height: min(62dvh, 480px); }
}

/* -------------------------------------------------------------------------
   2. «Was ansteht» — das Blatt bleibt im Bild
   -------------------------------------------------------------------------
   Auf Fingergeraeten von Rand zu Rand: `left`/`right` aus dem Modul werden
   ueberstimmt, damit kein gerechneter Wert das Blatt je wieder hinausschiebt.
   Der Deckel kommt aus `dvh` und zusaetzlich aus einem harten Anschlag gegen
   die Fensterhoehe. */
.lx-bell-panel {
  max-height: min(60dvh, 520px);
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
}

@media (max-width: 720px), (pointer: coarse) {
  .lx-bell-panel {
    left: 12px !important;
    right: 12px !important;
    width: auto;
    max-width: none;
    max-height: min(60dvh, 520px, calc(100dvh - 24px));
  }
  /* Der Titel wird nicht abgeschnitten, der Text bricht um statt zu enden. */
  .lx-bell-row__title,
  .lx-bell-row__meta,
  .lx-bell-panel__leer { overflow-wrap: anywhere; }
}

/* -------------------------------------------------------------------------
   3. Die uebrigen angehaengten Blaetter — gleiche Klasse, gleicher Riegel
   ------------------------------------------------------------------------- */
/* Zeilenmenue der Standortbetreiber-Liste: es wird inline gelegt und geklemmt
   (partner-list.js:585-587), hatte aber keinen Deckel — bei vielen Eintraegen
   waechst es aus dem Bild. */
.pl-menu {
  max-height: calc(100dvh - 24px);
  overflow-y: auto;
  overscroll-behavior: contain;
}

/* Das «+ Neu»-Menue oeffnet nach oben. Bei kurzem Fenster (Querlage, offene
   Tastatur) lag der oberste Eintrag ueber dem Bildrand. */
.qc__menu {
  max-width: calc(100vw - 36px);
  max-height: calc(100dvh - 110px - var(--sab));
  overflow-y: auto;
  overscroll-behavior: contain;
}


/* -------------------------------------------------------------------------
   4. Wurzel A flaechendeckend: Hoehenmasse, die die Leisten kennen
   -------------------------------------------------------------------------
   Jede Stelle unten stand in reinem `vh` und deckelt einen Scroll-Behaelter
   oder ein Blatt, das am unteren Rand klebt. Am Rechner aendert sich nichts
   (dort ist `dvh == vh`); am Handy passt es nun in das, was wirklich sichtbar
   ist.

   Jede Regel steht in GENAU dem Fenster-Bereich ihres Originals. Grund: das
   Patch-Blatt haengt am Ende der Datei und wuerde sonst spaetere Ruecknahmen
   ueberstimmen — `.kp-liste` etwa wird unter 720px bewusst wieder deckellos
   (docs/design/grund.css), und `.mini-modal` wird dort zum randlosen Vollbild
   (docs/design/grund.css). Ein flaches `.kp-liste { max-height: … }` haette
   beides still zurueckgedreht. */

/* Ohne Bedingung im Original — hier ebenso. */
.lp-results { max-height: 50dvh; }                    /* docs/design/grund.css */
.pl-vorschau { max-height: 46dvh; }                   /* docs/design/patch-partnerliste.css */
.ao-verlauf { max-height: calc(100dvh - 360px); }     /* docs/design/patch-chat.css §A */

@media (min-width: 721px) {
  .mini-modal { max-height: 90dvh; }                  /* docs/design/grund.css */
  .kp-liste { max-height: min(56dvh, 520px); }        /* docs/design/grund.css */
}

@media (max-width: 720px) {
  .kanban__col { max-height: 70dvh; }                 /* docs/design/grund.css  */
}

/* Blaetter, die am unteren Rand kleben. Deckel und der Platzhalter darunter
   muessen dasselbe Mass tragen, sonst laeuft die Liste hinter das Blatt. */
@media (max-width: 900px) {
  .pl-panel { max-height: 62dvh; }                    /* docs/design/patch-partnerliste.css */
  .pl-arbeit[data-auswahl="1"] .pl-liste { padding-bottom: 62dvh; }  /* docs/design/patch-partnerliste.css */
  .pl-panel__liste { max-height: 22dvh; }             /* docs/design/patch-partnerliste.css */
  /* .vt2-panel ging mit W5-E4b (Detail-Panel wurde das Dossier). */
}

@media (max-width: 1000px) {
  .ao-verlauf { max-height: 52dvh; }                  /* docs/design/patch-chat.css §A + §B */
}

@media (max-width: 640px) {
  .ao-verlauf { max-height: 46dvh; }                  /* docs/design/patch-chat.css §A */
}

@media (max-width: 1100px) {
  .so-editor.is-wizard .so2-rail { max-height: 82dvh; }  /* docs/design/grund.css */
}

/* -------------------------------------------------------------------------
   5. Tapflaechen an den geflickten Stellen (Boden 44px)
   -------------------------------------------------------------------------
   Die 720px-Grenze allein laesst Tablets und grosse Handys quer offen —
   deshalb zusaetzlich ueber den Zeigertyp (project_tablet_touch_breakpoint). */
@media (max-width: 1024px), (pointer: coarse) {
  .cp__item { min-height: 44px; }
  .cp__input { min-height: 46px; }
  .lx-bell-row { min-height: 44px; }
  .lx-bell-panel__all { min-height: 44px; padding-left: 10px; padding-right: 10px; }
  .qc__item { min-height: 44px; }
  .pl-menu button { min-height: 44px; }
}

/* -------------------------------------------------------------------------
   Was hier BEWUSST nicht steht
   -------------------------------------------------------------------------
   · `.pl-panel`, `.ao-kontext` mit `calc(100vh - 32px)`
     (docs/design/patch-partnerliste.css, docs/design/patch-chat.css §A): das sind klebende Seitenspalten, die
     unter 900px bzw. 1000px ohnehin zum unteren Blatt bzw. deckellos werden.
     Auf dem Handy brechen sie nicht — die Umstellung waere reine Bewegung.
   · `min-height`-Masse in `vh` (`.loading` docs/design/grund.css, `.ao-chat`
     docs/design/patch-chat.css §A) und `padding: clamp(20px, 6vh, 56px)`: sie schneiden nichts ab,
     sie geben nur Luft.
   · Alle Stellen, die bereits ein `vh`/`dvh`-Paar tragen, sind unveraendert
     richtig. Hier standen einmal zehn Zeilennummern von public/style.css —
     ab dem naechsten Bau zeigte jede daneben. Wer sie sucht:
     `grep -n 'dvh' docs/design/*.css`. */

/* ============================================================
   Patch-Integration — Namensraum anruf-; Quelle: docs/design/patch-anruf.css
   Der Block wird bei Integration als GANZES ersetzt, nie editiert.
   Anruf-Baum (Team Anruf, 31.07.): Abstand der Katalog-Fragen.
   ============================================================ */
/* ============================================================
   Anruf-Erfassung — Quelle: docs/design/patch-anruf.css
   Zentral anhängen an public/style.css (diese Datei nie direkt ausliefern).
   Beweis: scripts/_anruf_fluss_test.mjs (Bühne hängt genau diesen Patch an).
   ============================================================

   WARUM ES DIESEN PATCH GIBT
   Der Anruf-Dialog rendert seit dem 31.07. den verzweigenden Katalog-Baum
   (Owner-Befund «alles hart codiert»). Die Fragen liegen dabei in EINEM
   Behälter `[data-slot="tree"]`. `.mini-modal__body` verteilt seine 14px
   Abstand nur zwischen seinen direkten Kindern — also zwischen Baum,
   Datums-Reihe und Notiz, NICHT zwischen den Fragen im Baum. Ohne diese
   sechs Zeilen kleben «Erreicht?» und «Was war?» aneinander.

   Alles andere, was der neue Ablauf braucht, steht bereits im Haus und wird
   bewusst NICHT dupliziert: .assessment-q/.tap-group/.tap-btn (1649-1684,
   das Tap-Vokabular samt 44px-Touch), .so2-chips/.so2-chip (3388-3400,
   Touch-Boden 3796), .call-when (2562-2563), .mini-modal (1610-1644).

   AUFRÄUMEN, wenn dieser Patch zentral eingehängt wird — zwei Regelblöcke in
   public/style.css haben mit dem alten Ablauf ihren letzten Nutzer verloren
   (nachgezählt: kein Treffer mehr in public/src und public/*.html):
     · .call-next                          (2561)
     · .seg--stack, .seg--stack .seg__btn,
       .seg--stack .seg__btn[hidden]       (2558-2560)
       und deren Touch-Zeile               (2564)
   Sie sind hier NICHT still entfernt, sondern benannt: sie gehören zur
   gestapelten Folge-Knopf-Reihe, die der Katalog-Baum ersetzt hat.
   Wer sie zieht, prüft vorher scripts/d04-call-flow-test.mjs — dort stand
   bis zum 31.07. die Zusicherung auf `.seg--stack`.
   ============================================================ */

/* Der Baum atmet: gleiche Rhythmik wie .mini-modal__body zwischen seinen
   Kindern. `[hidden]` bleibt wirkungslos ausgeblendet (style.css:142). */
[data-slot="tree"] {
  display: grid;
  gap: 14px;
  align-content: start;
}

/* Die Datums-Reihe folgt dem Baum, nicht dem Rand: sie gehört sichtbar zur
   zuletzt getippten Antwort, nicht zur Notiz darunter. */
.call-when > .so2-chipgroup__label {
  display: block;
}

/* ============================================================
   Patch-Integration — Namensraum of-; Quelle: docs/design/patch-offerte.css
   Der Block wird bei Integration als GANZES ersetzt, nie editiert.
   Offerten-Weg (Team Offerte, 31.07.): geführter Fluss, Daumen-Leiste,
   44px-Schrittpunkte.
   ============================================================ */
/* =========================================================================
   Der Offerten-Weg — «Für wen? · Wo? · Wie lange? · Fertig»
   Namensraum sof- (Sales-OFferte). Quelle dieses Umbaus: Owner-Wortlaut
   31.07. — «das komplizierte verfickte Offerten-Flow, rechnen, Kunde anlegen
   und und — das ist das Mühsamste der Welt.»

   WAS GEMESSEN WAR (docs/audit/OFFERTEN-WEG-VERMESSUNG.md, 390px):
     · Schritt 1 stellte fünf Fragen gleichzeitig, davon vier mit Tastatur —
       und die ERSTE war «Titel», also die einzige, die niemand beantworten
       kann, bevor er weiss, was drin ist.
     · Der Kunde hing in einem <select> über alle Kunden; auf 390px war die
       Beschriftung abgeschnitten («— noch kein Kund»).
     · «+ Kunde anlegen» klappte NEUN weitere Felder auf.
     · Die Kunden-Neuanlage für sich zeigte elf leere Kästen, von denen genau
       einer Pflicht war; der Anlege-Knopf schwamm über den letzten dreien.
     · Der Schluss waren zwei Knöpfe für einen Gedanken: erst «Speichern
       (zieht Nummer)», danach wurde «Als gesendet markieren» überhaupt erst
       bedienbar — mit einem Neu-Mount der ganzen Fläche dazwischen.
     · Die Schrittpunkte 1–4 massen 26px — unter der 44px-Tapfläche.

   DIE LINIE (EINHEIT.md 1.3/1.4/1.6, DESIGN.md):
     1. Eine Frage je Schritt, gross und ruhig. Was die Software weiss, steht
        als Vorschlag da und trägt einen «Ändern»-Knopf — nie ein leeres Feld.
     2. Wählen heisst antippen. Zeilen mit Zeichen im Soft-Quadrat, dieselbe
        Bauart wie die Standort-Suche daneben (.so2-indivadd) — EIN Muster
        für «etwas aus einer Liste nehmen», nicht zwei.
     3. Was später nachtragbar ist, liegt unter einem Deckel und hält den
        Fluss nicht auf.
     4. Der Schluss ist EIN Blick: Kunde · was drin ist · Preis · ein Knopf.
     5. Türkis bleibt der EINE Akzent. Keine zweite Farbe, kein Rahmen ohne
        Aufgabe, kein Erklärtext unter dem Titel.

   Bausteine aus style.css werden benutzt, nicht ersetzt: .panel, .field,
   .so-fields, .so-hint, .so2-indivadd/__plus, .so2-indivresults,
   .so2-ortsearch, .ghost-btn, .primary-btn, .modal-actions, .sl-badge.
   Der Orchestrator hängt diese Datei an style.css an; sie steht darum NACH
   allen Basisregeln und darf mit gleicher Spezifität stechen
   (Memory project_css_cascade_mobile — eigener Block NACH der Basis).
   ========================================================================= */

/* --- 1. Schritt 1: die Kundenfrage --------------------------------------- */

/* Die Wahl-Liste ist die Antwort auf «für wen» — sie steht sofort da, ohne
   dass jemand ein Feld anfassen muss. Suchfeld nur, wenn die Liste lang wird
   (der Editor rendert es erst ab 7 Kunden). */
.sof-kundenwahl { margin: 0 0 14px; }
.sof-kundenwahl .so2-indivresults { margin-top: 8px; }

/* Tap-Zeile: dieselbe Anatomie wie die Standort-Suche, nur höher — 48px hält
   die 44px-Tapfläche mit Luft (Memory feedback_mobile_pwa_mandatory). */
.sof-kundenzeile,
.sof-neuerkunde {
  min-height: 48px;
  padding: 9px 10px;
  border-radius: var(--radius-card);
}
.sof-kundenzeile + .sof-kundenzeile { margin-top: 2px; }
.sof-kundenzeile .so2-indivadd__plus,
.sof-gewaehlt .so2-indivadd__plus,
.sof-abschluss .so2-indivadd__plus {
  width: 26px; height: 26px;
  border-radius: var(--radius-card);
  font-size: 12px;
}

/* «Neuer Kunde» ist eine Tür, keine Zeile: getönte Kante, damit sie sich vom
   Bestand abhebt, ohne ein zweiter Hauptknopf zu werden (EINHEIT.md 1.4 —
   drei Knopfstufen, mehr nicht). */
.sof-neuerkunde {
  margin-top: 6px;
  border: 1px dashed rgba(var(--accent-rgb), .30);
  background: rgba(var(--accent-rgb), .04);
}
.sof-neuerkunde:hover { background: rgba(var(--accent-rgb), .09); }
.sof-neuerkunde .so2-indivadd__plus {
  background: rgba(var(--accent-rgb), .18);
  color: var(--accent-strong);
}

/* Der gewählte Kunde: eine Zeile, die die Frage beantwortet zeigt. */
.sof-gewaehlt {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  min-height: 52px;
  border: 1px solid rgba(var(--accent-rgb), .16);
  border-radius: var(--radius-card);
  background: var(--surface);
}
.sof-gewaehlt__wer { display: flex; flex-direction: column; min-width: 0; flex: 1; }
.sof-gewaehlt__wer strong {
  font-size: 15px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.sof-gewaehlt__wer .so-hint { font-size: 12px; margin: 0; }
/* Archivierter Kunde an einer bestehenden Offerte (04.08.): der Name bleibt,
   der Zustand steht daneben — nicht als Warnung, die Offerte gilt weiter. */
.sof-gewaehlt__archiv { font-weight: 500; color: var(--text-tertiary); }
.sof-gewaehlt .sof-wechseln { flex-shrink: 0; min-height: 44px; }

/* Die Neuanlage im Fluss: zwei Felder, kein Titel darüber — der Schrittkopf
   sagt schon, worum es geht (EINHEIT.md 1.6). */
.sof-neuform { margin: 0; }
.sof-neuform .modal-actions { margin-top: 10px; }

/* --- 2. Der vorgeschlagene Titel — ENTFERNT am 21.08.2026 --------------- */
/* Fuenf Regeln (.sof-titel, __label, __wort, .sof-titel .ghost-btn, __feld)
   sind gefallen, weil sie nichts mehr treffen: `sof-titel` steht an keiner
   Stelle in public/src/ — weder als Wort noch als Baustein einer Vorlage
   (gemessen: 0 Vorkommen in allen .js unter public/src/). Aufgefallen ist es
   beim Schrift-Boden-Gang: `.sof-titel__label` stand mit 10.5px unter dem
   Boden aus DESIGN.md §2 — und eine Regel, die keine Flaeche traegt, wird
   nicht gehoben, sie faellt (Hausregel «Ersetzen statt daneben»).
   Rueckweg: git show HEAD:docs/design/patch-offerte.css.
   ACHTUNG, groesserer Befund daneben: von den 36 Klassen dieses Blattes
   treffen 28 nichts mehr (der ganze `sof-`/`so2-`/`so-wiz`-Raum). Die
   restlichen 24 toten Regeln gehoeren nicht in den Schrift-Boden-Gang und
   stehen deshalb noch — als benannter Befund, nicht als Versehen. */

/* --- 3. Deckel «Feinheiten» / «Eigener Preis» --------------------------- */
/* Was vorgeschlagen ist und selten angefasst wird, hält den Fluss nicht auf.
   Ein Deckel, keine Fläche: zu = eine Zeile, offen = die Felder darunter. */
.sof-feinheiten,
.sof-freiheit {
  margin-top: 14px;
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  background: var(--surface);
  overflow: hidden;
}
.sof-feinheiten > summary,
.sof-freiheit > summary {
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 46px;
  padding: 0 14px;
  cursor: pointer;
  font-size: 13px;
  font-weight: 550;
  color: var(--text-secondary);
  list-style: none;
}
.sof-feinheiten > summary::-webkit-details-marker,
.sof-freiheit > summary::-webkit-details-marker { display: none; }
.sof-feinheiten > summary::after,
.sof-freiheit > summary::after {
  content: '';
  margin-left: auto;
  width: 8px; height: 8px;
  border-right: 1.6px solid currentColor;
  border-bottom: 1.6px solid currentColor;
  transform: rotate(45deg) translate(-2px, -2px);
  transition: transform var(--transition);
}
.sof-feinheiten[open] > summary::after,
.sof-freiheit[open] > summary::after { transform: rotate(-135deg) translate(-2px, -2px); }
.sof-feinheiten > summary:hover,
.sof-freiheit > summary:hover { color: var(--text-primary); background: rgba(var(--tint-rgb), .05); }
.sof-feinheiten > .so-fields,
.sof-freiheit > .so-fields,
.sof-freiheit > .so-hint { padding: 0 14px 14px; margin: 0; }
.sof-freiheit > .so-hint { padding-top: 0; padding-bottom: 8px; }

/* --- 4. Schritt 4: EIN Blick ------------------------------------------- */
/* Kunde · was drin ist · Preis · ein Knopf. Auf 390px untereinander, ab
   900px als eine Zeile mit dem Preis rechts vor dem Knopf. */
.sof-abschluss {
  display: grid;
  gap: 12px;
  padding: 14px;
  margin-bottom: 14px;
  border: 1px solid rgba(var(--accent-rgb), .16);
  border-radius: var(--radius-card);
  background: var(--surface);
}
.sof-abschluss__wer { display: flex; align-items: center; gap: 10px; min-width: 0; }
.sof-abschluss__wortlaut { display: flex; flex-direction: column; min-width: 0; }
.sof-abschluss__wortlaut strong {
  font-size: 15px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.sof-abschluss__wortlaut .so-hint { font-size: 12px; margin: 0; }
.sof-abschluss__was .so-hint { margin: 0; font-size: 12.5px; }
.sof-abschluss__was b { color: var(--text-primary); font-variant-numeric: tabular-nums; }
.sof-abschluss__preis { display: flex; flex-direction: column; gap: 2px; }
.sof-abschluss__preis > strong {
  font-size: 26px;
  font-weight: 650;
  letter-spacing: -.02em;
  font-variant-numeric: tabular-nums;
  line-height: 1.1;
}
.sof-abschluss__preis .so-hint { margin: 0; font-size: 11.5px; }
.sof-abschluss__preis .so-hint b { color: var(--text-secondary); font-variant-numeric: tabular-nums; }
.sof-abschluss__knopf { min-height: 48px; width: 100%; }
.sof-abschluss .so-hint--warn { margin: 0; }

@media (min-width: 900px) {
  .sof-abschluss {
    grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr) auto auto;
    align-items: center;
  }
  .sof-abschluss__preis { align-items: flex-end; text-align: right; }
  .sof-abschluss__knopf { width: auto; padding-inline: 22px; }
  .sof-abschluss .so-hint--warn { grid-column: 1 / -1; }
}

/* Der Abschluss in der mitlaufenden Rail (Desktop): abgesetzt, damit er nicht
   wie eine weitere Kennzahl aussieht, sondern wie das Ende. */
.sof-rail__ende {
  margin-top: 14px;
  padding-top: 14px;
  border-top: 1px solid var(--border);
  display: grid;
  gap: 6px;
}
.sof-rail__ende .primary-btn { width: 100%; min-height: 46px; }
.sof-rail__ende .so-hint--warn { margin: 0; font-size: 12px; }

/* --- 5. Die Leiste am Handy: der Schluss steht dort, wo der Daumen ist --- */
.sof-mobilbar__akt { display: flex; align-items: center; gap: 8px; flex-shrink: 0; }
.sof-mobilbar__akt .sof-sichern { padding-inline: 12px; }
.sof-mobilbar__akt .primary-btn,
.sof-mobilbar__akt .ghost-btn { min-height: 44px; }

/* --- 6. Reparatur am Schritt-Anzeiger ---------------------------------- */
/* Gemessen 26px — unter der Tapfläche. Die Punkte sind der Weg zurück in
   einen früheren Schritt; wer sie nicht trifft, wischt blind. Ein grösseres
   Trefferfeld über ein Pseudo-Element wäre gemogelt: der Prüfstand misst die
   Kachel selbst, und ein Mensch sieht sie auch. Also wird die Kachel gross —
   44px, Radius mit — und das Raster bekommt die Luft dafür. */
@media (max-width: 1100px) {
  .so-wiz__dot {
    width: 44px; height: 44px;
    border-radius: var(--radius-card);
    font-size: 14px;
  }
  .so-wiz__dots { gap: 8px; }
  /* Die Pfeile daneben tragen dieselbe Pflicht. */
  .so-wiz__arrow { min-width: 44px; min-height: 44px; }
}

/* --- 7. Kunden-Anlage: der Deckel «Mehr Angaben» ------------------------ */
/* Namensraum ku- (Kunde) — dieselbe Bauart wie die Deckel oben, aber im
   Modal, wo .sl-edit-grid das Raster stellt. */
.ku-mehr {
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  background: var(--surface-inset);
  overflow: hidden;
}
.ku-mehr > summary {
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 46px;
  padding: 0 14px;
  cursor: pointer;
  font-size: 13px;
  font-weight: 550;
  color: var(--text-secondary);
  list-style: none;
}
.ku-mehr > summary::-webkit-details-marker { display: none; }
.ku-mehr > summary::after {
  content: '';
  margin-left: auto;
  width: 8px; height: 8px;
  border-right: 1.6px solid currentColor;
  border-bottom: 1.6px solid currentColor;
  transform: rotate(45deg) translate(-2px, -2px);
  transition: transform var(--transition);
}
.ku-mehr[open] > summary::after { transform: rotate(-135deg) translate(-2px, -2px); }
.ku-mehr > summary:hover { color: var(--text-primary); }
.ku-mehr__felder { padding: 0 14px 14px; }
/* ============================================================
   Patch-Integration — Namensraum pool-; Quelle: docs/design/patch-pool.css
   Der Pool am Handy (Karte 01.08., Position 10). Steht am Ende der
   Datei und damit NACH allen Basisregeln — die Handy-Regeln muessen
   die Basis stechen duerfen (Memory project_css_cascade_mobile).
   ============================================================ */
/* =========================================================================
   Der Pool am Handy — Karte 01.08., Position 10
   Die meistgebrauchte Arbeitsflaeche der Berater (#/m/pool).

   GEMESSEN (Karte, Abschnitt 1): 9,6 Handy-Bildschirme. Der Pool blaettert
   laengst (25 je Seite, pool_free_firms mit limit/offset seit Iter 42) — die
   Hoehe kommt nicht aus der Menge, sondern aus der HOEHE JEDER KARTE: je
   Firma ein ganzer Absatz Fliesstext (Branche, Adresse, Ansprechpartner,
   Mitarbeiterzahl, Quelle, Schmerzpunkte bis 140 Zeichen) plus vier
   Filterfelder untereinander VOR dem ersten Treffer.

   DIE LINIE: am Handy traegt die Karte Name, Prioritaet, Ort und EINEN Knopf
   (die Telefonnummer). Alles Weitere steht auf Tipp im Fenster — die Karte
   oeffnet es seit jeher. Die Filter liegen hinter EINEM Knopf, der die Zahl
   der gesetzten Filter traegt; die Suche bleibt stehen, weil sie der
   schnellste Weg zu einer bestimmten Firma ist.

   Nichts wird geloescht, nichts wandert in ein Menue: alle vier Modi (samt
   «Verloren (holbar)»), alle Filter, die Reaktivierung und die
   Auto-Verteilung bleiben erreichbar. Die Regeln stehen ausschliesslich in
   @media-Bloecken — am grossen Bildschirm aendert sich kein Pixel.

   Tapflaechen: der Boden greift ueber `(max-width: 1024px), (pointer: coarse)`
   — die 720px-Grenze allein laesst die Tablet-Bruchzone offen
   (project_tablet_touch_breakpoint).

   Beweis: scripts/_blockb_flaechen_test.mjs (390x844, gemessene Hoehe als
   eigener Pruefpunkt — eine Gestalt, die wieder waechst, wird rot).
   ========================================================================= */

/* -------------------------------------------------------------------------
   1. Pool — die Filterleiste
   -------------------------------------------------------------------------
   Am grossen Bildschirm fliessen die drei Auswahlfelder wie bisher in einer
   Reihe: `display: contents` löst die Hülle auf, der Knopf ist weg. */
.pool-filter__knopf { display: none; }
.pool-filter__mehr { display: contents; }

/* -------------------------------------------------------------------------
   2. Pool — die kurze Karte am Handy
   ------------------------------------------------------------------------- */
@media (max-width: 720px) {
  /* Die Suche führt, der Griff steht daneben. Er trägt die Zahl der gesetzten
     Filter — sonst wäre eine geschnittene Liste nicht als solche zu erkennen.
     Bis 08.08. klappte er die Felder HIER auf (`.is-offen`); seither öffnen
     sie sich als Blatt, siehe Abschnitt «Fläche 3» weiter unten. */
  .pool-leiste .filters-group { display: grid; grid-template-columns: 1fr auto; gap: 8px; }
  /* `min-width: 0`: ein Rasterkind darf nicht breiter bleiben als seine Spalte —
     das breite Suchfeld schob sich sonst 26 px unter den Filter-Knopf, sobald
     dessen Wort in Versalien breiter wurde (Breitenprobe 03.09., pool@390). */
  .pool-leiste .field--search { grid-column: 1; min-width: 0; }
  .pool-filter__knopf {
    display: inline-flex; align-items: center; justify-content: center;
    grid-column: 2; align-self: end; min-height: 44px; white-space: nowrap;
  }
  .pool-filter__knopf.is-gesetzt { border-color: var(--accent); color: var(--accent-strong); }
  .pool-filter__mehr { display: none; grid-column: 1 / -1; }
  .pool-filter__mehr .field { min-width: 0; }

  /* Die kurze Karte: Name, Prioritäts- und Ortsmarke, die Nummer als EINZIGER
     Knopf. Was hier verschwindet, steht vollständig im Fenster, das ein Tipp
     auf die Karte öffnet — die Karte ist seit jeher anklickbar. */
  .pool-liste .firm-card__meta,
  .pool-liste .firm-card__schmerz,
  .pool-liste .firm-card__notes { display: none; }
  /* Mit der Adresse fällt der Ort weg — und genau er beantwortet die erste
     Frage der Fläche («wer ist das?») mit. Er kommt deshalb hier zurück, als
     Teil des Namens statt als eigene Zeile (08.08.). */
  .pool-liste .firm-card__ort { display: inline; }
  /* Die Website ist kein Arbeitsweg am Telefon — die Nummer ist es. */
  .pool-liste .firm-card__contact .firm-link[target="_blank"] { display: none; }
  /* Die Fusszeile «Details ∨» ist am Handy eine zweite Anzeige derselben
     Handlung: die ganze Karte öffnet das Fenster (Klick-Handler, tabindex,
     aria-label mit dem Firmennamen). Zwei Anzeigen für eine Handlung kosten
     hier 30px je Karte — mal 25 Karten eine dreiviertel Bildschirmhöhe.
     Am grossen Bildschirm bleibt sie. */
  .pool-liste .firm-card__bottom { display: none; }
  .pool-liste .firm-card { gap: 6px; padding: 12px 14px; }
  /* ⚠️ DAS AUSWAHL-KÄSTCHEN LAG AUF DEM FIRMENNAMEN.
     Gemessen und am Bild gesehen 08.08. auf 390×620: «Coiffure Bellevue» stand
     als «iffure Bellevue» da, «Hairwerk Winterthur…» als «irwerk Winterthur…».
     Auf einer Fläche, deren erste Frage «wer?» lautet, ist ein unlesbarer
     Firmenname der teuerste Fehler — und es ist genau der Moment, den der
     Owner mit «wie will mein Mitarbeiter sich trauen» gemeint hat.

     URSACHE, eine Kaskaden-Falle: `.firm-card__check` liegt `position:absolute`
     in der Kartenecke (docs/design/grund.css), und `.firm-card--lead.firm-card--selectable`
     reserviert dafür `padding-left: 48px` (style.css:3898). Die Zeile direkt
     darüber setzt aber die KURZFORM `padding: 12px 14px` — und eine Kurzform
     schreibt alle vier Seiten neu, also auch die Reserve links. Gleiche
     Spezifität, spätere Regel gewinnt.
     Am Desktop fiel es nie auf: dort ist das Kästchen bis zum Hover
     unsichtbar (style.css:3900, `@media (hover:hover)`). Am Finger gibt es
     kein Hover — dort steht es immer, und immer auf dem Namen. */
  .pool-liste .firm-card--selectable { padding-left: 48px; }
  /* Zeilenumbruch der Marken statt Abschneiden: ein Firmenname darf nie
     verschwinden (dieselbe Regel wie in der Zentrale). */
  .pool-liste .firm-card__title { flex-wrap: wrap; row-gap: 6px; }
}

/* Tap-Boden: eine Karte, die ein Fenster oeffnet, ist ein Knopf. */
@media (max-width: 1024px), (pointer: coarse) {
  .pool-liste .firm-card { min-height: 44px; }
}

/* Der Wirt des Werkzeug-Blattes existiert am Desktop gar nicht: dort stehen
   Ansicht, Filter und Auto-Verteilung sichtbar an ihrem Platz. */
.pool-werkzeuge { display: none; }

/* DIE ZWEI MASSENWEGE SIND EINE FAMILIE — «Leads hochladen» (N Leads) und
   «Auto-Verteilung» (N Zuweisungen). Sie stehen darum in EINER Huelle und
   reisen als ein Stueck ins Werkzeug-Blatt (views/manager-pool.js, `ordne`).
   Am Desktop aendert diese Regel kein Pixel: die Huelle ist eine Zeile mit
   demselben Abstand, den `.filters-actions` ihren Kindern gibt. */
.pool-massen { display: flex; align-items: center; gap: 8px; min-width: 0; }

/* ===========================================================================
   FLÄCHE 3 — DER POOL AM HANDY (`#/m/pool`), 08.08. zweite Runde
   ---------------------------------------------------------------------------
   GRENZE: alles hier hängt an `body.lx-pool` (gesetzt von manager-pool.js,
   abgeräumt in destroy()) UND am Handy-Breakpoint. Der Desktop sieht keine
   einzige dieser Regeln, und die Berater-Fläche (`#/m/my-leads`), die
   dieselben `firm-card`-Klassen benutzt, ebenfalls nicht.

   DER BEFUND (gemessen an der ECHTEN Fläche, 390×620, nicht an einer Probe):
     290 von 620 px waren Rahmen = 47 %. Aufteilung:
       Kopfzeile 52 · Ansicht-Block 106 · Suchzeile 50 · Knopfzeile 55 · Polster
     Der grösste Einzelposten war der Ansicht-Block — ein Bedienelement, das
     man selten anfasst, dauerhaft im Bild. Owner: «Man checkt nichts, es hat
     keine Übersicht.»

   DIE ANTWORT, drei Züge:
     1 Ansicht, Filterfelder und Auto-Verteilung ziehen hinter EINEN Griff
       («Werkzeuge») ins Blatt — dasselbe Bauteil wie im Rechner, kein zweites
       Muster. Damit fällt auch der alte Inline-Aufklapper: er schob sechs
       Auswahlfelder in die Fläche und schnitt den ersten Lead ab.
     2 «+ Neuer Lead» ist eine benannte Zeile statt des schwebenden Kreises.
     3 Die Karte beantwortet vier Fragen: wer (Name UND Ort), welcher Zustand,
       was ist der nächste Schritt, und die Nummer als Handlung «Anrufen».

   DIE GRENZE IST 720 px — dieselbe wie die der Kurzform darüber, absichtlich.
   Eine erste Fassung nahm `(max-width: 1080px), (pointer: coarse)` von der
   Offerten-Liste. Damit gälte zwischen 721 und 1080 px die neue Leiste, aber
   die ALTE Karte (mit voller Adresse und Fusszeile) — ein Zwischenzustand, den
   niemand entworfen hat. Wer diese Grenze weitet, weitet die Kurzform mit.
   Die JS-Seite hält denselben Wert (`schmal` in views/manager-pool.js).
   =========================================================================== */
@media (max-width: 720px) {

  /* 1 — DER SEITENTITEL FÄLLT. «Pool» steht schon im aktiven Punkt der
         Daumenleiste; ein Titel, der nur wiederholt, ist verlorene Höhe
         (dieselbe Entscheidung wie auf der Offerten-Liste). */
  body.lx-pool .admin-page__head { display: none; }
  body.lx-pool .admin-page { padding: 2px 12px 0; }

  /* 2 — DIE WERKZEUGE ZIEHEN INS BLATT.
         Der Wirt ist `fixed` und endet ÜBER der Daumenleiste (`--boden-h`,
         seit 09.08. aus dem Höhen-System statt als geratene 70 px): das Blatt
         deckt den Inhalt, nie den Ausgang — dieselbe Zusage wie im Cockpit.
         Solange nichts offen ist, liegt er ohne Zeigerannahme über der Fläche
         und fängt keinen einzigen Tipp ab. */
  body.lx-pool .pool-werkzeuge {
    display: block;
    /* 05.09.2026 — 30 auf 95: der schwebende «+» der Schale liegt auf z-index
       90 und lag damit AUF dem offenen Werkzeug-Blatt. Gemessen am offenen
       Blatt der Betreiber-Liste, 390 px: der Knopf (320,488, 52 x 52 px)
       verschluckte den Tipp auf die unterste Zeile. Dasselbe Blatt, dieselbe
       Zahl wie `.lx-blatt-wirt` (docs/design/patch-telefon-griffe.css) —
       zwei Zahlen für dieselbe Schicht wären die nächste Drift. */
    position: fixed; inset: 0 0 var(--boden-h); z-index: 95;
    pointer-events: none;
  }
  body.lx-pool .pool-werkzeuge > .lx-blatt { pointer-events: auto; }
  /* Zwei Felder je Reihe. Untereinander bräuchten die sieben Filter 460 px —
     mehr, als das Blatt hoch ist (84 % von 550 px), und man müsste in einem
     Blatt scrollen, das nicht sagt, dass es weitergeht. Zu zweit passen sie
     ganz hinein: alles, was die Liste schneidet, steht auf einen Blick da. */
  body.lx-pool .lx-blatt__fach .pool-filter__mehr {
    display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin: 0 0 12px;
  }
  body.lx-pool .lx-blatt__fach .pool-filter__mehr .field { min-width: 0; }
  /* Das Blatt zeigt seinen ganzen Inhalt, ohne zu scrollen — sonst läge die
     Auto-Verteilung unter der Kante und niemand fände sie. 92 % statt der
     üblichen 84 %: der dunkle Streifen darüber bleibt breit genug, um zum
     Schliessen getippt zu werden. */
  body.lx-pool .pool-werkzeuge .lx-blatt__karte { max-height: 92%; }
  /* Ansicht-Chip, «Sichern» und der Ausklapper in EINE Zeile. Untereinander
     kosteten sie 96 px — die fehlten unten beim Knopf. */
  body.lx-pool .lx-blatt__fach .aw { display: block; margin: 0 0 10px; }
  body.lx-pool .lx-blatt__fach .pl-ansichten {
    grid-template-columns: minmax(0, 1fr) auto auto; align-items: center;
  }
  body.lx-pool .lx-blatt__fach .pl-ansichten .pl-chip { grid-column: 1; }
  /* IM BLATT TEILEN SICH DIE ZWEI MASSENWEGE EINE ZEILE (zweite
     Gegenpruefung, 18.08.2026). Untereinander kosteten sie 52 px mehr, als das
     Blatt hoch ist — der Waechter `_pool_ui_test.mjs` sagt es wortgenau: «das
     Blatt zeigt alles ohne Scrollen — auch seinen Knopf». Nebeneinander kostet
     der Zug NULL zusaetzliche Hoehe, und sie stehen da, wo sie hingehoeren:
     als Paar. */
  body.lx-pool .lx-blatt__fach .pool-massen {
    display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin: 0;
  }
  body.lx-pool .lx-blatt__fach .pool-massen > * {
    min-width: 0; min-height: 48px; justify-content: center; text-align: center;
  }
  body.lx-pool .lx-blatt__fach .field { gap: 3px; }
  body.lx-pool .lx-blatt__fach .primary-btn { width: 100%; min-height: 48px; }
  body.lx-pool .lx-blatt__fach select,
  body.lx-pool .lx-blatt__fach input { min-height: 44px; font-size: 16px; }

  /* 3 — DIE LEISTE IST EINE ZEILE, NICHT ZWEI.
         Hier stand «zwei Zeilen statt vier», und das war der letzte Schritt zu
         wenig. NACHGEMESSEN 09.08. an der echten Fläche (390×620, beide
         Motoren): der Inhalt begann bei 237 px — 38 % Rahmen, Ziel ist ein
         Drittel = 207 px, und ganz im Bild standen ZWEI von sechs Karten.

         DIE RECHNUNG, warum zwei Zeilen arithmetisch nicht zu retten waren:
           52 px App-Kopf + 53 px Reiterzeile = 105 px gehören der Schale und
              sind hier unantastbar (sie tragen Identität und Ortsangabe).
           Bleiben bis 207 px genau 102 px für die ganze Leiste.
           «Werkzeuge» UND «+ Neuer Lead» sind Tapflächen: je 44 px, nicht
              verhandelbar. Untereinander sind das 88 px plus Abstand — mit
              jedem Polster, das ein Kasten braucht, liegt man über 207.
         Also teilen sie sich EINE Zeile. Drei Handgriffe nebeneinander:
         Suche · Werkzeuge · «+ Neuer Lead». Die Trefferzahl steht als leise
         Bildunterschrift darunter — sie ist Anzeige, keine Tapfläche, und
         braucht darum keine 44 px.

         GEMESSEN DANACH (beide Motoren, 390×620): 185 px = 30 % Rahmen, drei
         Karten ganz im Bild. */
  /* Der Kasten um die Leiste fällt. Drei umrandete Felder in einem umrandeten
     Kasten sind am Handy eine Schachtel zu viel, und seine 28 px Polster
     fehlen dem Suchfeld in der Breite. */
  body.lx-pool .filters-panel {
    padding: 0 0 5px; margin: 0 0 10px;
    background: none; border: 0; border-radius: 0; box-shadow: none;
  }
  /* ⚠️ DIE LEISTE KLEBT AM HANDY NICHT MEHR — sie klebte an der falschen Kante.
     BEIM BLÄTTERN GESEHEN (09.08., 390×620, 220 px gescrollt): `.sticky-filters`
     hält bei `top: var(--sat) + 10px` (style.css:437). Dieser Wert stammt vom
     grossen Bildschirm, wo die Fläche keinen festen Kopf über sich hat. Am
     Handy sitzt darüber der 52 px hohe App-Kopf — die Leiste blieb also HINTER
     ihm stehen: «Werkzeuge» und «+ Neuer Lead» schimmerten durch seinen
     durchscheinenden Grund, und unter ihm ragte nur noch die Trefferzahl
     hervor. Eine Leiste, die man weder sieht noch treffen kann, kostet trotzdem
     ihren Platz.
     Die Antwort ist nicht, sie tiefer zu hängen: dann nähme sie beim Blättern
     dauerhaft 60 der 447 sichtbaren Pixel — auf einer Fläche, deren ganzer
     Auftrag «Übersicht» heisst. Sie rollt jetzt mit dem Inhalt weg. Ihre drei
     Handgriffe braucht man, BEVOR man blättert; oben ist sie mit einer
     Daumenbewegung zurück. Die Auswahl-Leiste liegt im selben Wirt und war
     hinter dem Kopf ohnehin unerreichbar — im Fluss ist sie auffindbar. */
  body.lx-pool .sticky-filters { position: static; margin-bottom: 10px; }
  body.lx-pool .pool-leiste {
    display: grid; grid-template-columns: minmax(0, 1fr) auto auto;
    gap: 5px 8px; align-items: center;
  }
  /* Die zwei Hüllen lösen sich auf, ihre Kinder werden Zellen DERSELBEN
     Zeile. Ohne `display: contents` blieben «Suche + Griff» und «+ Neuer
     Lead + Treffer» zwei Kästen — und zwei Kästen sind zwei Zeilen. */
  body.lx-pool .pool-leiste .filters-group,
  body.lx-pool .filters-panel .filters-actions { display: contents; }
  /* Jede Zelle bekommt ihren Platz ausdrücklich: `display: contents` schiebt
     auch Elemente ins Raster, die gerade im Blatt liegen (Ansicht-Block,
     Filterfelder, Auto-Verteilung wandern per JS hin und her). Ohne feste
     Platzangabe legte ein solcher Rückkehrer die Zeile um. */
  /* `min-width: 0` schlägt `.field--wide { min-width: min(420px, 100%) }`
     (grund.css): am 390er mass das Suchfeld sonst 100 % der Leiste und lag
     26 px unter dem Filter-Knopf (Breitenprobe 03.09.). */
  body.lx-pool .pool-leiste .field--search { position: relative; grid-column: 1; grid-row: 1; min-width: 0; }
  /* DIE LUPE. Ohne sie standen drei gleich grosse, gleich gerandete Kästen
     nebeneinander — am Bild gesehen war nicht zu erkennen, dass der linke ein
     Feld zum Tippen ist und die beiden rechten Knöpfe sind. Das Zeichen steht
     NEBEN dem Wort, nie an seiner Stelle: der Platzhalter bleibt lesbar. */
  body.lx-pool .pool-leiste .field--search::before {
    content: ""; position: absolute; left: 12px; top: 50%; margin-top: -8px;
    width: 16px; height: 16px; background: var(--text-tertiary); pointer-events: none;
    -webkit-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.2' stroke-linecap='round'><circle cx='11' cy='11' r='7'/><path d='m20 20-3.6-3.6'/></svg>") center / contain no-repeat;
    mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.2' stroke-linecap='round'><circle cx='11' cy='11' r='7'/><path d='m20 20-3.6-3.6'/></svg>") center / contain no-repeat;
  }
  /* Das Suchfeld: 16px ist keine Geschmacksfrage — darunter zoomt iOS beim
     Antippen in die Seite hinein, und danach steht alles verrutscht da.
     Der Platzhalter wird am Handy kurz gesetzt (views/manager-pool.js):
     «Firmenname…» passt in diese Spalte nicht mehr und stünde abgeschnitten. */
  body.lx-pool .pool-leiste .field--search input {
    min-height: 44px; font-size: 16px; padding-left: 36px;
    /* ⚠️ NUR IN SAFARI GESEHEN, und genau dort arbeitet der Owner: WebKit gibt
       `input[type=search]` sein eigenes Aussehen (`searchfield`) und hält am
       rechten Rand rund 22 px für sein Löschkreuz frei — auch wenn nichts
       darin steht. Von 74 px Innenbreite blieben 52, und der Platzhalter stand
       als «Suche⌐» abgeschnitten da (am Bild gesehen, 09.08., webkit 390×620;
       Chromium zeigte «Suchen» vollständig und verriet nichts).
       `appearance: none` gibt die Breite zurück; das Kreuz ersetzt am Handy
       ohnehin die Rückwärtstaste der Tastatur. */
    -webkit-appearance: none; appearance: none;
  }
  body.lx-pool .pool-leiste .field--search input::-webkit-search-decoration,
  body.lx-pool .pool-leiste .field--search input::-webkit-search-cancel-button { display: none; }
  /* Der Griff so schmal wie sein Wort — jedes Pixel hier fehlt der Suche. */
  body.lx-pool .pool-leiste .pool-filter__knopf {
    grid-column: 2; grid-row: 1; padding: 0 12px;
  }
  /* «+ Neuer Lead» ist eine benannte Zeile MIT Wort statt eines Kreises ohne.
     Der schwebende Plus-Knopf der App fällt auf dieser Fläche weg: er sagte
     nichts und deckte die dritte Karte halb zu.
     Der lange Wähler ist nötig: style.css:3965 setzt `flex: 0 1 auto` auf
     JEDEN Knopf dieser Zeile, mit drei Klassen. Ein kürzerer Wähler verliert
     und der Knopf blieb schmal (am Bild gesehen). */
  body.lx-pool .filters-panel .filters-actions .pool-neu {
    grid-column: 3; grid-row: 1;
    min-width: 124px; min-height: 44px; padding: 0 12px;
    justify-content: center; white-space: nowrap;
  }
  /* Die Trefferzahl sagt, wie gross der Bestand hinter der Liste ist («1044
     Treffer» ist eine andere Fläche als «6»). Sie verliert dafür ihre
     Kapsel: als Knopf verkleidet nahm sie 30 px Höhe für eine Zahl, die
     niemand drückt. */
  body.lx-pool .pool-leiste .results-pill {
    grid-column: 1 / 3; grid-row: 2;
    min-height: 0; padding: 0 2px; background: none;
    color: var(--text-tertiary); font-size: 12px; line-height: 1.35;
  }
  /* W6.4 — DER WEG ZU DEN VERLORENEN LEADS TEILT SICH DIE ZEILE MIT DER ZAHL.
     Am Handy fällt der Seitenkopf (Zug 1 oben), also zieht der Weg per JS in
     diese Zeile (views/manager-pool.js, `ordne`). Er bekommt seinen Platz
     ausdrücklich — sonst legte er als Rückkehrer eine dritte Zeile an, und
     genau eine dritte Zeile ist der Rahmen, den diese Fläche nicht hat.
     Er steht rechts, ruhig wie die Zahl links: ein WEG, keine Handlung —
     «+ Neuer Lead» darüber bleibt der einzige Knopf mit Knopf-Anmutung. */
  body.lx-pool .pool-leiste .pool-weg {
    position: relative;
    grid-column: 3; grid-row: 2; justify-self: end; align-self: center;
    min-height: 32px; padding: 0 10px; border: 0; background: none;
    color: var(--accent-strong); font-size: 12.5px; font-weight: 600;
    white-space: nowrap;
  }
  /* DIE TAPFLÄCHE OHNE DIE HÖHE. 44 px als `min-height` schoben den Rahmen
     dieser Fläche von 197 auf 213 px — über das obere Drittel hinaus, das
     `_pool_ui_test.mjs` misst (Ziel 207 px). Der Daumen braucht aber 44 px.
     Beides geht: das Kästchen bleibt 32 px hoch, die FANGFLÄCHE ist 44 px und
     liegt mittig darüber. Sie gehört dem Anker selbst, ein Tipp darauf ist
     ein Tipp auf ihn — kein zweites Element, kein zweiter Zuhörer. */
  body.lx-pool .pool-leiste .pool-weg::after {
    content: ""; position: absolute; left: 0; right: 0; top: 50%;
    height: 44px; transform: translateY(-50%);
  }
  /* 05.09.2026: `.qc` -> `.qc__fab`. Weg ist weiter der SCHWEBENDE KNOPF (er
     lag auf der Pool-Leiste), nicht das Menue: seit «Neu» am Telefon in der
     Leiste am Daumen steht (docs/design/grund.css, «DER PLUS WANDERT IN DIE
     LEISTE»), wohnt in `.qc` die Schnellwahl dieses Ziels. Mit `display: none`
     auf der Huelle waere «Neu» ausgerechnet im Pool ein Griff ohne Wirkung —
     dort, wo der Berater seinen naechsten Lead anlegt. Sichtbar aendert sich
     nichts. */
  body.lx-pool .qc__fab { display: none; }
  /* Ohne den schwebenden Knopf braucht die Seite unter der letzten Karte auch
     nicht mehr seinen Platz freizuhalten. Der Verzicht steht jetzt als EINE
     Zahl im Höhen-System statt als eigene padding-Regel — die Daumenleiste
     bleibt darin unverändert reserviert. */
  body.lx-pool.has-quick-create { --fab-h: 0px; }

  /* 4 — DIE KARTE BEANTWORTET VIER FRAGEN IN ZWEI ZEILEN.
         Zeile 1: Name · Ort · Priorität · Zustand (bricht um, nie abgeschnitten).
         Zeile 2: «Nächster Schritt …» links, «Anrufen» rechts.

         ⚠️ ZURÜCK AUF RASTER. Ab 720 px abwärts stellt style.css:3926 die Karte
         auf `flex-direction: column` und ordnet ihre Teile über `order` —
         Rasterangaben sind dort wirkungslos. Eine erste Fassung dieses Blocks
         setzte nur `grid-row` und bekam die Schritt-Zeile prompt ÜBER den
         Firmennamen (sie hat `order: 0`, der Titel `order: 1`; am Bild gesehen).
         Wer hier Zeilen verteilt, muss das Raster ausdrücklich zurückholen.
         Die zweite Zeile ist 44 px hoch, weil der Knopf so hoch sein muss —
         der Schritt-Text hat darin Platz für zwei Zeilen, ohne dass die Karte
         wächst. */
  body.lx-pool .pool-liste .firm-card--lead {
    display: grid; grid-template-columns: minmax(0, 1fr) auto;
    gap: 6px 10px; align-items: center;
  }
  body.lx-pool .pool-liste .firm-card--lead .firm-card__title { grid-column: 1 / -1; grid-row: 1; }
  body.lx-pool .pool-liste .firm-card--lead .firm-card__schritt {
    grid-column: 1; grid-row: 2; flex-wrap: wrap; gap: 0 6px;
  }
  body.lx-pool .pool-liste .firm-card--lead .firm-card__contact { grid-column: 2; grid-row: 2; }
  /* Steht der Ort da, ist die Region eine Wiederholung — «Zürich · Zürich» auf
     jeder zweiten Karte. Sie bleibt am Desktop und im Filter. */
  body.lx-pool .pool-liste .firm-card__title:has(.firm-card__ort) .firm-card__region { display: none; }
  /* Kleinere Abzeichen: die Titelzeile hat 314 px, und «Coiffure Beispiel 1 AG»
     plus Ort plus zwei Abzeichen lagen bei 333 px — sie brach um, und 25 mal
     21 px sind fast ein ganzer Bildschirm. Elf Pixel Schrift bleiben über dem
     Lesboden (DESIGN.md: 11 px), das Abzeichen bleibt über dem Tapboden, weil
     es keine Tapfläche ist: es zeigt an, man drückt es nicht. */
  body.lx-pool .pool-liste .firm-card__title .badge {
    font-size: 11px; padding: 2px 8px; gap: 5px;
  }
  /* DIE NUMMER WIRD EINE BENANNTE HANDLUNG. Sie stand als blauer Link da —
     am Handy liest sich das wie ein Datenfeld, nicht wie ein Knopf, und
     «+41 44 261 88 20» nahm die halbe Kartenbreite. Die Nummer bleibt im DOM
     (Vorleseprogramme und der `tel:`-Sprung brauchen sie), sichtbar steht die
     Handlung. Kein Zeichen ohne Wort: das Wort ist da, das Zeichen daneben. */
  body.lx-pool .pool-liste .firm-link[data-call-link] {
    min-height: 44px; padding: 0 14px; border-radius: var(--radius-button);
    border-color: var(--accent-line); background: var(--accent-soft);
    font-size: 0; white-space: nowrap;
  }
  body.lx-pool .pool-liste .firm-link[data-call-link]::after {
    content: "Anrufen"; font-size: 14px; font-weight: 600; letter-spacing: .01em;
  }
  body.lx-pool .pool-liste .firm-link[data-call-link] .eico { font-size: 14px; }
  /* DER LEERFALL. Ohne Nummer stand in Spalte zwei gar nichts: die Kurzform
     der Pool-Karte blendet `.firm-card__meta` aus, und der Satz «Keine Nummer
     hinterlegt» steckt genau darin. Eine Karte, die dazu schweigt, sieht aus
     wie eine, bei der der Knopf fehlt. Hier steht er wieder — leise, ohne
     Knopf-Anmutung, damit niemand daraufdrückt. */
  body.lx-pool .pool-liste .firm-card__contact .firm-card__meta {
    display: inline-flex; font-size: 12px; color: var(--text-tertiary); white-space: nowrap;
  }
}

/* -------------------------------------------------------------------------
   W6.4 — Der Kopf des Pools trägt seinen Namen UND den Weg daneben
   -------------------------------------------------------------------------
   Die verlorenen Leads waren am Handy zwei Ebenen tief («Werkzeuge» →
   Auswahlfeld «Modus»). Die Dramaturgie (Teil 4.3) verbietet das: ein
   Zustand, der eine Arbeit benennt, gehört nie hinter «Mehr».

   Der Weg steht darum in der ersten Zeile der Fläche — am grossen Bildschirm
   neben dem Namen, zwischen 721 und 900 px allein (dort fällt nur die
   Überschrift, style.css «Handy: der Inhalt beginnt oben»). Unter 720 px
   fällt der ganze Kopf (Zug 1 weiter oben); dort zieht der Weg per JS in die
   Zeile der Trefferzahl und bekommt seine Regeln im Block darüber. */
.pool-kopf { display: flex; align-items: baseline; flex-wrap: wrap; gap: 6px 12px; }
.pool-kopf h1 { flex: 0 0 auto; }
.pool-weg { flex: 0 0 auto; align-self: center; }

@media (max-width: 900px), (pointer: coarse) {
  /* Tapfläche wie jeder andere Griff am Finger-Gerät. Unter 720 px gewinnt die
     schmalere Fassung im Block darüber (höhere Spezifität) — dort trägt eine
     eigene Fangfläche die 44 px, ohne die Zeile höher zu machen. */
  .pool-weg { min-height: 44px; display: inline-flex; align-items: center; }
}

/* ============================================================
   Patch-Integration — Namensraum sl-kern; Quelle: docs/design/patch-listen.css
   Standorte und Rechnungen am Handy (Karte 01.08., Position 11).
   ============================================================ */
/* =========================================================================
   Standorte und Rechnungen am Handy — Karte 01.08., Position 11
   #/v/locations und #/v/invoices

   GEMESSEN (Karte, Abschnitt 1): Standorte 10,7 Handy-Bildschirme,
   Rechnungen 2,1 bei DREI Rechnungen (bei dreissig waeren es zwanzig).
   Beide blaettern laengst. Die Hoehe kommt aus der Umwandlung der Tabelle:
   `.sl-table td::before` macht am Handy aus jeder Zelle eine Feldzeile mit
   Beschriftung — aus EINER Tabellenzeile werden SIEBEN untereinander.
   Das ist richtig gedacht (die Karte lobt es als einzige Flaeche, die die
   Tabelle nicht abschneidet) und in dieser Menge trotzdem unbenutzbar.

   DIE LINIE: am Handy traegt die Zeile ihren KERN.
     Standorte    Salon + Zustand, darunter Ort und Bildschirme
     Rechnungen   Nummer + Zustand, darunter Kunde, Total und Faelligkeit
   Der Rest steht auf Tipp: beide Zeilen oeffnen seit jeher ein Fenster mit
   dem vollstaendigen Datensatz. Die Feld-Umwandlung von `.sl-table` bleibt
   fuer alle anderen Tabellen unangetastet; hier wird sie nur GESCHNITTEN.

   Beweis: scripts/_blockb_flaechen_test.mjs (390x844).
   ========================================================================= */

/* Angesprochen über `data-kern`, weil die Zellen keine eigenen Klassen
   tragen — dasselbe Muster benutzt style.css schon für `.pl-table` und
   `.dw-tabelle` über `data-label`. */
/* Die Nebenwerte stehen als EIN Satz in einer eigenen Zelle, die am grossen
   Bildschirm gar nicht erscheint. Warum eine eigene Zelle statt der
   vorhandenen: die vorhandenen sind einzelne Rasterfelder und liessen sich
   nicht verlässlich in EINE zweite Zeile zwingen — und als Satz («Ebikon ·
   3 Bildschirme») liest sich der Kern ohnehin besser als vier Zellen. Die
   Werte sind dieselben, aus derselben Zeile, in derselben Funktion gebaut. */
.sl-kern { display: none; }

/* -------------------------------------------------------------------------
   05.09.2026 · DIE NUMMER BRACH SENKRECHT — Buchstabe unter Buchstabe

   GEMESSEN auf #/v/invoices, 390 px (scripts/_handy_verkauf_ui_test.mjs):
   die Rechnungsnummer «RE-2026-0001» mass 10 x 248 px — ZWOELF Zeilen fuer
   zwoelf Zeichen. Auf 430 px waren es drei Zeilen (45 x 59 px). Getroffen
   war genau die eine Zeile, die einem Berater am meisten sagt: die
   ueberfaellige, gemahnte Rechnung.

   URSACHE, in drei Gliedern:
     1. `grid-template-columns: 1fr auto` — die Zustands-Spalte stand auf
        `auto`, nahm also die max-content-Breite ihrer drei nicht
        umbrechenden Chips («Offen» + «8 Tg ueberfaellig · gemahnt x1» +
        Mail-Marke) = 308 px.
     2. Von 332 px Zeilenbreite blieben der Nummer 14 px. Ein Grid-Kind mit
        `min-width: 0` darf beliebig weit darunter schrumpfen — das war hier
        ausdruecklich gesetzt.
     3. `.sl-table td { overflow-wrap: break-word }` (grund.css:4594) brach
        den Rest Zeichen fuer Zeichen.

   WARUM ES NIEMAND SAH: es gab keinen Querlauf. Der Text lief nach UNTEN.
   Und `.table-wrap` behaelt bei Kern-Tabellen `overflow-x: auto`
   (patch-konfigurator.css:1376 nimmt sie ausdruecklich aus) — ein
   seitlicher Ueberlauf waere dort ebenfalls verschluckt worden. Dieselbe
   Haus-Lehre wie am 31.08.: ein Ueberlauf ohne Scrollbalken ist der
   gefaehrlichste.

   DIE LOESUNG IST DIE UMKEHRUNG DER KNAPPHEIT: nicht die Kennung schrumpft,
   sondern der Zustand RUTSCHT. Aus dem Raster wird eine umbrechende Reihe.
   Der Browser bricht eine Flex-Reihe an der HYPOTHETISCHEN Groesse der
   Kinder um, also BEVOR er sie staucht: passt der Zustand nicht mehr neben
   die Kennung, bekommt er eine eigene Zeile — die Kennung behaelt ihre
   volle Breite und bleibt einzeilig.

   `width: auto` ist dabei nicht schmueckend, sondern tragend: grund.css:3666
   gibt am Handy JEDER `.sl-table td` ein `width: 100%`. Als Flex-Kind
   verlangte damit jede Zelle die ganze Zeile — gemessen: alle drei Zellen
   untereinander, auch dort, wo sie bequem nebeneinander passen.

   WAS SICH NICHT AENDERT, GEMESSEN (390 px, Rechnungsliste):
     · die vier unbelasteten Zeilen stehen auf 0,01 px genau wie vorher
       (Oberkanten 347.00 / 411.30 / 563.89 ..., Hoehe 64-65 px)
     · ab 721 px greift dieser Block ohnehin nicht; die Tabelle bleibt Tabelle
   WAS SICH AENDERT: die belastete Zeile 293 px -> 88 px, die Nummer
   10 x 248 px -> 108 x 17 px, die ganze Liste 941 px -> 736 px.
   Beweis ist EINER: `_handy_verkauf_ui_test.mjs`, Kennungs-Probe auf 390 und
   430. Sie ist an dieser Stelle rot gewesen — gegen den Stand vor dem Fix
   meldet sie woertlich «schlimmste RE-2026-0001 12 Zeilen (10x248px)» und
   endet 49/52.

   `_jede_breite_test.mjs --nur=rechnungen,standorte` ist HIER KEIN BEWEIS,
   auch wenn er gruen ist (Pruefung 05.09., zweite Runde). Seine Buehne
   (scripts/lib/fundament-buehne.mjs:808-815) zeigt beide Flaechen im
   LEERZUSTAND — gemessen auf 768 px: Tabellenzeilen 0, Sortkoepfe 0,
   Karten 0. Ohne Zeile gibt es keine `.sl-table--kern tr`, und der Lauf
   kann diesen Block gar nicht sehen: gegen den kaputten Stand 74fc6ea6
   meldet er unveraendert 19/19. Was er wirklich deckt, ist das Booten und
   der Leerzustand auf allen neun Breiten — nicht die Kennung.

   GILT FUER BEIDE TRAEGER von `.sl-table--kern`: Rechnungen
   (sales-invoices.js:763) und Standorte (sales-locations.js:508). In der
   Standortliste traegt Spalte 1 den SALON-NAMEN, keine Kennung — ein Name
   darf und soll umbrechen. Genau darum steht hier kein `white-space: nowrap`
   und keine Ellipse: die Regel nimmt der Kennung die Enge, statt dem Namen
   den Umbruch zu verbieten.
   ------------------------------------------------------------------------- */
@media (max-width: 720px) {
  /* Zeile 1: Name links, Zustand rechts. Zeile 2: die Nebenwerte.
     Reicht der Platz in Zeile 1 nicht, rutscht der Zustand auf eine eigene. */
  .sl-table--kern tr {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    column-gap: 10px;
    row-gap: 2px;
    padding: 10px 14px;
  }
  .sl-table--kern td { display: none; padding: 0; text-align: left; }
  .sl-table--kern td::before { content: none; }
  /* Die Kennung nimmt den freien Platz, gibt ihn aber nie an den Zustand ab. */
  .sl-table--kern td[data-kern="1"] {
    display: block; flex: 1 1 auto; width: auto; min-width: 0; font-weight: 600;
  }
  /* Der Zustand ist so breit wie sein Inhalt und steht rechts — auch dann,
     wenn er allein auf seiner Zeile steht (`margin-left: auto`). */
  .sl-table--kern td[data-kern="2"] {
    display: block; flex: 0 1 auto; width: auto; min-width: 0;
    margin-left: auto; text-align: right;
  }
  /* Letzte Rettung fuer den Fall, den es heute nicht gibt: ein EINZELNER
     Chip, der breiter waere als die ganze Zeile. Chips sind `nowrap`
     (grund.css .sl-badge, patch-verkauf .vk-chip) — hier, und nur hier,
     duerfen sie an einer Luecke brechen, statt ihren Kasten zu sprengen.
     Bei den heutigen Chips (breitester 241 px von 332 px) greift die Regel
     nicht; sie ist der Boden, nicht das Mittel. */
  .sl-table--kern td[data-kern="2"] > * { max-width: 100%; white-space: normal; }
  .sl-table--kern td.sl-kern {
    display: block; flex: 1 0 100%; width: 100%;
    font-size: 12px; color: var(--text-secondary);
  }
}

/* Tap-Boden: eine Zeile, die ein Fenster oeffnet, ist ein Knopf. */
@media (max-width: 1024px), (pointer: coarse) {
  .sl-table--kern tr[data-id] { min-height: 44px; }
}


/* =========================================================================
   WISSEN — #/v/wissen (W5-E5)

   Der eine Ort fuer das Verkaufs-Wissen. Aufbau geliehen, nicht erfunden:
   Kopf, Suchleiste, Panel je Kategorie kommen aus dem `vk`-Namensraum
   (dieselben Klassen wie Kunden und Kunden-Detail). Eigen ist nur die
   DATEIZEILE — sie ist eine Panel-Zeile, keine Tabelle: eine Wissensdatei
   hat drei Angaben, und drei Angaben brauchen keinen Tabellenkopf.

   Am Handy klappt die Zeile: Titel und Nebenangaben untereinander, die
   beiden Pflege-Knoepfe darunter in einer Reihe. Jede Tap-Flaeche >= 44px
   (Memory project_mobile_pwa_mandatory + project_tablet_touch_breakpoint —
   der Boden gilt auch auf Tablet-Breiten und bei grobem Zeiger).
   Beweis: scripts/_wissensraum_ui_test.mjs (390x844).
   ========================================================================= */
.ws-liste { display: flex; flex-direction: column; }
.ws-zeile {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 0; min-height: 44px;
  border-top: 1px solid var(--vk-kante);
}
.ws-zeile:first-child { border-top: 0; }
.ws-zeile__ic { flex: 0 0 auto; }
/* Der Titel IST der Knopf: wer eine Wissensdatei sucht, tippt auf ihren
   Namen — nicht auf ein Wort «Oeffnen» daneben. */
.ws-zeile__oeffnen {
  flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column;
  gap: 2px; padding: 0; text-align: left;
  background: none; border: 0; cursor: pointer; color: inherit; font: inherit;
}
.ws-zeile__titel {
  font-weight: 600; color: var(--text-primary);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ws-zeile__oeffnen:hover .ws-zeile__titel,
.ws-zeile__oeffnen:focus-visible .ws-zeile__titel { color: var(--accent); }
.ws-zeile__meta { font-size: 12px; color: var(--text-secondary); }
.ws-zeile__akt { flex: 0 0 auto; display: flex; gap: 6px; }
/* Der Ablege-Knopf ist ein Label mit verstecktem Dateifeld (Muster
   material-panel.js:100) — er muss trotzdem aussehen und sich anfuehlen
   wie ein Knopf. */
.ws-ablegen { cursor: pointer; display: inline-flex; align-items: center; }
.ws-formular__felder {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 10px;
}
.ws-formular__akt { display: flex; gap: 8px; margin-top: 12px; flex-wrap: wrap; }
/* Der Grund steht unter dem Satz, nicht daneben: er ist die Serverantwort
   und darf die Zeile nicht sprengen. */
.ws-grund { display: block; margin-top: 4px; font-size: 12px; color: var(--text-secondary); }

@media (max-width: 720px) {
  .ws-zeile { flex-wrap: wrap; padding: 10px 0; }
  .ws-zeile__oeffnen { flex: 1 1 100%; }
  .ws-zeile__titel { white-space: normal; }
  .ws-zeile__akt { flex: 1 1 100%; }
  .ws-zeile__akt .ghost-btn { flex: 1 1 0; }
}

/* Tap-Boden — gilt auch in der Tablet-Bruchzone und bei grobem Zeiger. */
@media (max-width: 1024px), (pointer: coarse) {
  .ws-zeile__oeffnen { min-height: 44px; justify-content: center; }
  .ws-zeile__akt .ghost-btn { min-height: 44px; }
  .ws-ablegen { min-height: 44px; }
}

/* =========================================================================
   Die Ordnung der Listen — W5.5 «Der Listen-Pass»
   #/v/customers · #/v/offers · #/v/invoices · #/v/locations

   ANLASS, gemessen (docs/berichte/ganzes-bild/C-ist-und-auffindbarkeit.md,
   Klasse H): vier Flaechen ohne jede Sortiersteuerung, waehrend
   Standortbetreiber, Vertriebe, Vermittlungen und Team-Uebersicht sie
   laengst hatten. Owner am Video: «Die Testkunde, wo habe ich den jetzt? …
   Ich finde es nicht.»

   ZWEI BAUTEILE, EIN ZUSTAND (Markup: public/src/utils/sortierung.js):
     .lst-ordnung   die immer sichtbare Auswahl «Sortieren: …». Sie ist die
                    HAUPTsteuerung — `.sl-table thead` ist am Handy
                    ausgeblendet (style.css, Block «Standorte und Rechnungen
                    am Handy» weiter oben), ein Spaltenkopf allein waere dort
                    keine Tuer.
     .lst-sortkopf  der sortierbare Spaltenkopf mit Pfeil (EINHEIT 4.9), am
                    grossen Bildschirm ZUSAETZLICH.

   Beide Bauformen sind die bestehenden: `.pl-chip` und `.pl-sortkopf` der
   Standortbetreiber-Liste (docs/design/patch-partnerliste.css:54 und :117),
   Zeichen fuer Zeichen dieselben Werte. Eigener Namensraum, weil `pl-` der
   Standortbetreiber-Liste gehoert und eine Aenderung dort sonst vier
   Verkaufsflaechen mitrisse.
   ========================================================================= */

.lst-ordnung {
  display: inline-flex; align-items: center; gap: 6px;
  min-height: 38px; padding: 0 10px 0 12px;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-badge);
  font-size: 13px; color: var(--text-secondary); cursor: pointer;
}
.lst-ordnung:hover { border-color: var(--line-strong); }
.lst-ordnung:focus-within { border-color: var(--accent-line); }
.lst-ordnung__ic { display: grid; place-items: center; color: var(--text-tertiary); }
.lst-ordnung__ic svg { width: 15px; height: 15px; }
.lst-ordnung__wort { white-space: nowrap; }
.lst-ordnung select {
  min-height: 34px; padding: 0 4px; border: 0; background: transparent;
  color: var(--text-primary); font-size: 13px; font-weight: 550; cursor: pointer;
  max-width: 46vw;
}
.lst-ordnung select:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: var(--radius-card); }

/* Die Werkzeugzeile der Standorte trug bisher nur den Umschalter und war
   darum kein Behaelter. Jetzt stehen zwei Dinge darin — der Umschalter links,
   die Ordnung rechts daneben. Der Aussenabstand bleibt, wo er steht
   (`.sl-seg { margin-bottom: 4px }` im Grundstil) — hier kommt nur die
   Anordnung dazu. Die Klasse traegt genau EINE Flaeche
   (views/sales-locations.js:150), nachgesehen statt angenommen. */
.sl-seg { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }

/* Der Spaltenkopf ist ein echter <button> im <th>: Tabulator, Enter und
   Leertaste funktionieren damit ohne nachgebaute Tastatur-Logik. */
.lst-sortkopf {
  display: inline-flex; align-items: center; gap: 5px;
  background: transparent; border: 0; padding: 0; cursor: pointer;
  font: inherit; color: inherit; letter-spacing: inherit; text-transform: inherit;
}
.sl-table th.num .lst-sortkopf { flex-direction: row-reverse; }
.lst-sortkopf:hover, .lst-sortkopf:focus-visible { color: var(--text-primary); outline: none; }
.lst-sortkopf:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: var(--radius-card); }
.lst-sortkopf__pfeil { color: var(--text-tertiary); font-size: 11px; line-height: 1; }
.lst-sortkopf.is-aktiv { color: var(--accent-strong); }
.lst-sortkopf.is-aktiv .lst-sortkopf__pfeil { color: var(--accent); }

/* Tap-Boden — gilt auch in der Tablet-Bruchzone und bei grobem Zeiger
   (Memory project_tablet_touch_breakpoint: 720px allein laesst sie offen). */
@media (max-width: 1024px), (pointer: coarse) {
  .lst-ordnung { min-height: 44px; }
  /* 40 -> 44 am 28.08.2026. Der KASTEN stand auf 44, sein Griff auf 40 — aber
     angetippt wird die Auswahlliste, nicht ihr Rand. Gemessen auf /v/locations:
     select#sl-sort mass 179 x 40 px am Handy und 200 x 40 am Tablet, vier
     Pixel unter dem Boden, auf jeder Fingerbreite. */
  .lst-ordnung select { min-height: 44px; }
}

/* ============================================================
   Patch-Integration — Namensraum pr-; Quelle: docs/design/patch-preise.css
   Der Block wird bei Integration als GANZES ersetzt, nie editiert.
   ============================================================ */
/* =========================================================================
   Preise (#/v/pricing) — die Fläche, an der der Owner am 03.08. «wie kann man
   so etwas Hässliches machen … das ist beleidigend» gesagt hat.

   WAS DA STAND und warum es Gestaltung braucht, nicht nur Wörter: sechzehn
   nackte Zahlenfelder in zehn Kästen untereinander, jedes mit einer
   grauen Erklärzeile darunter («0.5 = −50 % ⇒ publizierte Rate-Card»), die
   Beschriftung in Bau-Vokabular («EARLY-BIRD-FAKTOR», «FOLGESLOT-FAKTOR»,
   «ZUSATZRABATT-CAP», «6-TAGE-FAKTOR»). Ein Formular-Abladeplatz — die Form,
   die das Owner-Gesetz `DAS-SYSTEM.md` «Einstellwerte sind kein
   Formular-Abladeplatz» ab sofort verbietet.

   DIE ANATOMIE, die diese Datei durchsetzt — eine Zeile = ein Wert:
     1. Links der SATZ mit der Zahl darin («Frühbucher zahlen 50 % vom
        Listenpreis»), darunter die WIRKUNG in Franken, live aus der echten
        Preis-Engine gerechnet. Rechts das Feld mit seiner Einheit.
        Kein Label über einem Feld, keine Erklärzeile unter einem Feld.
     2. Panel: `var(--surface)`, 1px Kante `rgba(var(--accent-rgb), .16)`,
        Radius 14px, CAPS-Kopf 10.5px/.08em (EINHEIT 3).
     3. Zahlen tabellarisch (`tabular-nums`) — Preisspalten, die untereinander
        stehen, springen sonst bei jeder Ziffer.
     4. Der Warnzustand ist ein Zustand, kein Absatz: eine Zeile mit Zeichen,
        Bernstein, keine drei Sätze Fliesstext.

   BAUSTEINE, die WIEDERVERWENDET werden (kein Nachbau): .panel, .empty-state,
   .primary-btn, .ghost-btn, .field, .stat, .table-wrap, .pnl-warn,
   .admin-page. Neu ist nur die Wert-Zeile `.pr-zeile` und das Preisraster
   `.pr-matrix` — beides gibt es in diesem Blatt nicht.

   Der Namensraum ist `pr-`. Die alten `.sp-*`-Regeln (style.css:3236-3282,
   3563-3565) bleiben unangetastet stehen: sie gehören zur abgelösten Fassung
   derselben Fläche und werden erst entfernt, wenn jemand sie ausdrücklich
   aufräumt — eine fremde Zeile in einer fremden Welle ist kein Gewinn.

   EINSETZEN: Diesen Block unverändert an das ENDE von public/style.css
   hängen (Projekt-Cascade-Regel, Memory project_css_cascade_mobile: ein
   eigener @media-Block gehört NACH die Basis-Regeln, sonst wirkt er nicht).
   ========================================================================= */

/* Welle 8 «Muster», 18.08.2026 — ENTFERNT, nicht ersetzt: .pr-kopf__akt (1×), .pr-kopf__stand (1×).
   Diese Hülle(n) waren eine Nachbildung der EINEN Kopfreihe. Sie kommt jetzt
   aus `components/seiten-kopf.js` (Blatt patch-seitenkopf.css, Abschnitt 1b/2).
   «Ersetzen statt daneben» — Hausregel 7. */

.pr-page { display: flex; flex-direction: column; gap: 14px; }

/* Kopf: Titel links, Speichern/Verwerfen rechts. BEWUSST NICHT klebend: ein
   klebender Kopf hängt am nächsten scrollenden Vorfahren — das ist je nach
   Fläche die Seite oder die App-Hülle, und auf 390px frisst er ein Viertel des
   Bildes. Gemessen am 03.08.: der Titel wurde dort oben abgeschnitten. */
/* Welle 8 «Muster», 18.08.2026: die REIHE (display/align/justify/gap/flex-wrap)
   stand hier ein zweites Mal — `.page-head` (grund.css:2840) sagt dasselbe. Sie
   ist entfernt; was bleibt, ist das, was `.page-head` NICHT sagt: dieser Kopf
   ist ein Kasten mit Rahmen. Und die eigene Titelgrösse (19 px) ist gefallen —
   EINHEIT 1.5 kennt EINEN Grad für einen Seitentitel, 26/650/-.02em, und der
   kommt jetzt zentral. `margin: 0` bleibt: `.pr-page` ist eine Flex-Spalte mit
   14 px Abstand, ein zweiter Rand darunter wäre doppelt. */
.pr-kopf {
  padding: 12px 16px; margin: 0;
  background: var(--surface);
  border: 1px solid rgba(var(--accent-rgb), .16);
  border-radius: var(--radius-card);
}

/* Gruppe = eine Sache. Der Kopf sagt, worum es geht, nicht welches Feld
   darunter liegt. */
/* Sprungleiste der Preise — zwölf Gruppen, 3400px Scroll (gemessen 06.08.).
   Sie klebt unter dem Kopf, damit man von jeder Stelle zu jeder anderen
   kommt, ohne zurückzuscrollen. Owner: «nicht dieser Dreck, der unendlich
   zum Scrollen ist … dann sieht man immer gleich, wo was ist.» */
.pr-sprung {
  position: sticky; top: 0; z-index: 5;
  display: flex; flex-wrap: wrap; gap: 6px;
  margin: 0 0 2px; padding: 9px 12px;
  border: 1px solid var(--border); border-radius: var(--radius-panel);
  background: var(--surface-1);
}
.pr-sprung button {
  padding: 6px 10px; border-radius: var(--radius-button);
  border: 1px solid var(--border); background: var(--surface);
  color: var(--text-secondary); font: inherit;
  font-size: 12px; line-height: 1.2; white-space: nowrap; cursor: pointer;
}
.pr-sprung button:hover { color: var(--text-primary); background: var(--surface-2); border-color: var(--accent-line); }
.pr-sprung button.is-hier { color: var(--accent-strong); border-color: var(--accent-line); background: var(--accent-soft); }
/* Der Anker darf nicht unter der klebenden Leiste landen. */
.pr-gruppe { scroll-margin-top: 68px; }

@media (max-width: 780px) {
  .pr-sprung { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; }
  .pr-sprung::-webkit-scrollbar { display: none; }
}
@media (max-width: 640px) {
  /* Als Karte gibt es keine erste Spalte, an der etwas kleben koennte. */
  .pr-matrix thead th:first-child,
  .pr-matrix tbody th:first-child { position: static; }
  .pr-matrix tbody th:first-child::after { content: none; }
}

.pr-gruppe {
  background: var(--surface);
  border: 1px solid rgba(var(--accent-rgb), .16);
  border-radius: var(--radius-card);
  padding: 16px 18px;
}
.pr-gruppe__kopf {
  display: block; margin: 0 0 2px;
  font-size: 11px; letter-spacing: .08em; text-transform: uppercase;
  font-weight: 700; color: var(--text-tertiary);
}
.pr-gruppe__satz {
  display: block; margin: 0 0 10px;
  font-size: 13px; color: var(--text-secondary);
  font-variant-numeric: tabular-nums;
}

/* --- Die Wert-Zeile: Satz links, Feld rechts ------------------------------ */
.pr-zeile {
  display: flex; align-items: center; gap: 10px 16px; flex-wrap: wrap;
  padding: 12px 0; border-bottom: 1px solid var(--border);
}
.pr-zeile:last-child { border-bottom: 0; }
.pr-zeile:first-of-type { padding-top: 4px; }
.pr-zeile__wort { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1 1 300px; }
.pr-zeile__satz {
  font-weight: 600; color: var(--text-primary); font-size: 13.5px;
  font-variant-numeric: tabular-nums;
}
/* Die Zahl im Satz trägt den Akzent — sie ist das, was der Owner ändert. */
.pr-zeile__satz b { color: var(--accent-strong); font-weight: 700; }
.pr-zeile__wirkung {
  font-size: 12.5px; color: var(--text-secondary);
  font-variant-numeric: tabular-nums;
}
.pr-zeile__wirkung b { color: var(--text-primary); font-weight: 600; }

/* Feld + Einheit als ein Block. Die Einheit steht IM Feldrahmen, damit sie
   nicht als zweites Wort gelesen wird. */
.pr-feld {
  display: inline-flex; align-items: center; gap: 6px; flex: 0 0 auto;
  padding: 0 10px 0 0;
  background: var(--surface-inset);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  transition: border-color var(--transition);
}
.pr-feld:focus-within { border-color: var(--accent); }
.pr-feld input {
  width: 92px; padding: 9px 4px 9px 11px;
  background: none; border: 0; color: var(--text-primary);
  font: inherit; font-size: 14px; font-variant-numeric: tabular-nums;
  text-align: right; -moz-appearance: textfield;
}
.pr-feld input:focus { outline: none; }
.pr-feld input::-webkit-outer-spin-button,
.pr-feld input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.pr-feld--breit input { width: 118px; }
.pr-feld__einheit {
  font-size: 12px; color: var(--text-tertiary); white-space: nowrap;
  font-weight: 600;
}

/* Schalter statt Feld: derselbe Platz rechts, damit die Spalte hält. */
.pr-schalter {
  display: inline-flex; align-items: center; gap: 8px; flex: 0 0 auto;
  cursor: pointer; user-select: none;
  font-size: 12.5px; color: var(--text-secondary);
}
.pr-schalter input[type="checkbox"] {
  width: 20px; height: 20px; accent-color: var(--accent); cursor: pointer;
}

/* Wahl aus Stufen (Mahnfarbe, Tarifname) — nie ein Freitextfeld, wo es
   genau drei Möglichkeiten gibt. */
/* `width: auto` ist hier keine Kosmetik: der Boden `select { width: 100% }`
   (style.css:445) macht aus jeder Auswahl sonst einen Balken über die ganze
   Zeile — die Spalte der Felder rechts bricht, und der Satz daneben steht
   allein auf seiner Zeile. Gemessen am 09.08. an der MWST-Auswahl. */
.pr-zeile select {
  flex: 0 0 auto; width: auto; max-width: 100%;
  padding: 9px 11px; background: var(--surface-inset);
  border: 1px solid var(--border); border-radius: var(--radius-card);
  color: var(--text-primary); font: inherit; font-size: 13.5px;
}

/* Entfernen-Knopf einer Staffelzeile: klein, am Ende, ohne Farbe. */
.pr-zeile__weg { padding: 6px 10px; flex: 0 0 auto; }

/* Verweis-Zeile (E4 «Verweise statt Kopien»): sieht aus wie eine Wert-Zeile,
   setzt aber nichts — sie zeigt, wo der Wert wohnt. Der Satz steht darum
   ruhiger als ein Einstellsatz, damit niemand hier eine Eingabe sucht. */
.pr-zeile--verweis .pr-zeile__satz { color: var(--text-secondary); }
.pr-zeile--verweis .ghost-btn { flex: 0 0 auto; text-decoration: none; }

/* Ein Steuersatz, der heute nicht gilt: die Auswahl traegt die Warnfarbe, der
   Satz daneben sagt, was daraus JE FALL folgt — ein frueherer Satz heisst
   falsche Steuer auf neuen Belegen, ein unbekannter eine fehlende Zeile in der
   MWST-Abrechnung. Zwei verschiedene Schaeden, zwei verschiedene Saetze. */
.pr-zeile select.is-warn { border-color: rgba(var(--warn-rgb), .55); }

/* Stichtag eines kuenftigen Satzes: sichtbar, aber KEINE Eingabe — er ist ein
   Termin, keine Einstellung. Deshalb ohne Feld rechts und ruhiger gesetzt,
   damit ihn niemand fuer den heute gueltigen Wert haelt. */
.pr-zeile--stichtag { border-bottom: 0; padding-top: 2px; }
.pr-zeile--stichtag .pr-zeile__satz { color: var(--text-secondary); font-weight: 600; }

/* Rabatt-Korridor (F3): Obergrenze und Freigabe-Schwelle im selben Abschnitt.
   Die Regel-Zeilen kommen aus derselben Komponente wie im Regel-Zentrum und
   brauchen hier keinen zweiten Kasten. */
.pr-zeile--korridor { border-bottom: 0; padding-bottom: 2px; }
[data-slot="rabatt-korridor"] .lx-approval-rules { padding-bottom: 12px; }

/* Neue Staffelzeile anlegen: eine Zeile aus zwei kleinen Feldern + Knopf. */
.pr-neu { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; padding-top: 12px; }
.pr-neu .pr-feld input { width: 76px; }

/* --- Warnzustand ---------------------------------------------------------- */
.pr-warn {
  display: flex; align-items: flex-start; gap: 8px;
  margin: 0 0 10px; padding: 9px 12px;
  background: rgba(var(--warn-rgb), .10);
  border: 1px solid rgba(var(--warn-rgb), .28);
  border-radius: var(--radius-card);
  font-size: 12.5px; color: var(--warn-strong);
}
.pr-warn svg { flex: 0 0 auto; margin-top: 1px; }

/* --- Preisraster ---------------------------------------------------------- */
/* Eine Zeile je Bildschirmzahl, eine Spalte je Tarif. Der Spaltenkopf trägt
   den Tarifnamen UND die Regel, ab wie vielen Standorten er gilt — die
   Schwelle gehört an die Spalte, die sie auslöst, nicht in einen eigenen
   Kasten am anderen Ende der Fläche. */
.pr-matrix { width: 100%; border-collapse: separate; border-spacing: 0; }
/* Die Bildschirm-Spalte bleibt stehen, wenn die Matrix waagrecht scrollt —
   sonst weiss man beim vierten Tarif nicht mehr, ob man in Zeile «1
   Bildschirm» oder «6 Bildschirme» tippt. Masterplan Welle 4, Punkt 18:
   «Preismatrix erste Spalte fixiert». `border-collapse: separate` ist dafuer
   noetig — mit `collapse` traegt eine klebende Zelle ihre Rahmen nicht mit. */
.pr-matrix thead th:first-child,
.pr-matrix tbody th:first-child {
  position: sticky; left: 0; z-index: 2;
  background: var(--surface);
}
.pr-matrix thead th:first-child { z-index: 3; background: var(--surface-1); }
/* Der Rahmen muss mit: `separate` zeichnet ihn nicht mehr fuer die Nachbarn. */
.pr-matrix th, .pr-matrix td { border-bottom: 1px solid var(--border); }
.pr-matrix tbody th:first-child::after {
  content: ''; position: absolute; inset: 0 -1px 0 auto; width: 1px;
  background: var(--border);
}
.pr-matrix th, .pr-matrix td {
  padding: 8px 10px; text-align: left; vertical-align: top;
  border-bottom: 1px solid var(--border);
}
/* Der Spaltenkopf trägt den NAMEN einer Preisstufe, keine Beschriftung —
   deshalb hier ausdrücklich KEIN Versalsatz. Genau das war der Satz, den der
   Owner am 03.08. angeschrien fand: «LOOPSTARTER», «LX13 SPEZIAL». Die
   CAPS-Linie aus EINHEIT 3 gilt für Abschnitts-Label (.pr-gruppe__kopf), nicht
   für den Namen einer Stufe. Seit dem 08.09.2026 sind die Produktnamen selbst
   weg: der Name ist der Standort-Bereich («1–2 Standorte»), gerechnet aus den
   Schwellen des Owners (Kanon CL-039, Prüfgate G-16). */
.pr-matrix thead th {
  font-size: 12.5px; font-weight: 600; color: var(--text-primary);
  white-space: nowrap;
}
.pr-matrix thead th i {
  display: block; margin-top: 2px;
  font-style: normal; font-size: 11px;
  color: var(--text-secondary); font-weight: 500;
}
.pr-matrix tbody th {
  font-size: 13px; font-weight: 600; color: var(--text-primary);
  white-space: nowrap; font-variant-numeric: tabular-nums;
}
.pr-matrix tbody tr:last-child th,
.pr-matrix tbody tr:last-child td { border-bottom: 0; }
.pr-matrix .pr-feld input { width: 84px; }
/* Der Frühbucher-Preis der Zelle: die zweite Wahrheit derselben Zahl. */
.pr-zelle__eb {
  display: block; margin-top: 4px;
  font-size: 11.5px; color: var(--text-secondary); font-variant-numeric: tabular-nums;
}
/* Das Label IST die Tapfläche (Memory project_tablet_touch_breakpoint) —
   deshalb liegt der 44px-Boden unten auf `.pr-zelle__aus`, nicht auf dem
   Kästchen. Das Kästchen selbst bleibt trotzdem gross genug zum Treffen. */
.pr-zelle__aus {
  display: inline-flex; align-items: center; gap: 6px; margin-top: 4px;
  font-size: 11.5px; color: var(--text-tertiary); cursor: pointer;
}
.pr-zelle__aus input[type="checkbox"] { width: 18px; height: 18px; accent-color: var(--accent); }
.pr-zelle--zu { opacity: .45; }

/* --- Handy: die Zeile bricht, das Feld bleibt gross ------------------------ */
/* Eigener @media-Block NACH den Basis-Regeln (project_css_cascade_mobile).
   Tap-Boden auch in der Tablet-Bruchzone (project_tablet_touch_breakpoint). */
@media (max-width: 720px) {
  .pr-gruppe { padding: 14px; }
  .pr-kopf { padding: 10px 12px; }
  .pr-zeile { align-items: flex-start; }
  .pr-zeile__wort { flex: 1 1 100%; }
  .pr-feld, .pr-schalter, .pr-zeile select { margin-left: 0; }
  .pr-feld input { width: 100%; min-width: 0; }
  .pr-feld { flex: 1 1 140px; }
  .pr-neu .pr-feld { flex: 1 1 100px; }
  .pr-neu .ghost-btn { flex: 1 1 100%; }
  /* Das Preisraster wird zur Kartenliste: vier Spalten passen auf 390px nie,
     und eine quer laufende Seite ist auf dem Telefon ein Fehler. */
  .pr-matrix, .pr-matrix tbody, .pr-matrix tr, .pr-matrix td, .pr-matrix th { display: block; }
  .pr-matrix thead { display: none; }
  .pr-matrix tbody tr {
    padding: 10px 0; border-bottom: 1px solid var(--border);
  }
  .pr-matrix tbody th { padding: 0 0 6px; border: 0; }
  .pr-matrix td { border: 0; padding: 6px 0; display: flex; align-items: center;
    gap: 10px; flex-wrap: wrap; }
  .pr-matrix td::before {
    content: attr(data-tarif); flex: 1 1 120px;
    font-size: 12.5px; color: var(--text-secondary);
  }
  .pr-matrix td .pr-feld { flex: 0 0 auto; }
  .pr-matrix .pr-feld input { width: 92px; }
  /* Frühbucher-Preis und Schalter teilen sich die zweite Zeile der Zelle —
     einzeln untereinander wären 24 Zellen ein endloser Streifen. */
  .pr-zelle__eb { flex: 1 1 120px; margin-top: 0; }
  .pr-zelle__aus { flex: 0 0 auto; margin-top: 0; margin-left: auto; }
}

@media (max-width: 1024px), (pointer: coarse) {
  .pr-feld input { min-height: 44px; }
  .pr-zeile select { min-height: 44px; }
  /* «Ja»/«Nein» sind kurze Wörter — ohne Mindestbreite bliebe die Tapfläche
     schmaler als der Finger. */
  .pr-schalter { min-height: 44px; min-width: 64px; padding: 0 6px; }
  .pr-zelle__aus { min-height: 44px; }
  .pr-zeile__weg { min-height: 44px; min-width: 44px; }
  .pr-kopf .primary-btn, .pr-kopf .ghost-btn { min-height: 44px; }
  .pr-neu .ghost-btn { min-height: 44px; }
}

/* ============================================================
   Patch-Integration — Namensraum lx-agent-; Quelle: docs/design/patch-agent-panel.css
   Der Assistent als Seitenpanel (Owner-Gesetz 2026-08-03).
   ============================================================ */
/* =========================================================================
   Der Assistent als Seitenpanel — Namensraum lx-agent-
   Owner-Gesetz 2026-08-03 (.claude/DAS-SYSTEM.md:408-431)

   «eigentlich muss dieser Chat immer per Seitenpanel — auch kann ich einfach
   rechts Seitenpanel oeffnen und dann ihn auffordern, alles zu machen, anstatt
   dass ich es mache.»

   WARUM DIESER BLOCK GANZ AM ENDE VON style.css STEHT: Er muss das Chat-Blatt
   (docs/design/patch-chat.css — Grundlage §A und Anatomie-Pass §B; bis zum
   21.08. zwei getrennte Blaetter) UEBERSTIMMEN, nicht umgekehrt — der
   Assistent ist im Panel immer schmal, egal wie breit der Bildschirm ist.
   Keine bestehende Regel wird umsortiert oder geaendert; alles hier ist neu
   und traegt eine hoehere Genauigkeit (`.ao--panel .x` schlaegt `.x` auch aus
   einem @media heraus — Memory project_css_cascade_mobile).

   DIE ARBEIT DARUNTER BLEIBT SICHTBAR UND BEDIENBAR. Es gibt hier bewusst
   KEINEN Vorhang: `.modal-backdrop` faengt Klicks ab, dieses Panel nicht.
   Der Inhalt rueckt zur Seite (`padding-right` an der Schale), statt verdeckt
   zu werden — genau der Unterschied zwischen einem Panel und einem Fenster.
   ========================================================================= */
:root { --lx-agent-b: clamp(320px, 34vw, 420px); }

/* --- 1. Der Griff in der Kopfzeile --------------------------------------- */
/* Gleiche Bauart wie Glocke und Konto daneben (docs/design/patch-chrome.css):
   40px-Quadrat, ruhig, ohne Rahmen — kein dritter Knopfstil in einer Zeile. */
.lx-top__agent {
  display: inline-flex; align-items: center; justify-content: center;
  width: 40px; height: 40px; padding: 0; border: 0; border-radius: var(--radius-card);
  background: transparent; color: var(--text-secondary); cursor: pointer;
}
.lx-top__agent:hover { background: rgba(var(--tint-rgb), .06); color: var(--text-primary); }
.lx-top__agent:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* Offen = derselbe getoente Zustand, den auch die Zeichen im Chat tragen
   (patch-chat.css:261) — der Owner sieht am Knopf, dass das Panel steht. */
.lx-top__agent.is-offen { color: var(--accent); background: var(--accent-soft); }
.lx-top__agent-ic { display: inline-flex; width: 19px; height: 19px; }
.lx-top__agent-ic svg { width: 19px; height: 19px; }
/* AM HANDY STEHT ER NICHT IM KOPF. Der Handy-Kopf trägt Identität und Konto
   (Owner-Entscheid 08.08. am Referenzbild); ein Blitz ohne Wort ist genau das
   unerklärte Zeichen, das dort nicht hingehört. Sein Weg ist die Zeile
   `.lx-agent-zeile` in der Seitenleiste, die unten über «Mehr» aufgeht.
   ⚠️ Diese Regel steht HIER und nicht im Kopfzeilen-Block
   (docs/design/patch-chrome.css):
   `.lx-top__agent` wird oben in diesem Block ohne @media auf `inline-flex`
   gesetzt, und bei gleicher Spezifität gewinnt die spätere Regel — eine
   Abschaltung weiter oben wäre wirkungslos gewesen. Genau das ist beim ersten
   Bild passiert: der Blitz stand trotz `display:none` noch im Kopf
   (Hausgesetz «Mobile-@media NACH der Basis»). */
@media (max-width: 900px) {
  .lx-top__agent { display: none; }
}

/* --- 2. Der Rahmen rechts ------------------------------------------------ */
.lx-agent {
  position: fixed; top: 0; right: 0; bottom: 0;
  width: var(--lx-agent-b);
  z-index: 95;                       /* ueber dem FAB (90), unter Fenster (100+) */
  display: flex; flex-direction: column;
  background: var(--surface-1);
  border-left: 1px solid var(--border);
  box-shadow: -26px 0 60px -34px rgba(0, 0, 0, .8);
  overscroll-behavior: contain;
  overflow: hidden;
}
/* `display:flex` schlaegt sonst das hidden-Attribut — ohne diese Zeile stuende
   das Panel offen, sobald es einmal gebaut ist. */
.lx-agent[hidden] { display: none; }

/* Die Arbeit rueckt zur Seite, statt zu verschwinden. */
body.lx-agent-offen .app-shell { padding-right: var(--lx-agent-b); }

/* --- 3. Der Chat-Kern im Panel ------------------------------------------- */
/* Er ist derselbe wie vorher — nur immer schmal. Was am Handy schon galt
   (eine Spalte, der Live-Kontext als Blatt darunter), gilt hier auf jeder
   Bildschirmbreite: Erscheinung, nicht zweite Bauart. */
.ao.ao--panel {
  display: flex; flex-direction: column; gap: 0;
  flex: 1 1 auto; min-height: 0; overflow-y: auto;
}
.ao--panel .ao-raster {
  grid-template-columns: minmax(0, 1fr);
  grid-template-rows: minmax(0, 1fr) auto;
  align-items: stretch; gap: 0;
  flex: 1 1 auto; min-height: 0;
}
/* Kein Rahmen im Rahmen: das Panel ist die Kante, nicht die Spalte darin. */
.ao--panel .ao-chat {
  border: 0; border-radius: 0; background: transparent;
  min-height: 0; height: 100%;
}
.ao--panel .ao-verlauf { max-height: none; min-height: 0; }
/* Der Kopf des Panels — auch im gesperrten und im kaputten Zustand, wo er
   ohne die Chat-Spalte dasteht. */
.ao--panel > .ao-chat__kopf { flex: 0 0 auto; }
.ao--panel .ao-chat__zu { margin-left: auto; }

/* Der Live-Kontext ist im Panel immer das Blatt am Fuss — dieselben Werte wie
   die Handy-Gestalt (patch-chat.css:420-437), hier ohne @media, weil die
   Breite des Panels nicht an der Breite des Fensters haengt. */
.ao--panel .ao-kontext {
  position: static; max-height: none; padding: 0; gap: 0;
  border-radius: 0; border-left: 0; border-right: 0; border-bottom: 0;
}
.ao--panel .ao-kontext__kopf { display: flex; align-items: center; gap: 10px; padding: 13px 15px; min-height: 44px; }
.ao--panel .ao-kontext__kopf h2 { flex: 1 1 auto; }
.ao--panel .ao-kontext__schalter {
  display: grid; place-items: center;
  width: 44px; height: 44px; margin: -8px -10px -8px 0; padding: 0;
  background: transparent; border: 0; border-radius: var(--radius-card);
  color: var(--text-tertiary); cursor: pointer;
}
.ao--panel .ao-kontext__schalter svg { width: 18px; height: 18px; transition: transform var(--transition); }
.ao--panel .ao-kontext__leib { display: none; padding: 0 15px 15px; }
.ao--panel .ao-kontext.is-offen .ao-kontext__kopf { border-bottom: 1px solid var(--border); }
.ao--panel .ao-kontext.is-offen .ao-kontext__kopf h2 { color: var(--text-primary); }
.ao--panel .ao-kontext.is-offen .ao-kontext__schalter { color: var(--accent); }
.ao--panel .ao-kontext.is-offen .ao-kontext__schalter svg { transform: rotate(180deg); }
.ao--panel .ao-kontext.is-offen .ao-kontext__leib { display: grid; padding-top: 14px; }

/* Die drei gemessenen Punkte am Fuss bleiben — im Panel untereinander statt
   nebeneinander, sonst brechen sie mitten im Wort. */
.ao--panel .ao-lage { flex: 0 0 auto; border-radius: 0; border-left: 0; border-right: 0; border-bottom: 0; }
.ao--panel .ao-lage__punkt, .ao--panel .ao-lage__detail { flex-basis: 100%; }

/* Gesperrt und kaputt: der Satz steht im Panel, nicht am Rand geklebt. */
.ao--panel > .ao-zu,
.ao--panel > .ao-zugang { margin: 14px 15px; }
.ao--panel > .load-error,
.ao--panel > .empty-state { margin: 14px 15px; }

/* --- 4. Unter 900px: ein Blatt ueber die volle Breite --------------------- */
/* Dieselbe Grenze, an der auch die Schale umschaltet
   (docs/design/patch-chrome.css, `@media (min-width: 901px)`), und dieselbe Gestalt wie das Glocken-Blatt.
   Geschlossen wird es mit dem Zeichen in seinem Kopf — es gibt keinen zweiten
   Weg hinaus, wenn das Panel den ganzen Bildschirm fuellt. */
@media (max-width: 900px) {
  .lx-agent {
    left: 0; width: auto; border-left: 0;
    padding-top: var(--sat); padding-bottom: var(--sab);
  }
  body.lx-agent-offen .app-shell { padding-right: 0; }
}

/* Am grossen Bildschirm weicht der «+ Neu»-Knopf aus — sonst laege er auf dem
   Panel (docs/design/grund.css, Regel `.qc`, right: 18px). */
@media (min-width: 901px) {
  body.lx-agent-offen .qc { right: calc(18px + var(--lx-agent-b)); }
}

/* ============================================================
   Patch-Integration — Namensraum lx-zweite-reihe; Quelle: docs/design/patch-zweite-reihe.css
   Gefaehrliche Handlungen hinter einem bewussten zweiten Schritt (Owner 01.08.).
   ============================================================ */
/* Die zweite Reihe — gefährliche Handlungen hinter einem bewussten Schritt.
   Owner 01.08.: «ein Klick, und dann ist es weg» · «es gehört aus der ersten
   Reihe». Der Ausklapper ist absichtlich das leiseste Element der Zeile: kein
   Rahmen, kein Flächenton, nur drei Punkte in der Tertiärfarbe. Er soll
   gefunden werden, wenn man ihn sucht — nicht auffallen, wenn man es nicht tut.

   Keine box-shadow-Ebene: die Referenz trennt mit dunkler Naht, nie mit Hof
   (Stil-Wächter, Owner-Befund 03.08. «die ganze App hat kein Glüh»). */
.lx-zweite-reihe { position: relative; display: inline-block; }

.lx-zweite-reihe__auf {
  list-style: none; cursor: pointer; user-select: none;
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 44px; min-height: 44px; padding: 0 10px;
  border-radius: var(--radius-card); color: var(--text-tertiary);
  font-size: 17px; line-height: 1; letter-spacing: .08em;
}
.lx-zweite-reihe__auf::-webkit-details-marker { display: none; }

/* W6.1 «Beschriftungs-Pass»: das Wort neben den Punkten. Es ist bewusst klein
   und in derselben leisen Farbe — der Ausklapper soll gefunden werden, nicht
   um Aufmerksamkeit mit «Speichern» konkurrieren. Ohne dieses Wort war der
   Griff für einen Laien unsichtbar (Bericht C, Klasse D1). Das Sperrmass der
   Punkte (.08em) gilt für das Wort nicht — gesperrte Fliessschrift liest sich
   schlecht. */
.lx-zweite-reihe__wort {
  margin-left: 7px; font-size: 13px; letter-spacing: 0; font-weight: 500;
}
.lx-zweite-reihe__auf:hover { color: var(--text-secondary); background: var(--surface-2); }
.lx-zweite-reihe__auf:focus-visible {
  outline: none; box-shadow: 0 0 0 3px rgba(var(--accent-rgb), .45);
}
.lx-zweite-reihe[open] .lx-zweite-reihe__auf { color: var(--text-secondary); background: var(--surface-2); }

/* Das Fach SCHWEBT NICHT — es klappt im Fluss auf und nimmt die nächste Zeile.
   Zwei Anläufe am 04.08. sind an der Lage gescheitert, beide vom Wächter
   gefunden: nach oben ausgeklappt lag es in einer Kopfzeile über dem
   Seitenrand (Playwright: «element is outside of the viewport»); rechtsbündig
   ragte es links aus dem Bild, sobald der Ausklapper nahe am linken Rand sass
   (gemessen x=-72). Beides sind Randfälle einer schwebenden Schicht, und
   beide verschwinden, wenn nichts schwebt: kein z-index, kein Viewport-Rand,
   keine Engine-Unterschiede. Dass die Zeile beim Öffnen aufgeht, ist hier
   sogar richtig — es macht sichtbar, dass ein zweiter Schritt begonnen hat. */
.lx-zweite-reihe[open] { width: 100%; flex: 1 0 100%; }
/* FLACH STATT KASTEN (Owner «Widget», 2026-08-13): das Fach schwebte zwar nie
   (siehe oben), sah aber aus wie ein aufgeklapptes Widget — Rahmen, Radius 12
   und ein hellerer Grund. Es ist die zweite Reihe DERSELBEN Zeile, also traegt
   es die Haarlinie, die eine zweite Reihe traegt: eine Linie oben, sonst
   nichts. 11px = 10px + die 1px des alten Rahmens. */
.lx-zweite-reihe__fach {
  margin-top: 8px; padding: 11px 0 0;
  background: transparent; border: 0; border-top: 1px solid var(--border); border-radius: 0;
  display: flex; flex-direction: column; gap: 8px; align-items: stretch;
  text-align: left;
}
.lx-zweite-reihe__hinweis {
  margin: 0; font-size: 12.5px; line-height: 1.45; color: var(--text-tertiary);
}
.lx-zweite-reihe__fach > button { width: 100%; justify-content: center; }

/* Die Schublade verschwindet mit ihrem Inhalt. Die Fenster schalten ihren
   Löschen-Knopf per `hidden` frei; ohne diese Regel bliebe ein Ausklapper
   stehen, der ein leeres Fach öffnet. Steuerung im CSS statt in acht
   Flächen — acht Gelegenheiten weniger, eine zu vergessen. */
.lx-zweite-reihe:has(> .lx-zweite-reihe__fach > button[hidden]) { display: none; }

/* ===========================================================================
   Patch-Integration — Namensraum lx-blatt; Quelle: docs/design/patch-blatt.css
   =========================================================================== */
/* ===========================================================================
   DAS BLATT — was am Handy nicht dauernd im Bild stehen muss
   Bauteil: public/src/components/blatt.js
   ---------------------------------------------------------------------------
   Eine Karte, die von unten in ihren Behälter hochfährt, ein Fach zeigt und
   wieder verschwindet. Sie liegt IM Behälter (absolut gegen ihn), nicht über
   der Seite: die Daumenleiste der App bleibt erreichbar, und die z-Schichten
   der App (Dialog 100, Toast 200) werden gar nicht erst berührt. Der Behälter
   trägt dafür `position: relative`.

   NEUTRAL: hier steht nur die Karte. Was eine Fläche IN ihr Fach legt,
   gestaltet die Fläche in ihrem eigenen Block — der Rechner tut das unter
   `.lx-blatt__fach .cp__leiste` / `.kf-*` in patch-konfigurator.css.

   Herkunft: bis 08.08. hiess das `cp__blatt-menu`/`cp__menu-*` und wohnte im
   Cockpit. Die Pool-Fläche braucht dieselbe Bedienung; zwei Muster für
   dieselbe Geste sind die Doppelspurigkeit, die am ganzen System gerügt wird.
   =========================================================================== */
.lx-blatt {
  position: absolute; inset: 0; z-index: 5;
  display: flex; flex-direction: column; justify-content: flex-end;
}
.lx-blatt[hidden] { display: none; }
.lx-blatt__grund { position: absolute; inset: 0; background: rgba(0, 0, 0, .5); }
.lx-blatt__karte {
  position: relative;
  max-height: 84%;
  display: flex; flex-direction: column;
  border-top: 1px solid var(--line-strong, var(--border));
  border-radius: var(--radius-card) var(--radius-card) 0 0;
  background: var(--surface);
  box-shadow: 0 -18px 44px -18px rgba(0, 0, 0, .8);
  animation: lx-blatt-hoch var(--dur, 180ms) var(--ease, cubic-bezier(.22, 1, .36, 1));
}
@keyframes lx-blatt-hoch { from { transform: translateY(16px); opacity: .35; } }
.lx-blatt__kopf {
  flex: 0 0 auto;
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 12px 14px 10px;
  border-bottom: 1px solid var(--border);
}
.lx-blatt__kopf h2 {
  margin: 0; min-width: 0;
  font-size: 15px; font-weight: 650; letter-spacing: -.01em; color: var(--text-primary);
}
.lx-blatt__x {
  flex: 0 0 auto; display: grid; place-items: center;
  width: 44px; height: 44px;
  border: 1px solid var(--border); border-radius: var(--radius-button);
  color: var(--text-secondary); background: var(--surface-2);
  cursor: pointer;
}
.lx-blatt__x svg { width: 18px; height: 18px; }
.lx-blatt__fach {
  flex: 1 1 auto; min-height: 0; overflow: auto;
  padding: 12px 14px calc(16px + var(--sab, 0px));
}
.lx-blatt__fach[hidden] { display: none; }
/* Die Handlungen im Blatt sind Zeilen MIT Wort — nie wieder ein wortloser
   Knopf (Owner-Befund 2 vom 08.08.: «einsamer ✓ ohne Wort»). */
.lx-blatt__fach--aktionen { display: grid; gap: 8px; }


/* Wo ein Blatt haengt, wenn sein Behaelter zu klein dafuer ist, steht in
   docs/design/patch-telefon-griffe.css (`.lx-blatt-wirt`) — dort, wo auch die
   Griffe stehen, die es oeffnen. Es ist derselbe Namensraum und dasselbe
   Bauteil; getrennt liegt es nur, damit dieses Blatt EINE Definition je
   Selektor behaelt (scripts/_stil_einmalig_test.mjs). */

/* ===========================================================================
   Patch-Integration — Namensraum cp-/kf-; Quelle: docs/design/patch-konfigurator.css
   =========================================================================== */
/* ===========================================================================
   COCKPIT — eine Arbeitsfläche, die auf den Bildschirm passt
   Bauteil: public/src/components/cockpit.js · Owner-Auftrag 2026-08-05
   ---------------------------------------------------------------------------
   Das Gesetz: die SEITE scrollt nicht. Zonen und Blätter scrollen innen; was
   nicht hineinpasst, wird ein Blatt weiter rechts, nie mehr Höhe.

   Verhältnis zu DESIGN.md: Farbe, Schrift und Schrift-Floor (11px) gelten
   unverändert — jeder Wert unten stammt aus dem Token-Block. Was das Cockpit
   ergänzt, ist TIEFE: die Fläche ist ein Gerät mit Kante, Kopf und Fuss, damit
   das Auge sofort weiss, wo es steht («Dann sieht man immer gleich, wo was
   ist»). Das ist die begründete Ausnahme vom Satz «Border UM Panels» — sie
   gilt für .cp und seine Zonen, nicht für Panels im Rest der App.
   =========================================================================== */

.cp {
  /* --cp-oben setzt das Bauteil (Abstand des Cockpits zur Fensteroberkante).
     Ohne JS bleibt der Vorgabewert — dann ist die Fläche etwas zu hoch, aber
     nie kaputt. */
  /* Der Abzug unten deckt den Seitenrand der Schale MIT ab. Vorher blieben
     darunter ein paar Pixel Seitengrund sichtbar, und es sah aus, als läge
     etwas hinter dem Fuss (Owner-Befund 05.08. am Bild). */
  /* ⚠️ Der Abzug deckt den Seitenrand UND die sichere Zone mit ab. Zweimal
     stand darunter noch Seitengrund durch, und es sah aus, als läge etwas
     hinter dem Fuss (Owner-Befund, zweimal gemeldet). `overflow:hidden` unten
     schneidet zusätzlich alles ab, was ein Kind über die Kante schiebt. */
  /* --cp-unten ist der Platz, den die Seite UNTER der Fläche reserviert
     (Seitenrand, am Handy die Daumenleiste); das Bauteil misst ihn, weil ein
     fester Wert hier auf der Hälfte der Bildschirme falsch wäre. Ohne JS greift
     der bisherige Rückfallwert und alles bleibt wie gehabt. Die 40 px daneben
     sind die gewollte Luft der Schale, keine Reserve — sie bleiben. */
  height: calc(100svh - var(--cp-oben, 96px) - 40px - var(--cp-unten, var(--sab, 0px)));
  margin-bottom: 0;
  min-height: 540px;
  display: flex;
  /* ⚠️ FLEX, nicht Grid — teuer gelernt (05.08., drei Fehlversuche).
     Als Grid mit `minmax(0,1fr)` wuchs die Werk-Zeile trotzdem auf ihre
     Inhaltshöhe (gemessen: 1202px in einer 800px-Fläche), und Ausgabe und Fuss
     samt Total lagen ausserhalb der sichtbaren Fläche. Weder minmax(0,1fr) noch
     min-height am Item noch overflow:hidden haben das gehalten.
     `flex: 1 1 0` + `min-height: 0` ist die Mechanik, die genau dafür gebaut
     ist: die Mitte bekommt exakt den Rest und darf ihn nie überschreiten.
     Kopf, Wegweiser, Ausgabe und Fuss geben nie Höhe her (flex: 0 0 auto). */
  flex-direction: column;
  align-items: stretch;   /* sonst schrumpfen Kopf, Ausgabe und Fuss auf ihren
                             Inhalt und schweben mittig (gesehen 05.08.) */
  overflow: hidden;
  border: 1px solid var(--line-strong, var(--border));
  border-radius: var(--radius-card);
  background: var(--surface-1);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .05),
    0 1px 2px rgba(0, 0, 0, .3),
    0 18px 44px -20px rgba(0, 0, 0, .65);
}

/* ---- Die Namenskollision, entschärft ------------------------------------- */
/* ⚠️ `.cp` ist ZWEIMAL vergeben: Befehls-Palette (command-palette.js:136) und
   diese Schale (cockpit.js:109). Die Palette ist ein Vollbild-Overlay —
   `position: fixed; inset: 0; z-index: 400` (docs/design/grund.css, Regel `.cp`)
   plus die Fenster-Geometrie aus den --cp-*-Variablen
   (docs/design/patch-handy.css §1). Die Schale erbte
   beides mit und lag damit fix über dem ganzen Bildschirm auf z 400. DAHINTER
   verschwanden: jeder Bestätigungs-Dialog (.modal-backdrop, z 100,
   docs/design/grund.css), jeder Toast (z 200, docs/design/grund.css), die Topbar (z 30) und die Seitenleiste. «Senden»,
   «Löschen» und «Entwurf zurücksetzen» stellten eine Frage, die niemand sah;
   jede Fehler- und Erfolgsmeldung verschwand (FORENSIK B0, gemessen 07.08.).

   Dieser Block neutralisiert NUR die Overlay-Eigenschaften und steht deshalb
   NACH beiden .cp-Basisblöcken. Die Palette trägt kein `data-cockpit` — sie
   bleibt Pixel für Pixel unberührt.

   HÖHE steht bewusst NICHT hier: sie kommt aus dem Cockpit-Block darüber und
   aus den @media-Blöcken (12763, 14952). Ein Wert an dieser Stelle hätte die
   höhere Spezifität und würde beide aushebeln.
   Der saubere Umbau auf einen eigenen Klassennamen ist MASTERPLAN E1d. */
.cp[data-cockpit] {
  /* `relative` statt `static` seit 08.08.: das Blatt (`.lx-blatt`)
     spannt sich absolut gegen diese Fläche und bleibt damit IM Cockpit.
     `relative` ist keine Overlay-Eigenschaft — die Palette bleibt unberührt,
     und die Neutralisierung von `fixed`/`inset`/`z-index` wirkt unverändert. */
  position: relative;
  inset: auto;
  width: auto;
  z-index: auto;
}

/* ===========================================================================
   EINGEBETTET — die Fläche IST die Fläche, auch am Rechner (31.08.2026)
   ---------------------------------------------------------------------------
   OWNER-WORTLAUT (31.08., diktiert): «[Wenn ich] auf den Offertenrechner gehe,
   ist [er] immer noch als Fenster wie ein Widget, anstatt dass es die gesamte
   Fläche einfach übernimmt und dazu gehört zum System. Es ist immer noch wie
   etwas, das einfach draufgeklebt ist, und das kotzt mich an.»

   GEMESSEN, bevor eine Zeile entstand (scratchpad/w3c-vorher.txt, neun echte
   Gerätebreiten auf der Bühne aus scripts/handy-buehne.mjs):
     390 · 430 · 768 · 1024 px   randlos, volle Fläche, radius 0, kein Rahmen
     1280 px   980×540 @268,174 · radius 14 · Rahmen 1 · Schatten · SEITE
               SCROLLT 46 px
     1366 px   1062×540 @270,174 · … · SEITE SCROLLT 86 px
     1440 px   1132×543 @272,174 · … · 73 px Seitengrund darunter
     1680 px   1360×702 @278,174 · … · 74 px darunter
     1920 px   1588×722 @284,174 · … · 74 px darunter
   Das Bild, das der Owner meint, entsteht also GENAU ab 1280 px — und die
   Fassung, die er will, ist die, die auf seinem Handy längst steht.

   DIE WURZEL, dreiteilig, und jeder Teil ist gemessen:
     1. Der Kasten selbst: Rundung, Kante, Schatten und die 40 px «Luft der
        Schale» im `.cp`-Basisblock darüber.
     2. Die Reiterzeile darüber trägt `margin-bottom: 18px` (#subnav) — das
        ist die Lücke zwischen Reiter-Unterkante (156 px) und Flächenoberkante
        (174 px).
     3. Die Schale reserviert unten `calc(32px + var(--boden-abstand))` und
        seitlich `var(--lx-rand)` = clamp(28px, 2.5vw, 56px)
        (docs/design/grund.css `.main-shell`) — das ist der Seitengrund rechts
        und unter der Fläche.

   DIE ALTE ENTSCHEIDUNG IST ÜBERSTIMMT. Der Kopf dieses Blattes nennt «die
   Fläche ist ein Gerät mit Kante» als begründete Ausnahme vom Satz «Border UM
   Panels» (05.08.). Für eine EINGEBETTETE Fläche gilt sie ab heute nicht mehr
   — der Owner-Wortlaut oben ist jünger (fail-closed: die neuere ausdrückliche
   Owner-Korrektur schlägt). Für jede andere `.cp`-Fläche bleibt sie in Kraft.

   ⚠️ ES IST EINE WAHL, KEIN NEUER STANDARD. `components/cockpit.js` hat einen
   zweiten Nutzer: `views/kunde-portal.js` (Besucher-Auftritt, Owner 06.08.:
   «Kundenportal bleibt, wie es ist»). Es setzt `spec.einbau` nicht, trägt
   damit weder `cp--einbau` noch `lx-einbau` — und bleibt Pixel für Pixel, wie
   es ausgeliefert ist. Beweis: derselbe Breiten-Lauf über `/k`.

   DAS INNERE GESETZ BLEIBT UNBERÜHRT: die Seite scrollt nicht, Zonen und
   Blätter scrollen innen. `body.lx-einbau { overflow: hidden }` macht genau
   das mechanisch — und heilt nebenbei den Befund oben, dass bei 1280 und
   1366 px die Seite sehr wohl scrollte (das `min-height: 540px` des
   Basisblocks schlug dort die Höhenrechnung).

   WARUM `@media (min-width: 1081px)`: darunter gilt die Handy-Anatomie
   (`body.lx-werkflaeche`, ab Zeile 606) — sie tut dasselbe, ist seit dem
   08.08. bewiesen und wird hier nicht angefasst. `.cp.cp--einbau` trägt zwei
   Klassen und schlägt damit den `.cp`-Block der Handy-Anatomie, verliert aber
   gegen `body.lx-werkflaeche .cp` — auf einem Touch-Gerät gilt also weiter,
   was dort steht.
   =========================================================================== */
@media (min-width: 1081px) {
  /* Die Seite scrollt nicht — das Gesetz der Schale, mechanisch. Derselbe
     Riegel, den die Handy-Anatomie seit dem 08.08. setzt (Zeile 653). */
  body.lx-einbau { overflow: hidden; }
  /* 2 · Bündig unter der Reiterzeile. NUR ihr Abstand fällt weg, und nur
     solange diese Fläche steht — die Kopfzeile darüber bleibt unberührt
     (sie bricht mit `margin: -20px calc(-1 * var(--lx-rand))` selbst aus und
     würde von einer Änderung an `.main-shell` seitlich verschoben). */
  body.lx-einbau #subnav { margin-bottom: 0; }
  /* 3a · Der Bodenrand der Schale. Ohne diese Zeile stünde die Fläche zwar
     bündig, die SEITE wäre aber 32 px höher als das Fenster — und `--cp-unten`
     (das Bauteil misst die Polster seiner Vorfahren) zöge dieselben 32 px ein
     zweites Mal von der Höhe ab: ein Streifen Seitengrund unter dem Total,
     genau der Fehler, den der Owner am Handy zweimal gemeldet hat. */
  body.lx-einbau .main-shell { padding-bottom: 0; }

  .cp.cp--einbau {
    /* 1 · Kein Gerät mit Kante mehr. */
    border: 0;
    border-radius: 0;
    box-shadow: none;
    /* Die 40 px «Luft der Schale» aus dem Basisblock fallen weg: die Fläche
       reicht von ihrer eigenen Oberkante bis zum Fensterrand. `--cp-unten` ist
       durch die Zeile darüber 0 und bleibt trotzdem in der Rechnung — auf
       einem Gerät mit sicherer Zone (`--sab`) trägt es sie. */
    height: calc(100svh - var(--cp-oben, 96px) - var(--cp-unten, var(--sab, 0px)));
    /* Das `min-height: 540px` des Basisblocks war die Ursache des Seiten-
       Scrollens auf 1280 und 1366 px (gemessen: 46 bzw. 86 px). Eine Fläche,
       die sich weigert zu schrumpfen, bricht das Gesetz, für das sie gebaut
       wurde. */
    min-height: 0;
    /* 3b · Volle Inhaltsbreite: der seitliche Rand der Schale wird
       zurückgenommen — Zeichen für Zeichen die Ausbruch-Form, die die
       Kopfzeile des Hauses seit je benutzt (`.lx-top`,
       docs/design/patch-chrome.css:229). `--lx-rand` ist derselbe Wert, den
       `.main-shell` als seitliches Polster setzt. */
    margin: 0 calc(-1 * var(--lx-rand, 28px));
  }
}

/* ---- Kopf ---------------------------------------------------------------- */
.cp__kopf {
  flex: 0 0 auto;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: 18px;
  padding: 14px 18px;
  border-bottom: 1px solid var(--border);
  background: linear-gradient(180deg, var(--surface-2), var(--surface));
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .045);
}
.cp__marke {
  display: grid; place-items: center;
  width: 34px; height: 34px;
  border: 1px solid var(--accent-line);
  border-radius: var(--radius-button);
  color: var(--accent-strong);
  background: var(--accent-soft);
  font-size: 11px; font-weight: 700; letter-spacing: .02em;
}
.cp__titel { min-width: 0; }
.cp__kicker {
  margin: 0 0 3px;
  font-size: 11px; font-weight: 600; letter-spacing: .07em; text-transform: uppercase;
  color: var(--text-tertiary);
}
.cp__kopf h1 {
  margin: 0;
  font-size: 20px; font-weight: 650; letter-spacing: -.01em; line-height: 1.15;
  color: var(--text-primary);
}
.cp__hinweis {
  margin: 4px 0 0;
  font-size: 12.5px; line-height: 1.45; color: var(--text-secondary);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.cp__aktionen { display: flex; align-items: center; gap: 8px; }
.cp__knopf {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  min-height: 36px; padding: 0 13px;
  border: 1px solid var(--border);
  border-radius: var(--radius-button);
  color: var(--text-primary);
  background: var(--surface-2);
  font: inherit; font-size: 12px; font-weight: 650; letter-spacing: .1em; text-transform: uppercase;
  cursor: pointer;
  transition: background var(--dur-fast, 120ms), border-color var(--dur-fast, 120ms);
}
.cp__knopf:hover:not(:disabled) { background: var(--surface-3); border-color: var(--line-strong, var(--border)); }
.cp__knopf:active:not(:disabled) { transform: scale(.985); }
/* Eine Kopfaktion, die gerade nicht traegt, sieht auch so aus — dieselbe Form
   wie `.primary-btn:disabled` (style.css:539). Ohne diese Zeile waere ein
   gesperrter Griff optisch nicht von einem offenen zu unterscheiden
   (Kundenportal: «Prüfen & buchen» ohne Standort). */
.cp__knopf:disabled { opacity: .55; cursor: not-allowed; }
.cp__knopf--primaer {
  border-color: transparent; color: var(--on-accent); background: var(--accent-fill); font-weight: 650;
}
.cp__knopf--primaer:hover:not(:disabled) { background: var(--accent-bright); }
.cp__ic { display: grid; place-items: center; width: 17px; height: 17px; flex: 0 0 17px; }
.cp__ic svg { width: 100%; height: 100%; }

/* ---- Wegweiser: nur auf schmalen Schirmen ------------------------------- */
.cp__zonenwahl { display: none; flex: 0 0 auto; }

/* ---- Werk: die drei Spalten --------------------------------------------- */
.cp__werk {
  flex: 1 1 0;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 1px;
  min-height: 120px;
  /* ⚠️ overflow:hidden ist Pflicht, nicht Kosmetik: ohne es blähen die Zonen
     das Werk über seine Grid-Zeile hinaus auf (gemessen 05.08.: 1202px statt
     der zugeteilten ~800px), und der Fuss samt Total wird unten aus der Fläche
     geschoben. Gescrollt wird INNEN, in .cp__zoneleib und .cp__blatt. */
  overflow: hidden;
  background: var(--border);          /* die 1px-Fugen zwischen den Zonen */
}
.cp[data-spalten="2"] .cp__werk:has(.cp__zone--links)  { grid-template-columns: clamp(220px, 17vw, 290px) minmax(0, 1fr); }
.cp[data-spalten="2"] .cp__werk:has(.cp__zone--rechts) { grid-template-columns: minmax(0, 1fr) clamp(230px, 18vw, 310px); }
.cp[data-spalten="3"] .cp__werk { grid-template-columns: clamp(210px, 16vw, 280px) minmax(0, 1fr) clamp(230px, 18vw, 310px); }

.cp__zone, .cp__buehne {
  display: grid;
  grid-template-rows: auto minmax(0, 1fr);
  min-width: 0; min-height: 0;
  background: var(--bg);
}
.cp__zonekopf {
  display: block;                     /* schmale Spalte: Titel über Hinweis */
}
.cp__buehnekopf {
  display: flex; align-items: flex-start; justify-content: space-between; gap: 14px;
}
.cp__zonekopf, .cp__buehnekopf {
  padding: 10px 15px 9px;
  border-bottom: 1px solid var(--border);
  background: var(--surface);
}
.cp__zonekopf h2, .cp__buehnekopf h2 {
  margin: 0; font-size: 13px; font-weight: 650; letter-spacing: .01em; color: var(--text-primary);
}
.cp__buehnekopf p {
  margin: 4px 0 0; font-size: 11.5px; line-height: 1.4; color: var(--text-tertiary);
}
/* Der erklärende Satz der Seitenzonen steht als Zeigehilfe am Titel statt als
   eigene Zeile: einmal gelesen, danach kostet er nur Höhe — und genau die
   fehlte der rechten Spalte (gemessen: 25px). */
.cp__zonekopf p { display: none; }
.cp__buehnetitel { min-width: 0; }
.cp__zoneleib { padding: 11px 14px; overflow: auto; min-height: 0; }

/* ---- Der Umschalter der Bühne ------------------------------------------- */
.cp__wahl {
  display: flex; gap: 3px; flex: 0 0 auto;
  padding: 3px;
  border-radius: var(--radius-card);
  background: var(--surface-inset);
}
.cp__wahlknopf {
  display: inline-flex; align-items: center; gap: 6px;
  min-height: 30px; padding: 0 11px;
  border: 0; border-radius: var(--radius-card);
  color: var(--text-secondary);
  background: transparent;
  font: inherit; font-size: 12px; font-weight: 600;
  cursor: pointer;
  transition: color var(--dur-fast, 120ms), background var(--dur-fast, 120ms);
}
.cp__wahlknopf:hover { color: var(--text-primary); }
.cp__wahlknopf[aria-selected="true"] {
  color: var(--accent-strong);
  background: var(--accent-soft);
  box-shadow: inset 0 0 0 1px var(--accent-line);
}

/* ---- Das Deck: die Blätter liegen nebeneinander -------------------------- */
.cp__deck {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 100%;
  min-height: 0;
  overflow-x: auto; overflow-y: hidden;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
  overscroll-behavior-x: contain;
}
/* … aber nur, solange es wirklich Blätter zum Wischen gibt. Ein Deck mit EINEM
   Blatt (Konfigurator, Kundenportal) kann nichts scrollen — `contain` machte
   die ganze Bühne dann zur Sperrzone: ein Finger darauf bewegte auch die ZONE
   nicht mehr weiter, obwohl das Deck selbst nichts zu bieten hatte (gemessen
   07.08. auf 390 px: werk.scrollLeft 360 → 360; mit `auto` 360 → 720). Mehrere
   Blätter behalten die Sperre — dort ist sie richtig, sonst risse ein Wisch
   übers letzte Blatt gleich die Zone mit. */
.cp__deck:not(:has(.cp__blatt:nth-child(2))) { overscroll-behavior-x: auto; }
.cp__deck::-webkit-scrollbar { display: none; }
.cp__blatt {
  scroll-snap-align: start;
  min-width: 0; min-height: 0;
  padding: 14px 16px;
  overflow: auto;
}
/* Ein Blatt, das die Karte trägt, will keinen Rand und keinen eigenen Scroll. */
.cp__blatt--voll { padding: 0; overflow: hidden; display: grid; place-items: center; }

/* Die Karte nimmt im Cockpit die Bühne ein. Ihr Vorgabe-Deckel von 780px
   stammt aus dem Portal-Panel und liesse hier zwei Drittel der Fläche leer. */
.cp__blatt .bs-karte { max-width: none; width: 100%; height: 100%; margin: 0; }

/* Innen-Scroll-Affordance (DESIGN.md §7): solange unten mehr folgt, blendet
   die Fläche aus — sonst sieht eine hart abgeschnittene Zeile wie ein Ende aus. */
.cp .is-mehr,
.cp__zoneleib.is-mehr, .cp__blatt.is-mehr, .cp__ausgabe.is-mehr {
  -webkit-mask-image: linear-gradient(180deg, #000 calc(100% - 34px), transparent);
  mask-image: linear-gradient(180deg, #000 calc(100% - 34px), transparent);
}

/* ---- Ausgabe: das Ergebnis bleibt immer im Bild -------------------------- */
.cp__ausgabe {
  /* Ohne gezogenen Wert nimmt das Ergebnis so viel, wie es braucht, aber
     höchstens ein Drittel — sonst drückt es die Arbeitsfläche zusammen, und
     beide Spalten laufen über (gemessen: je ~65px). Wer zieht, überschreibt.
     ⚠️ `flex: 0 1 auto`, nie `0 0 auto`: mit shrink 0 nahm sich das Ergebnis
     bei knapper Schale (1280×800: Schale 540px, Festteile 316px) seine vollen
     34svh und schob Fuss samt TOTAL aus Schale und Fenster (Bedien-Rundgang
     08.08., WebKit und Chromium: fuss.top=790 bei Schalenkante 685,
     totalSichtbar=false). Das Ergebnis KANN innen scrollen — der Fuss nicht.
     ⚠️ EIN max-height: bis 08.08. stand nach dem var()-Deckel ein zweites
     `max-height: 34svh` — gleiche Spezifität, später, gewann immer. Der
     Griff-Zug oberhalb von 34svh war damit ein toter Regler.
     ⚠️ 25.08.2026: dass «höchstens ein Drittel» hier den BILDSCHIRM misst und
     nicht die Schale, ist am Offerten-Rechner gemessen und dokumentiert —
     patch-konfigurator-w10.css, Block W10-2, samt der Zahlenreihe und samt dem
     Grund, warum der naheliegende Griff dagegen ZURÜCKGENOMMEN wurde (er holt
     Owner-Befund C7 zurück). Diese Grundregel bleibt unverändert. */
  flex: 0 1 auto;
  height: var(--cp-ausgabe-h, auto);
  max-height: var(--cp-ausgabe-h, 34svh);
  min-height: 90px;
  padding: 12px 16px;
  border-top: 1px solid var(--border);
  background: var(--surface);
  overflow: auto;
}

/* ---- Fuss ---------------------------------------------------------------- */
/* Der Griff zwischen Arbeitsfläche und Ergebnis. Owner 05.08.: «man kann den
   oberen Bereich vertikal grösser machen, verkleinern». */
.cp__griff {
  flex: 0 0 auto;
  height: 9px; cursor: row-resize;
  background: var(--surface-1);
  border-top: 1px solid var(--border);
  position: relative;
}
.cp__griff::after {
  content: ''; position: absolute; left: 50%; top: 50%;
  width: 44px; height: 3px; margin: -1.5px 0 0 -22px;
  border-radius: 2px; background: var(--border);
}
/* DIE FANGFLÄCHE OHNE DIE FORM. Der Balken IST 9 px — das ist seine Gestalt
   (`cursor: row-resize`), und ein 24 px dicker grauer Streifen quer durch die
   Fläche wäre kein besserer Griff, sondern ein Band. Aber 9 px sind zu wenig
   zum Treffen (Maus-Boden 24). Also wächst nur die FANGFLÄCHE, mittig über
   dem Balken, unsichtbar: dieselbe Bauart, die jeder Editor seinen Teilern
   gibt. Sie gehört dem Griff selbst — ein Zug darauf ist ein Zug an ihm.
   `::after` ist schon vergeben (der sichtbare Balken), darum `::before`. */
.cp__griff::before {
  content: ''; position: absolute; left: 0; right: 0; top: 50%;
  height: 24px; transform: translateY(-50%);
}
.cp__griff:hover::after, .cp__griff:focus-visible::after { background: var(--accent); }
.cp__griff:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

.cp__fuss {
  flex: 0 0 auto;
  display: grid;
  grid-template-columns: auto auto minmax(0, 1fr) auto;
  align-items: center;
  gap: 16px;
  padding: 10px 16px;
  border-top: 1px solid var(--border);
  background: linear-gradient(180deg, var(--surface), var(--surface-1));
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .035);
}
.cp__marke--fuss { width: 30px; height: 30px; font-size: 11px; }
.cp__anzeige {
  display: flex; align-items: baseline; gap: 10px;
  padding: 6px 13px;
  border: 1px solid var(--border);
  border-radius: var(--radius-button);
  background: var(--surface-1);
  box-shadow: inset 0 2px 6px rgba(0, 0, 0, .45);
}
.cp__anzeige-wort {
  font-size: 11px; font-weight: 600; letter-spacing: .08em; text-transform: uppercase;
  color: var(--text-tertiary);
}
.cp__anzeige-wert {
  font-size: 19px; font-weight: 650; font-variant-numeric: tabular-nums; letter-spacing: .01em;
  color: var(--text-primary);
}
.cp__signatur { margin: 0; min-width: 0; }
.cp__signatur strong {
  display: block;
  font-size: 12px; font-weight: 600; letter-spacing: .1em; text-transform: uppercase;
  color: var(--text-secondary);
}
.cp__signatur span {
  display: block; margin-top: 2px;
  font-size: 11px; letter-spacing: .06em; text-transform: uppercase;
  color: var(--text-tertiary);
}
/* Weiter/Zurück (02.09.2026): in der LETZTEN Spalte des Fusses — `-2 / -1`
   trifft sie auf jeder Breite, auch wenn der Fuss am Handy weniger Spalten
   hat. Am Handy bleibt nur «Weiter»: zurück führt das Band darunter. */
.cp__weiter { grid-column: -2 / -1; justify-self: end; display: flex; align-items: center; gap: 8px; }
.cp__weiter .cp__knopf { min-height: 36px; padding: 0 16px; font-size: 13px; }

/* ---- Was der Rechner IN sein Blatt legt --------------------------------- */
/* Das Blatt selbst (`.lx-blatt`) ist ein eigenes Bauteil und steht in
   docs/design/patch-blatt.css. Hier steht nur, wie die Bauteile DES RECHNERS
   darin sitzen — sie tragen `cp-`/`kf-` und gehören deshalb in diesen Block. */
.lx-blatt__fach--aktionen .cp__knopf {
  width: 100%; min-height: 48px; justify-content: flex-start; gap: 11px;
  padding: 0 14px; font-size: 14px;
}
.lx-blatt__fach--aktionen .cp__knopf span:not(.cp__ic) { display: inline; }
/* Die Leiste im Blatt hat volle Breite: sie bricht ihre Wörter, statt sie
   mitten entzwei zu schneiden (Owner-Befund 4: «LEGT AN … ZÄHLT JE ST»). */
.lx-blatt__fach .cp__leiste {
  display: grid; gap: 14px;
  padding: 0; border: 0; background: transparent;
  overflow: visible; -webkit-mask-image: none; mask-image: none;
}
.lx-blatt__fach .kf-leiste__gruppe,
.lx-blatt__fach .kk-leiste { display: grid; gap: 7px; align-items: stretch; }
/* Ein Schalter ist Kästchen UND Wort in EINER Zeile — gestapelt sähe das
   Kästchen aus, als gehörte es zur Gruppe darüber (im Bild gesehen, 08.08.). */
.lx-blatt__fach .kf-schalter { display: flex; align-items: center; gap: 10px; }
.lx-blatt__fach .kf-leiste__wort { font-size: 12px; letter-spacing: .04em; }
.lx-blatt__fach .kf-segment { display: flex; flex-wrap: wrap; }
.lx-blatt__fach .kf-segment button { flex: 1 1 auto; }
/* Überlauf-Knopf und Einstell-Griff existieren immer im Markup und zeigen
   sich nur dort, wo sie gebraucht werden: am Desktop stehen Leiste und alle
   Handlungen sichtbar an ihrem Platz — dann sind beide stumm.
   (`hidden` allein genügt nicht: `.cp__knopf` setzt `display:inline-flex`
   und schlägt die UA-Regel `[hidden]{display:none}`.) */
.cp__knopf[hidden], .cp__einstellen { display: none; }
.cp__einstellen[aria-expanded="true"] {
  color: var(--accent-strong); border-color: var(--accent-line); background: var(--accent-soft);
}
.cp__einstellen .cp__ic { width: 19px; height: 19px; }

/* ---- Schmal: die Zonen werden selbst zu Blättern ------------------------- */
/* Dieselbe Bewegung wie im Deck — wischen statt scrollen. Cascade-Regel:
   Mobile-@media NACH der Basis (Memory project_css_cascade_mobile). */
@media (max-width: 1080px), (pointer: coarse) {
  /* HANDY-ANATOMIE (Owner 06.08.: «auf dem Smartphone hast du alles verkackt …
     das Smartphone ist genauso wichtig wie der Desktop»). Gemessen auf 390×844
     hatte die Arbeitsfläche nur 27 % der Höhe — Kopf, Ergebnis und Fuss
     frassen den Rest. Deshalb hier eine EIGENE Anatomie statt einer
     gestauchten Desktop-Seite: Kopf einzeilig, Ergebnis wird ein Wischbereich
     wie die anderen, Fuss trägt nur die Zahl. */
  .cp {
    height: calc(100svh - var(--cp-oben, 76px) - 16px - var(--cp-unten, var(--sab, 0px)));
    min-height: 420px;
  }

  /* Kopf: EINE Zeile, ~56 px — so wie in der Referenz (13_25_27.png: Marke,
     Titel, ein Griff, fertig; darunter beginnt sofort der Inhalt).
     Vorgeschichte: Der Titel KUERZT statt zu wachsen — ab «gesendet» stehen
     fuenf Aktionen im Kopf, die ihn auf 30 px Breite druecken; er brach dann
     auf fuenf Zeilen und der Kopf wuchs von 60 auf 138 px (gemessen 07.08.).
     Die Antwort darauf war bis 08.08. eine ZWEITE Zeile nur fuer Aktionen —
     und weil dieselbe Regel dort die Woerter ausblendete, stand auf ihr am
     Entwurf ein einzelner, wortloser ✓ (Owner-Befund 2). Beides faellt: es
     bleibt EIN fuehrender Knopf MIT Wort, alles Weitere zieht ins Blatt. */
  .cp__kopf { grid-template-columns: auto minmax(0, 1fr) auto; gap: 10px; padding: 8px 12px; }
  .cp__kopf h1 { font-size: 15px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .cp__kicker, .cp__hinweis { display: none; }
  .cp__marke { width: 28px; height: 28px; }
  .cp__aktionen { grid-column: auto; gap: 6px; flex-wrap: nowrap; }
  /* Nur-Icon-Knoepfe fallen sonst auf 39×40 — unter der Tapflaeche, die ein
     Daumen sicher trifft (WCAG 2.2 AA, gemessen 06.08.). */
  .cp__knopf { min-height: 44px; min-width: 44px; padding: 0 12px; font-size: 12.5px; }
  /* Der fuehrende Knopf traegt sein Wort; er darf dem Titel aber nicht die
     ganze Zeile nehmen. */
  .cp__aktionen > .cp__knopf > span:not(.cp__ic) {
    max-width: 34vw; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .cp__knopf--mehr { padding: 0; }
  /* Der Einstell-Griff traegt seit 09.08. sein WORT neben dem Symbol
     (Owner-Befund c1 B25: «beide Symbolknoepfe rechts sind
     unbeschriftet» — und dahinter lag genau das, was er suchte).
     Ohne waagrechtes Polster klebte das Wort an der Kante. */
  .cp__einstellen { padding: 0 11px; }
  .cp__knopf--mehr .cp__ic { width: 20px; height: 20px; }
  /* Der Griff zur Leiste erscheint erst hier — am Desktop steht die Leiste
     sichtbar an ihrem Platz und braucht keinen Griff. */
  .cp__einstellen { display: inline-flex; align-items: center; justify-content: center; }

  /* Die Dauerleiste faellt (Owner-Befund 3: 77 px, die IMMER standen). Sie
     wohnt jetzt im Blatt hinter dem Griff in der Zonenwahl. Bleibt sie aus
     irgendeinem Grund doch im Fluss (Flaeche ohne Zonenwahl), gilt das Alte. */
  .cp__leiste {
    flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none;
    padding: 7px 12px; gap: 8px 14px;
    -webkit-mask-image: linear-gradient(90deg, #000 calc(100% - 26px), transparent);
    mask-image: linear-gradient(90deg, #000 calc(100% - 26px), transparent);
  }
  .cp__leiste::-webkit-scrollbar { display: none; }

  /* Die Zonenwahl ist die Navigation dieser Flaeche — und Navigation gehoert
     am Handy an den DAUMEN, nicht an den oberen Rand (Referenz: Tab-Bar
     unten). `order` schiebt sie im Flex-Stapel ans Ende, direkt ueber den
     Fuss mit dem Total. Das spart 57 px oben UND macht sie erreichbar. */
  .cp__zonenwahl {
    order: 8;
    position: relative; z-index: 2;
    display: flex; gap: 4px; align-items: center;
    padding: 6px 10px calc(6px + var(--sab, 0px) / 2);
    overflow-x: auto; scrollbar-width: none;
    border-top: 1px solid var(--border);
    background: var(--surface-1);
  }
  .cp__fuss { order: 9; }
  .cp__zonenwahl::-webkit-scrollbar { display: none; }
  .cp__zonenwahl button {
    /* 44 GILT IN BEIDE RICHTUNGEN. Hier stand nur `min-height` — und der
       kuerzeste Name der Leiste, «Wo», mass damit 41.7 × 44 px (gemessen
       25.08.2026, Breiten-Waechter). Ein Daumen ist rund, nicht hoch: was in
       der einen Richtung 44 braucht, braucht es in der anderen auch. */
    flex: 0 0 auto; min-height: 44px; min-width: 44px; padding: 0 10px;
    border: 1px solid transparent; border-radius: var(--radius-badge);
    color: var(--text-tertiary); background: transparent;
    font: inherit; font-size: 12.5px; font-weight: 600;
    white-space: nowrap; cursor: pointer;
  }
  .cp__zonenwahl button[aria-current="true"] {
    color: var(--accent-strong); background: var(--accent-soft); border-color: var(--accent-line);
  }
  /* Passt die Leiste nicht (laengere Bereichsnamen, kleinere Geraete), wird
     GESCROLLT statt abgeschnitten — mit Fahne in die Richtung, in der noch
     etwas liegt (DESIGN §7 Innen-Scroll-Affordance). Ein hart mitten durch
     ein Wort geschnittener Reiter ist ein Defekt, keine Affordance
     (Owner-Befund 4, «ZÄHLT JE ST»). cockpit.js setzt die Klassen. */
  .cp__zonenwahl.is-mehr-rechts {
    -webkit-mask-image: linear-gradient(90deg, #000 calc(100% - 30px), transparent);
    mask-image: linear-gradient(90deg, #000 calc(100% - 30px), transparent);
  }
  .cp__zonenwahl.is-mehr-links {
    -webkit-mask-image: linear-gradient(90deg, transparent, #000 30px);
    mask-image: linear-gradient(90deg, transparent, #000 30px);
  }
  .cp__zonenwahl.is-mehr-links.is-mehr-rechts {
    -webkit-mask-image: linear-gradient(90deg, transparent, #000 30px, #000 calc(100% - 30px), transparent);
    mask-image: linear-gradient(90deg, transparent, #000 30px, #000 calc(100% - 30px), transparent);
  }

  .cp[data-spalten] .cp__werk {
    min-height: 0; align-self: stretch;
    display: grid; grid-auto-flow: column; grid-auto-columns: 100%;
    grid-template-columns: none;
    overflow-x: auto; overflow-y: hidden;
    scroll-snap-type: x mandatory; scrollbar-width: none;
    overscroll-behavior-x: contain; gap: 0;
  }
  .cp[data-spalten] .cp__werk::-webkit-scrollbar { display: none; }
  /* `scroll-snap-stop: always` heisst: EIN Wisch, EINE Zone — der Streifen
     darf keinen Schnappunkt ueberspringen, egal wie schwungvoll gewischt
     wird. Anlass 08.08.: seit die Karte randlos ist, trug der Schwung eines
     normalen Wisches ueber ZWEI Zonen (werk.scrollLeft 390 → 1170 statt 780,
     gemessen von test:konfigurator-ui) — man landete im «Ergebnis», wollte
     aber in die «Konditionen». Das ist dieselbe Klasse wie das
     Zonen-Rueckspringen, das der Owner schon einmal geruegt hat: die Fläche
     geht woanders hin als der Finger sagt. Die Regel gilt fuer JEDE
     Cockpit-Flaeche, nicht nur den Rechner — sie steht deshalb hier und
     nicht im Werkflaeche-Block. */
  .cp__zone, .cp__buehne {
    scroll-snap-align: start; scroll-snap-stop: always;
    border-right: 1px solid var(--border);
  }

  /* Das Ergebnis ist hier ein Bereich wie jeder andere. */
  .cp__ausgabe--zone {
    scroll-snap-align: start; scroll-snap-stop: always;
    height: auto; max-height: none; min-height: 0;
    overflow: auto; border-top: 0; border-right: 1px solid var(--border);
  }
  .cp__griff[hidden] { display: none; }

  .cp__zonekopf { display: none; }
  .cp__buehnekopf { flex-direction: column; align-items: stretch; padding: 8px 12px; }
  .cp__buehnetitel h2 { display: none; }
  .cp__wahl { overflow-x: auto; scrollbar-width: none; }
  .cp__wahl::-webkit-scrollbar { display: none; }

  /* Fuss: nur die Zahl. Die Signatur ist auf 390px reines Gewicht. */
  .cp__fuss { grid-template-columns: auto minmax(0, 1fr); padding: 7px 12px; }
  /* Am Handy steht im Fuss genau EINE Handlung (unten, `ordne()`); das Band
     am Daumen ist dort die Navigation — Weiter/Zurück nur ab 1080. */
  .cp__fuss > .cp__weiter { display: none; }
  .cp__signatur { display: none; }
  .cp__marke--fuss { width: 26px; height: 26px; }
  .cp__anzeige { padding: 4px 10px; }
  .cp__anzeige-wert { font-size: 17px; }
}

/* Der Rueckweg-Griff existiert im Markup immer (cockpit.js, wenn `zurueck`
   gesetzt ist), ist aber am Desktop AUS. Diese Zeile steht bewusst AUSSERHALB
   des @media-Blocks: stuende sie darin, haette der Knopf am Desktop gar keine
   Regel und erschiene als unformatierter Standard-Knopf im Kopf — genau der
   Desktop-Schaden, den dieser Umbau nicht anrichten darf (beim Lesen des
   eigenen Entwurfs gefunden, 08.08., bevor ein Bild entstand).
   Ein `display:none`-Element faellt aus dem Grid-Fluss; die Kopfzeile behaelt
   ihre drei Spalten und damit jedes Pixel. */
.cp__zurueck { display: none; }
/* Zwei Beschriftungen fuer nackte Zahlen: am Desktop AUS (Pixel-Grenze), am
   Handy AN. Die Gegenstuecke stehen im Handy-Block unten.
   ⚠️ Beim ersten Versuch stand die Karten-Beschriftung im Hinweistext der
   Buehne (`zonenHinweisWo()`). Der wird auch am Desktop gezeigt — der
   Pixelvergleich 1280/1440/1920 schlug sofort aus. Beschriftungen, die nur
   das Handy braucht, gehoeren in ein eigenes Element, nie in geteilten Text. */
.kf-kopf__einheit { display: none; }
.kf-karte__legende { display: none; }

/* ===========================================================================
   AUFGABEN-MODUS AM HANDY — die Arbeitsflaeche IST der Bildschirm
   ===========================================================================
   Owner-Befund 08.08. am eigenen iPhone, woertlich: «Es hat keine Uebersicht.
   Und dann noch in einem kleinen Fenster, obwohl das Smartphone schon so
   klein ist.»

   GEMESSEN auf 390x620 (dem ECHTEN Mass — siehe unten), Rechner `#/v/offer/:id`:
     App-Kopf 52 + Reiter 45 + Zonenwahl 57 + cp-Kopf 61 + cp-Fuss 51
     + Daumenleiste 68  =  334 px NAVIGATION von 620 px  =  54 %.
   Fuer die Arbeit blieben 286 px — und der Plus-Knopf lag auf dem Total.

   WARUM ES NIE AUFFIEL: 59 Pruefskripte messen das Handy auf 390x844 (47x)
   bzw. 390x800 (12x). Das ist die Punktgroesse des GERAETS. Im Safari des
   Owners bleiben nach Adressleiste und Werkzeugleiste real ~620 px. Jeder
   Waechter sah 224 px Hoehe, die es auf seinem Bildschirm nie gab.
   Das Werkzeug auf dem echten Mass: `scripts/handy-buehne.mjs` (HANDY_MASSE).

   DIE ANTWORT ist keine weitere Stauchung, sondern eine EIGENE Anatomie:
   Wer eine Offerte oeffnet, arbeitet an EINER Sache. Die Navigation der App
   tritt so lange ab; die Flaeche traegt ihre eigene — Rueckweg im Kopf,
   Zonenwahl am Daumen, Total und Primaeraktion fest am unteren Rand.

     ┌───────────────────────────────┐
     │ ‹  Offerte 2026-0042 · Entwurf ⋯│  Kopf: Rueckweg + was + Ueberlauf
     ├───────────────────────────────┤
     │        ZONE, randlos          │  scrollt innen, nimmt allen Rest
     ├───────────────────────────────┤
     │ Kunde&Korb  Wo  Kondit.  Ergeb│  die EINE Navigation der Flaeche
     ├───────────────────────────────┤
     │ TOTAL CHF 3'316.50 [Speichern]│  fest am Daumen
     └───────────────────────────────┘

   GRENZE: alles hier haengt an `body.lx-werkflaeche` (cockpit.js, nur bei
   `spec.vollflaeche`) UND am Handy-Breakpoint. Der Desktop sieht keine
   einzige dieser Regeln — 1280/1440/1920 bleiben Pixel fuer Pixel gleich.
   =========================================================================== */
@media (max-width: 1080px), (pointer: coarse) {
  /* 1 — Die drei fremden Leisten treten ab. Ihre Ziele sind einen Rueckweg
         entfernt (Kopf links), nicht verloren. */
  body.lx-werkflaeche #lx-topbar,
  body.lx-werkflaeche #subnav,
  body.lx-werkflaeche #lx-unten,
  /* ⚠️ DAS ORTSSCHILD KAM SPÄTER (patch-ortsschild.css, Welle 17.08.) UND
     STAND NICHT IN DIESER LISTE. Es kostete 44 px + 10 px Rand über `#app-view`
     — und weil `.cp` eine Zeile tiefer auf `height: 100dvh` steht, schob es die
     Fläche GENAU um diesen Betrag über die untere Bildkante.
     GEMESSEN am 25.08.2026 auf 390×620 (echte Schale, echtes main.js):
     `.cp` reichte von y=54 bis y=674 — 54 px über den Schirm hinaus. Was dort
     unten liegt, ist der Fuss: das TOTAL und der einzige Knopf der Fläche.
     Der Preis stand bei y=626 auf einem 620-px-Schirm, «Speichern» endete bei
     667. In VIER gemessenen Zuständen (leer · Kunde gewählt · Kanton gewählt ·
     Laufzeit 6 Monate) war der Preis NIE im Bild, während er von 0.00 über
     465.70 und 931.40 auf 4'470.65 stieg. Der Owner sah keine dieser Zahlen.
     Das Schild sagt hier ausserdem nichts Neues: es trägt «Verkauf › Offerten ›
     Offerte», und der Kopf der Fläche trägt Rückweg, «NEUE OFFERTE · ENTWURF»
     und den Titel. Genau diese Begründung steht schon in patch-ortsschild.css
     («Ein Schild, das nur diese beiden Wörter wiederholt, kostet am Handy 54 px
     und sagt nichts Neues») — sie greift dort nur nicht, weil dieses Schild
     drei Glieder hat. Im Aufgaben-Modus gilt sie ohne Ausnahme. */
  body.lx-werkflaeche #lx-ort { display: none; }
  /* Was hier abtritt, gibt seinen Platz auch frei — sonst hielte das
     Höhen-System (Block «Boden-Geometrie») ihn weiter frei und der Toast
     schwebte 62 px zu hoch. */
  body.lx-werkflaeche:has(.lx-unten) { --nav-h: 0px; }
  body.lx-werkflaeche:has(.lx-top) { --kopf-h: 0px; }
  /* Der Plus-Knopf lag auf dem Total (Owner: «ein schwebender Plus-Knopf, der
     dort nichts zu suchen hat»). In der Flaeche, die neu anlegt, ist er
     ohnehin sinnlos. */
  body.lx-werkflaeche .qc { display: none; }
  body.lx-werkflaeche.has-quick-create { --fab-h: 0px; }
  /* Der Hamburger schwebt `fixed` ueber allem (style.css:294) und laege sonst
     auf dem Rueckweg-Griff. */
  body.lx-werkflaeche .sidebar-toggle { display: none; }

  /* 2 — Kein Kasten in der Seite. Die Flaeche IST die Seite.
         Und die Seite scrollt nicht — das Gesetz der Schale, hier mechanisch
         statt nur als Vorsatz. Anlass: die Einblendung `view-enter` hebt
         #app-view um 4 px (DESIGN §5, style.css:4096). Bei einer Flaeche, die
         exakt 100dvh misst, macht das die Seite fuer 180 ms 4 px zu hoch —
         ein Wisch am Rand haette in dieser Zeit die ganze Seite bewegt statt
         die Zone. Gemessen 08.08. mit nachgestellter sicherer Zone (59/34).
         Die Einblendung selbst bleibt; nur der Ueberlauf ist zu. */
  body.lx-werkflaeche { overflow: hidden; }
  body.lx-werkflaeche .main-shell {
    padding: 0;
    /* Die Schale reservierte oben Platz fuer den Kopf und unten fuer die
       Daumenleiste (style.css:1113, 12803). Beide sind hier weg. */
    padding-top: 0;
    padding-bottom: 0;
  }
  body.lx-werkflaeche .cp {
    /* VOLLE Hoehe, nicht «Hoehe minus sichere Zone».
       ⚠️ Hier stand zuerst `calc(100dvh - var(--sat) - var(--sab))`. Im
       Testbrowser sind beide Werte 0 — es sah also richtig aus. Auf einem
       echten iPhone haette es die sichere Zone ZWEIMAL abgezogen: einmal von
       der Hoehe der Flaeche, ein zweites Mal als Polster in Kopf und Fuss
       (zwei Zeilen tiefer). Unter dem Total waere ein Streifen Seitengrund
       stehengeblieben — genau der Fehler, den der Owner schon zweimal
       gemeldet hat (siehe Kommentar am .cp-Basisblock).
       `dvh` ist fuer BEIDE Faelle richtig: in Safari misst es das Fenster
       ohne die Leisten (~620), in der installierten App den ganzen
       Schirm (812). Kein Sonderfall, keine Abfrage auf standalone.

       ⚠️ ZWEI ABZÜGE, BEIDE GEMESSEN — nicht «volle Höhe» (25.08.2026):

       `--cp-oben` ist der Abstand der Fläche zur Fensteroberkante, den das
       Bauteil selbst misst (cockpit.js `messeRand`). Er ist normalerweise 0,
       weil alles darüber abtritt. Stand aber je EIN Element darüber, schob es
       den Fuss samt TOTAL um genau diesen Betrag über den Bildrand — passiert
       mit dem Ortsschild (54 px, siehe Block 1 oben). Der Abzug macht das
       mechanisch unmöglich: was oben steht, kann den Fuss nicht mehr
       hinausdrücken. Das ist die Wurzel, nicht der Einzelfall.

       `--vv-unten` ist, wie viel unten NICHT sichtbar ist — auf dem iPhone die
       offene Tastatur (utils/viewport.js misst es aus `visualViewport`; das
       ganze Haus rechnet damit, style.css «Boden-Geometrie»). Ohne diesen Abzug
       liegt der Fuss beim Tippen HINTER der Tastatur: `dvh` reagiert auf die
       Browserleisten, nie auf die Tastatur. Genau das ist der Fall «ich tippe
       eine Zahl und sehe den Preis nicht mehr» — auf einer Fläche, deren
       einzige Antwort dieser Preis ist. Ohne das Modul (alte Engine) ist der
       Wert ungesetzt und es gilt exakt das Verhalten von vorher. */
    height: calc(100dvh - var(--cp-oben, 0px) - var(--vv-unten, 0px));
    min-height: 0;
    border: 0;
    border-radius: 0;
    box-shadow: none;
    margin: 0;
  }
  /* Die sichere Zone traegt der Kopf bzw. der Fuss, nicht die Seite — sonst
     entstuende oben und unten wieder ein Streifen Seitengrund. */
  body.lx-werkflaeche .cp__kopf { padding-top: calc(8px + var(--sat, 0px)); }
  body.lx-werkflaeche .cp__fuss { padding-bottom: calc(7px + var(--sab, 0px)); }

  /* 3 — Der Rueckweg. Er ersetzt am Handy die Marke: «L13» sagt nichts, was
         der Titel nicht schon sagt (Owner: unerklaerte Zeichen fallen). */
  .cp__zurueck {
    display: inline-flex; align-items: center; justify-content: center;
    flex: 0 0 auto;
    width: 44px; height: 44px; margin-left: -6px;
    border: 0; border-radius: var(--radius-sm, 8px);
    background: transparent; color: var(--text);
    cursor: pointer;
  }
  .cp__zurueck:active { background: var(--surface-3); }
  .cp__zurueck .cp__ic { width: 22px; height: 22px; }
  body.lx-werkflaeche .cp__kopf > .cp__marke { display: none; }
  body.lx-werkflaeche .cp__fuss > .cp__marke--fuss { display: none; }
  /* Mit Rueckweg links, Titel in der Mitte und Ueberlauf rechts sind es
     wieder genau drei Spalten. */
  body.lx-werkflaeche .cp__kopf { grid-template-columns: auto minmax(0, 1fr) auto; }
  /* Der Kicker traegt die Kennung («Offerte 2026-0042 · Entwurf»). Er ist am
     Handy die einzige Stelle, an der steht, WORAN man arbeitet — im Kopf der
     App stand vorher nur «Offerten», also der Name der Tuer. */
  body.lx-werkflaeche .cp__kicker {
    display: block;
    font-size: 11px; font-weight: 600; letter-spacing: .02em;
    color: var(--text-tertiary);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
    margin: 0 0 1px;
  }
  body.lx-werkflaeche .cp__kopf h1 { font-size: 15px; line-height: 1.2; }
  /* W2b 30.08.: Und derselbe Grund fuer den HINWEIS — genau eine Ebene
     tiefer. Er steht nur in zwei Zustaenden ueberhaupt im Markup: solange
     kein Kunde gewaehlt ist, und NACH DER ANNAHME, wo er den Weg des
     Verkaufs traegt («Rechnung RE-2026-0001 offen · Ausstrahlung ab
     02.09.2026»). Gemessen am 30.08.: dieselbe Auskunft lag sonst nur im
     Ergebnis-Blatt bei left 796 px — eine Wischbewegung vom Kopf entfernt,
     im ersten Bild also nicht da. Der Kopf waechst dadurch NUR in diesen
     zwei Zustaenden um eine Zeile; in Entwurf und Versand ist das Element
     gar nicht vorhanden, und die Einzeiligkeit von 06.08. bleibt.
     Ausserhalb der Werkflaeche (Admin-Flaechen mit langen Erklaertexten)
     bleibt der Hinweis am Handy stumm — die Regel darueber gilt weiter. */
  /* ZWEI ZEILEN, KEIN AUSLASSUNGSPUNKT. Erste Fassung stand hier einzeilig mit
     `text-overflow: ellipsis` — im Bild (23-nach-annahme, 30.08.) las sich das
     als «Rechnung RE-2026-0001 offen · Ausstrahlung…»: die Rechnung stand da,
     der Ausstrahlungstag war abgeschnitten. Der ganze Satz misst 53 Zeichen,
     die Titelspalte auf 390 px traegt rund 42. Eine halbe Auskunft ist keine.
     Der Deckel bleibt bei ZWEI Zeilen (clamp), damit der Kopf nie waechst,
     wenn ein Kunde einmal drei Rechnungen traegt. */
  body.lx-werkflaeche .cp__hinweis {
    display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;
    font-size: 11.5px; line-height: 1.25; color: var(--text-secondary);
    white-space: normal; overflow: hidden; text-overflow: clip;
    margin: 1px 0 0;
  }

  /* 4 — Total und Primaeraktion am Daumen. `ordne()` haengt den fuehrenden
         Knopf hier ein; der Fuss wird dadurch zur Handlungszeile. */
  body.lx-werkflaeche .cp__fuss {
    grid-template-columns: minmax(0, 1fr) auto;
    gap: 10px; align-items: center;
  }
  /* Im Fuss steht genau EINE Handlung — die fuehrende. Sie muss auch so
     aussehen: solide Akzentflaeche (DESIGN.md, «Button primary»). Vorher erbte
     sie den stillen Sekundaer-Stil, weil `speichern` im Entwurf nicht als
     `primaer` markiert ist; am Bild sah die einzige Handlung der Flaeche aus
     wie ein Nebenknopf (selbst gesehen, 08.08., erste Fassung). */
  .cp__knopf.cp__knopf--fuss {
    min-height: 44px; padding: 0 18px;
    font-size: 14px; font-weight: 650;
    border-color: transparent; color: var(--on-accent); background: var(--accent);
  }
  .cp__knopf.cp__knopf--fuss:hover { background: var(--accent-hover); }
  .cp__knopf.cp__knopf--fuss > span:not(.cp__ic) { max-width: none; }
  body.lx-werkflaeche .cp__anzeige-wert { font-size: 19px; }

  /* 6 — Der Hinweis ueber der Buehne traegt jetzt drei Angaben (Stand der
         Auswahl, Beschriftung der Kartenzahlen, was ein Tap tut) und brach
         damit auf zwei Zeilen à 27 px. Er BLEIBT vollstaendig — gekuerzt
         waere er wieder eine unerklaerte Zahl — aber er wird typografisch
         dicht: 12 px statt 13, engere Zeile, weniger Polster. 54 px -> 36 px.
         Auf einem 620-px-Schirm sind 18 px drei Prozent der Arbeitsflaeche. */
  body.lx-werkflaeche .cp__buehnekopf { padding: 6px 12px; }
  body.lx-werkflaeche .cp__buehnetitel p {
    font-size: 12px; line-height: 1.35; margin: 0;
  }

  /* 7 — Karte UND Korb, statt Karte ODER Korb.
         Gemessen 08.08. auf 390x620: Karte 211 px, Liste 158 px, eine
         Korb-Zeile 79 px — es war IMMER nur eine Zeile sichtbar, der Rest lag
         hinter einem 158-px-Guckloch. Ein Deckel auf die Karte loest das
         nicht: unter ~200 px werden ihre Beschriftungen unlesbar, und genau
         das war Owner-Befund 6 («Karte fix 190 px mit unlesbaren Labels»).
         Zwei Blaetter mit Umschalter waeren eine fuenfte Navigationsebene.

         Also scrollt die ZONE als Ganzes: die Karte behaelt ihr Seiten-
         verhaeltnis und bleibt lesbar, die Liste haengt darunter und ist so
         lang wie noetig. Das Gesetz der Schale bleibt gewahrt — die SEITE
         scrollt nicht, eine Zone scrollt innen (so wie `.kf-wo__liste` es
         vorher allein tat). */
  body.lx-werkflaeche .kf-wo {
    overflow-y: auto; overflow-x: hidden;
    -webkit-overflow-scrolling: touch; overscroll-behavior-y: contain;
  }
  body.lx-werkflaeche .kf-wo__karte { flex: 0 0 auto; }
  body.lx-werkflaeche .kf-wo__liste {
    flex: 0 0 auto; overflow: visible; padding-bottom: 8px;
  }

  /* 8 — BEIDE Zahlen mit ihrer Einheit (Owner-Befund 08.08.: «Kopf 8
         Standorte, darunter 7 ORTE — fachlich richtig, auf dem Bild wirkt es
         wie ein Fehler»). Am Handy war der ganze Zahlen-Nachsatz aus, weil er
         auf zwei Zeilen brach. Jetzt ist er GETEILT: «· 8 Standorte» kommt
         zurueck, «· 21 Bildschirme» bleibt aus — zwei Zahlen passen in die
         Zeile, drei nicht. Am Desktop stehen weiter alle drei, Zeichen fuer
         Zeichen wie vorher (die Teilung aendert nur das Markup, nicht den
         gerenderten Text). */
  body.lx-werkflaeche .kf-kopf__zahlen--orte { display: inline; }

  /* 9 — SCROLL-ANDEUTUNG, verstaerkt (Owner-Befund 08.08.: «Unter Basel
         beginnt eine zweite Karte und endet mitten im Nichts»).
         ⚠️ Hier stand zuerst eine EIGENE Maske samt eigenem Scroll-Horcher im
         Konfigurator. Falsch: cockpit.js:709 haengt die Affordance laengst an
         JEDE scrollende Flaeche der Schale, und `.kf-wo` traegt die Klasse
         `is-mehr` seit dem Moment, in dem die Zone zu scrollen begann. Zwei
         Mechaniken fuer dieselbe Sache — genau das, was das Haus verbietet.
         Der Doppel ist entfernt; geblieben ist die eine Mechanik.
         Was WIRKLICH fehlte, war Deutlichkeit: 34 px Verlauf las der Owner am
         620-px-Schirm als harte Kante. Auf der Vollflaeche sind es 56 px. */
  body.lx-werkflaeche .cp .is-mehr {
    -webkit-mask-image: linear-gradient(180deg, #000 calc(100% - 56px), transparent);
    mask-image: linear-gradient(180deg, #000 calc(100% - 56px), transparent);
  }

  /* 10 — DIE KARTE BEKOMMT DIE GANZE BREITE.
          Owner-Befund 08.08.: «Die Schweiz sitzt klein in der Mitte, links und
          rechts steht viel Schwarz.» Gemessen, woher die 70 px kamen:
            Zone 390 → .cp__blatt Innenabstand 357 → .kf-wo__karte Polster 349
            → Leerrand IN der viewBox (42 von 1000 je Seite) 320 px Land.
          Seine Vermutung «Rahmen fast quadratisch» war es NICHT: die viewBox
          misst 1000/640 = 1.5625, das Land 917/588 = 1.5595 — praktisch gleich.
          Es waren zwei Innenabstaende und ein Leerrand in der Grafik.
          (1) Das Blatt gibt seinen Innenabstand her — die Liste darunter hat
              ihren eigenen, es geht also nichts verloren ausser Schwarz.
          (2) Das Polster der Karte faellt.
          (3) Der Leerrand der viewBox wird weggeschnitten: 1000/917 = 1.09.
              Zentriert skaliert, und weil der Rand symmetrisch ist (42/42,
              26/26), schneidet das genau die leere Zone weg — das Land
              waechst, die Kastenhoehe bleibt. Die viewBox selbst bleibt
              unangetastet: sie gilt auch am Desktop, und der darf sich nicht
              aendern. Der Zoom-Weg bleibt heil, weil karteZoombar die INNERE
              Gruppe transformiert, nicht dieses Element. */
  body.lx-werkflaeche .cp__blatt:has(.kf-wo) { padding: 0; }
  body.lx-werkflaeche .kf-wo__karte { padding: 0; overflow: hidden; }
  body.lx-werkflaeche .kf-wo__karte .bs-karte { transform: scale(1.09); }

  /* 5 — Keine unerklaerte Ziffer. Die Zaehler in den Korb-Zeilen zeigen
         «gebucht / moeglich»; ohne Beschriftung ist das ein nacktes «3 / 3». */
  .kf-kopf__einheit {
    display: block;
    margin-top: 2px;
    font-size: 11px; font-weight: 550; letter-spacing: .01em;
    color: var(--text-tertiary); text-transform: none;
  }
  /* Dasselbe fuer die Zahlen IN der Karte. Sie sitzt an der Karte, nicht im
     Hinweis darueber — so steht die Beschriftung dort, wo die Zahlen sind. */
  body.lx-werkflaeche .kf-karte__legende {
    display: block; flex: 0 0 auto; margin: 0;
    padding: 5px 14px 3px; text-align: center;
    font-size: 11px; font-weight: 550; color: var(--text-tertiary);
    background: var(--bg);
  }
}

/* Ganz schmal: die Marke tritt ab.
   ⚠️ HIER STAND BIS 08.08. DAS GEGENTEIL: eine zweite Kopfzeile nur fuer die
   Aktionen. Sie loeste ein echtes Problem (ab «gesendet» endete die fuenfte
   Handlung 10 px AUSSERHALB des Kopfes, gemessen 07.08.) und schuf ein
   groesseres: 97 px Kopf, und auf der zweiten Zeile am Entwurf ein einzelner
   ✓ OHNE Wort — Owner-Befund 2 vom 08.08. Die Wurzel war nicht die Zeile,
   sondern die Zahl der Ziele im Kopf. Fuenf Handlungen gehoeren am Handy
   nicht in eine Kopfzeile; sie stehen jetzt mit vollem Wort im Blatt
   (cockpit.js `ordne()`), im Kopf bleibt EINE. Auf 390 px gewinnt der Titel
   dadurch Breite: die Marke faellt, weil sie nichts sagt, was der Titel nicht
   schon sagt. */
@media (max-width: 400px) {
  .cp__kopf { grid-template-columns: minmax(0, 1fr) auto; padding-left: 14px; }
  .cp__kopf > .cp__marke { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .cp__deck, .cp__werk { scroll-behavior: auto; }
  .cp__knopf:active { transform: none; }
}


/* ===========================================================================
   KONFIGURATOR — die Innenausstattung des Cockpits
   Bauteil: public/src/views/sales-konfigurator.js
   ---------------------------------------------------------------------------
   Diese Regeln fehlten beim ersten Bau vollständig: die Fläche gab HTML mit
   .kf-*-Klassen aus, die es im Stylesheet nicht gab. Ergebnis war ein Bild, in
   dem jedes Label an seinem Wert klebte («Netto430.80»). Ein Test, der nur
   Struktur und Zahlen prüft, fängt das nie — nur Hinsehen.
   =========================================================================== */

.kf-kopf {
  margin: 12px 0 5px;
  font-size: 11px; font-weight: 650; letter-spacing: .12em; text-transform: uppercase;
  color: var(--text-secondary);
}
.kf-kopf:first-child { margin-top: 0; }

/* Label links, Wert rechts — das Idiom für Stats in schmalen Spalten
   (DESIGN.md §4, «Stat-in-Rail»: nie 2×2-Grid unter 400px). */
.kf-zeile {
  display: flex; align-items: baseline; justify-content: space-between; gap: 12px;
  padding: 4px 0;
  border-bottom: 1px solid var(--border);
  font-size: 12.5px; color: var(--text-secondary);
}
.kf-zeile:last-child { border-bottom: 0; }
.kf-zeile b { color: var(--text-primary); font-weight: 620; font-variant-numeric: tabular-nums; }
.kf-zeile.is-stark { padding-top: 10px; border-bottom: 0; font-size: 13.5px; }
.kf-zeile.is-stark b { font-size: 18px; font-weight: 680; color: var(--accent-strong); }

.kf-hint { margin: 6px 0 0; font-size: 11px; line-height: 1.45; color: var(--text-tertiary); }
.kf-gewaehlt { margin: 8px 0 0; font-size: 11.5px; line-height: 1.4; color: var(--accent-strong); }
/* P7 (Owner-Video-Audit 09.08.2026, c2 B19 · c3 B7/B8): DIE LEITPLANKEN WAREN
   GRAU. `var(--border)` auf `var(--surface-inset)` mit sekundaerem Text ist
   exakt die Anmutung eines Hinweises, und so wurde sie auch gelesen — der
   Owner scrollte an sieben unterpreisigen Standorten vorbei. Die Warnstufe
   traegt jetzt die Warnfarben des Hauses (`--warn-*`, dasselbe Idiom wie
   `.so-warning--warnung` und `.cal-src-warn`), die kritische die
   Gefahrenfarben. Kein neues Bild, nur die richtige Stufe. */
/* FLACH STATT KASTEN (Owner «Widget», 2026-08-13): die Warnung war ein
   umrandeter, warngefaerbter Kasten — sie «schwebte» ueber der Flaeche wie ein
   Hinweis-Widget. Jetzt sitzt sie auf dem Grund; die Warnstufe bleibt voll
   erkennbar ueber den Warn-Text UND eine Akzentkante links (dasselbe Idiom wie
   `.kf-loc.is-gratis`), aber ohne Rahmen, Radius und abhebenden Hintergrund.
   Damit bleibt der P7-Sinn erhalten (eine Warnung liest sich als Warnung, nicht
   als grauer Hinweis), ohne einen schwebenden Kasten zu sein. */
.kf-warn {
  /* 8px statt 7px Padding: die 1px des alten Rahmens wandern ins Padding, die
     senkrechte Hoehe bleibt exakt gleich (siehe .kf-register). */
  margin: 6px 0 0; padding: 8px 10px;
  border: 0; border-radius: 0; background: transparent;
  box-shadow: inset 3px 0 0 var(--warn);
  font-size: 11.5px; line-height: 1.4; color: var(--warn-strong);
}
.kf-warn--kritisch {
  box-shadow: inset 3px 0 0 var(--bad); color: var(--bad-strong);
}
/* Die Zaehlzeile steht ueber der GANZEN Ausgabe, nicht in einer ihrer Spalten
   — sie ist der Satz, den der Owner sehen soll, bevor er scrollt. Die
   linke Akzentkante (vom Basis-Padding getragen) traegt sie mit. Padding und
   Marge bleiben wie zuvor — entfernt ist nur die Kasten-Optik, damit die
   Ausgabe-Anatomie (Roll-Raster, klebender Positionskopf) unveraendert traegt. */
.kf-block--alarm { grid-column: 1 / -1; }
.kf-warn--zahl { margin-top: 0; padding: 10px 12px; font-size: 13px; font-weight: 650; }

/* Felder und Schalter */
.kf-feld { display: block; margin-bottom: 8px; }
.kf-feld > span {
  display: block; margin-bottom: 4px;
  font-size: 11px; font-weight: 600; color: var(--text-tertiary);
}
.kf-feld select, .kf-feld input {
  width: 100%; min-height: 38px; padding: 0 10px;
  border: 1px solid var(--border); border-radius: var(--radius-button);
  color: var(--text-primary); background: var(--surface-inset);
  font: inherit; font-size: 13px;
}
.kf-feld select:focus-visible, .kf-feld input:focus-visible {
  outline: none; border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(var(--accent-rgb), .20);
}
.kf-schalter {
  display: flex; align-items: center; gap: 9px;
  min-height: 30px; margin-bottom: 2px;
  font-size: 12.5px; color: var(--text-secondary); cursor: pointer;
}
.kf-schalter input { flex: 0 0 auto; width: 17px; height: 17px; accent-color: var(--accent); }
/* «wirkt hier nicht» — ein gesetzter Haken, der nichts bewirkt, sagt es selbst
   (Prüfer 13.08.). Inline und leise: es ist eine Auskunft, keine Warnung, und
   der Haken bleibt bedienbar. */
.kf-schalter__ohne { font-style: normal; color: var(--warn-strong); white-space: nowrap; }
.kf-schalter b { font-weight: 650; color: var(--text); }

/* Gebietsebenen: zwei Spalten, damit vier Knöpfe nicht vier Zeilen brauchen */
.kf-wahl { display: grid; grid-template-columns: 1fr 1fr; gap: 5px; }
.kf-knopf {
  display: grid; grid-template-columns: auto 1fr; align-items: center; gap: 8px;
  min-height: 44px; padding: 8px 10px;
  border: 1px solid var(--border); border-radius: var(--radius-button);
  color: var(--text-primary); background: var(--surface);
  font: inherit; font-size: 12px; font-weight: 600; text-align: left; cursor: pointer;
  transition: background var(--dur-fast, 120ms), border-color var(--dur-fast, 120ms);
}
.kf-knopf .cp__ic { width: 17px; height: 17px; color: var(--text-tertiary); }
.kf-knopf:hover { background: var(--surface-3); }
.kf-knopf[aria-pressed="true"] {
  border-color: var(--accent-line); background: var(--accent-soft); color: var(--accent-strong);
}
.kf-knopf[aria-pressed="true"] .cp__ic { color: var(--accent-strong); }
.kf-knopf:disabled { opacity: .45; cursor: default; }

/* Segmentierte Umschalter (Positions-Modi, Dauer-Einheit) */
/* Polster 2 px + Haarlinie 1 px = die 3 px von v393: die Haarlinie der Farbwelt
   darf den Schalter nicht wachsen lassen — 2 px mehr Werkzeugzeile kosteten
   die Karte auf 1440 drei Pixel Breite (Ratsche G, A/B `ab-karte.mjs`). */
.kf-segment {
  display: flex; gap: 2px; padding: 2px;
  border-radius: var(--radius-button); border: 1px solid var(--border); background: var(--surface-inset);
}
.kf-segment button {
  flex: 1 1 0; min-height: 34px; padding: 0 8px;
  border: 0; border-radius: var(--radius-button);
  color: var(--text-secondary); background: transparent;
  font: inherit; font-size: 12px; font-weight: 650; letter-spacing: .06em; text-transform: uppercase; cursor: pointer;
}
.kf-segment button[aria-pressed="true"] {
  color: var(--accent-strong); background: var(--accent-soft);
  box-shadow: inset 0 0 0 1px var(--accent-line);
}
.kf-segment button:disabled { opacity: .45; cursor: default; }

/* Schnellwahl */
.kf-presets { display: flex; flex-wrap: wrap; gap: 5px; }
.kf-presets button {
  min-height: 32px; padding: 0 11px;
  border: 1px solid var(--border); border-radius: var(--radius-badge);
  color: var(--text-secondary); background: var(--surface);
  font: inherit; font-size: 11px; font-weight: 650; letter-spacing: .06em; text-transform: uppercase; cursor: pointer;
}
.kf-presets button:hover { color: var(--text-primary); background: var(--surface-3); }

.kf-add {
  min-height: 36px; padding: 0 12px; margin-top: 4px;
  border: 1px dashed var(--border); border-radius: var(--radius-button);
  color: var(--text-secondary); background: transparent;
  font: inherit; font-size: 11px; font-weight: 650; letter-spacing: .06em; text-transform: uppercase; cursor: pointer;
}
.kf-add:hover { color: var(--accent-strong); border-color: var(--accent-line); }

/* FLACH STATT KASTEN (Owner «Widget», 2026-08-13): der gewaehlte Kunde stand in
   einer akzent-hinterlegten, umrandeten Karte, die ueber der Flaeche schwebte.
   Er ist jetzt schlicht der Wert unter dem Label «Kunde» — Name gross, «ändern»
   als kleiner Knopf daneben, ohne Rahmen und ohne abhebenden Grund. */
.kf-kunde {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 2px 0;
  border: 0; border-radius: 0; background: transparent;
  font-size: 13px; color: var(--text-primary);
}
.kf-kunde strong { min-width: 0; font-size: 13.5px; font-weight: 650; color: var(--text-primary); }
.kf-kunde button {
  flex: 0 0 auto; min-height: 30px; padding: 0 9px;
  border: 1px solid var(--border); border-radius: var(--radius-button);
  color: var(--text-secondary); background: var(--surface);
  font: inherit; font-size: 11.5px; cursor: pointer;
}
/* TOUCH-BODEN fuer «ändern» (Pruefer-Befund 13.08.2026: gemessen 58×30 px,
   Hausregel 44). Der globale Touch-Block (Z. 656) steht VOR dieser Datei-Zone
   und verliert die Kaskade gegen die Regel darueber — deshalb steht der Boden
   hier, direkt hinter seiner Basis (Hausgesetz «Mobile-@media NACH der Basis»,
   Memory project_css_cascade_mobile). Am Rechner bleibt der Knopf klein: er
   soll den Namen nicht erschlagen. */
@media (max-width: 1080px), (pointer: coarse) {
  .kf-kunde button { min-height: 44px; padding: 0 14px; font-size: 12.5px; }
}

/* Standort-Liste mit Stepper je Zeile.
   FLACH STATT KASTEN (Owner-Dauerschmerz «Widget», 2026-08-13): die Zeile war
   eine umrandete, gerundete Kachel auf var(--surface) — sie «schwebte» über der
   Fläche. Jetzt sitzt sie direkt auf dem Grund und ist von der nächsten nur
   durch eine feine Linie getrennt, wie jede Liste im Rest der App (Hairline-
   Konvention, siehe Korb-Block unten). Kein border-Rahmen, kein Radius, kein
   abhebender Hintergrund. */
.kf-liste { display: grid; gap: 0; }
.kf-loc {
  display: grid; grid-template-columns: minmax(0, 1fr) auto auto;
  align-items: center; gap: 10px;
  padding: 9px 11px;
  border: 0; border-bottom: 1px solid var(--border); border-radius: 0;
  background: transparent;
}
.kf-loc:last-child { border-bottom: 0; }
/* «gratis» ist ein Zustand, kein Kasten: ein Akzent-Strich an der linken Kante
   statt eines umrandeten Feldes (das border-color-Signal des alten Kastens). */
.kf-loc.is-gratis { box-shadow: inset 2px 0 0 var(--accent); }
.kf-loc__wer { min-width: 0; }
.kf-loc__wer strong { display: block; font-size: 12.5px; font-weight: 620; color: var(--text-primary); }
.kf-loc__wer small { display: block; margin-top: 2px; font-size: 11px; color: var(--text-tertiary); }
.kf-stepper {
  display: grid; grid-template-columns: 32px auto 32px; align-items: center; gap: 2px;
  border: 1px solid var(--border); border-radius: var(--radius-button);
  background: var(--surface-inset);
}
.kf-stepper button {
  min-height: 32px; border: 0; border-radius: var(--radius-button);
  color: var(--text-primary); background: transparent;
  font: inherit; font-size: 15px; cursor: pointer;
}
.kf-stepper button:hover { background: var(--surface-3); }
.kf-stepper button:disabled { opacity: .35; cursor: default; }
.kf-stepper b {
  min-width: 34px; text-align: center;
  font-size: 12.5px; font-variant-numeric: tabular-nums; color: var(--accent-strong);
}
.kf-weg {
  width: 30px; height: 30px; border: 0; border-radius: var(--radius-button);
  color: var(--text-tertiary); background: transparent;
  font: inherit; font-size: 14px; cursor: pointer;
}
.kf-weg:hover { color: var(--bad); background: var(--surface-3); }

/* Kundenportal im Cockpit — dieselbe Anatomie wie der Konfigurator.
   Owner 05.08.: «das Design der Region genau in dieser Art und Weise … auch
   fuer externe Partner und dann fuer Kundenportale.» */
.kk-wo {
  display: flex; gap: 1px; height: 100%; min-height: 0;
  /* Ohne die Breitenklemme wird das Kind breiter als die Buehne und die
     Buehne schneidet ab — gemessen am 06.08.: .kk-wo 1191px in einer
     1105px-Buehne, die letzten 86px der Standortliste unsichtbar. */
  width: 100%; max-width: 100%; min-width: 0;
  background: var(--border);
}
.kk-wo__karte {
  display: grid; place-items: center;
  flex: 0 1 auto; aspect-ratio: 1000 / 640; max-width: 62%; min-width: 0;
  padding: 8px; overflow: hidden; background: var(--bg);
}
.kk-wo__karte .bs-karte { max-width: none; width: 100%; height: 100%; margin: 0; }
.kk-wo__liste {
  flex: 1 1 0; min-width: 0; min-height: 0;
  padding: 10px 12px 16px; overflow: auto; background: var(--bg);
}
.kk-listenkopf {
  display: flex; align-items: baseline; justify-content: space-between; gap: 8px;
  margin: 0 0 8px;
  font-size: 11px; font-weight: 600; letter-spacing: .09em; text-transform: uppercase;
  color: var(--text-tertiary);
}
/* Die Gebietswahl in der Leiste: vier Kacheln, aber flach — sie steht jetzt in
   einer Zeile ueber allem, nicht als Block auf einer eigenen Seite. */
.cp .bs-gebiete {
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 6px;
  margin: 0;
}
.cp .bs-gebiet { padding: 7px 10px; }
.cp .bs-gebiet__marke { display: none; }
.cp .bs-gebiet b { font-size: 12.5px; }
.cp .bs-gebiet__zahl { font-size: 11px; }
/* Ein Behaelter fuer beide Zeilen: die Cockpit-Leiste wird auf schmalen
   Schirmen zu einem Waagrecht-Streifen (flex-wrap: nowrap), und ohne diese
   Klammer landeten Gebietswahl und Suchfeld NEBENEINANDER — gemessen am
   06.08. auf 390px: «Einzelner Standort» stand als «Ei St 15 Sa» unter einem
   Suchfeld, das darueber lag. */
.kk-leiste { flex: 1 1 100%; min-width: 0; display: grid; gap: 8px; }
.kk-filterzeile {
  display: flex; align-items: center; gap: 8px;
}
.kk-filterzeile .kp-search { flex: 1 1 auto; min-width: 0; }
.kk-filterzeile .kp-kanton { flex: 0 0 auto; }
.kk-cfg { display: grid; gap: 12px; }
.kk-cfg .field { display: grid; gap: 5px; }
.kk-cfg .field > span {
  font-size: 11px; font-weight: 600; letter-spacing: .09em; text-transform: uppercase;
  color: var(--text-tertiary);
}
.kk-cfg .kp-seg { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 4px; }
.kk-cfg .seg__btn { white-space: nowrap; padding: 8px 4px; text-align: center; }

/* Rechts unter den Konditionen: was nach der Buchung passiert. Der Raum war
   sonst leer, und ein Kunde, der gerade Geld ausgeben soll, will genau das
   wissen — bisher stand es erst auf der letzten Seite. */
.kk-rechts__mehr { margin-top: 18px; padding-top: 14px; border-top: 1px solid var(--border); }
.kk-kopf {
  margin: 0 0 8px;
  font-size: 11px; font-weight: 600; letter-spacing: .09em; text-transform: uppercase;
  color: var(--text-tertiary);
}
.kk-rechts__mehr .bs-ablauf { margin: 0 0 14px; }
.kk-rechts__mehr .bs-ablauf__punkt { padding: 6px 0; }
.kk-rechts__mehr .bs-ablauf__satz { font-size: 11.5px; }
.kk-vertrauen { margin: 0; padding: 0; list-style: none; display: grid; gap: 8px; }
.kk-vertrauen .bs-vertrauen__punkt b { font-size: 12.5px; }
.kk-vertrauen .bs-vertrauen__punkt span:last-child { font-size: 11.5px; }

/* Linke Zone im Leerzustand: was das Netz hergibt, und ein Tap zum Anfangen. */
.kk-netz { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; margin-bottom: 4px; }
.kk-netz > div {
  padding: 9px 10px; border: 1px solid var(--border); border-radius: var(--radius-button);
  background: var(--surface-inset); text-align: center;
}
.kk-netz b { display: block; font-size: 18px; font-weight: 650; color: var(--accent-strong); font-variant-numeric: tabular-nums; }
.kk-netz span { display: block; margin-top: 1px; font-size: 11px; color: var(--text-tertiary); }
.kk-schnell { display: grid; gap: 6px; }
.kk-schnell button {
  display: grid; gap: 1px; padding: 8px 11px; text-align: left; cursor: pointer;
  border: 1px solid var(--border); border-radius: var(--radius-button);
  background: var(--surface); color: inherit; font: inherit;
}
.kk-schnell button:hover { background: var(--surface-2); border-color: var(--accent-line); }
.kk-schnell b { font-size: 13px; font-weight: 620; }
.kk-schnell span { font-size: 11px; color: var(--text-tertiary); }
.kp-hint--stop { color: var(--warn-strong); }

/* Die Standortzeile in der schmalen Cockpit-Spalte: Name oben, Ort und
   Bildschirme darunter. Gemessen am 06.08.: fuenf Spalten auf 370px schnitten
   «3 Bildschirme» zu «3 Bil…» ab — eine Zahl, die man nicht lesen kann, ist
   keine Zahl. */
.kk-wo__liste .kp-liste { max-height: none; margin: 0; overflow: visible; }
.kk-wo__liste .kp-row {
  grid-template-columns: 20px minmax(0, 1fr);
  gap: 2px 10px; padding: 8px 10px;
}
.kk-wo__liste .kp-row__name { grid-column: 2; }
.kk-wo__liste .kp-row__ort,
.kk-wo__liste .kp-row__screens,
.kk-wo__liste .kp-row__grenze {
  grid-column: 2; font-size: 11.5px;
}
.kk-wo__liste .kp-row__ort { grid-row: 2; }
.kk-wo__liste .kp-row__screens { grid-row: 2; justify-self: end; }
.kk-wo__liste .kp-row__grenze { grid-row: 3; }
/* Im Cockpit tragen die Zonen den Rahmen — ein Panel darin waere ein zweiter. */
.cp .panel { border: 0; background: transparent; padding: 0; margin: 0; }
.cp .kp-preis { margin: 0; }

@media (max-width: 1080px), (pointer: coarse) {
  .kk-wo { flex-direction: column; }
  /* Derselbe Zwilling desselben Fehlers wie `.kf-wo__karte` (Owner-Befund 6):
     ein geratenes `height:38%; min-height:180px` liess die Karte in ihrem
     Kasten schwimmen — schwarze Balken oben und unten, und weil die Schriften
     viewBox-Einheiten sind, schrumpfte jede Beschriftung mit. Der Kunde sieht
     dieselbe Karte; er bekommt dieselbe Reparatur. */
  .kk-wo__karte {
    flex: 0 0 auto; max-width: none; height: auto; min-height: 0;
    aspect-ratio: 1000 / 640; padding: 4px;
  }
  .kk-wo__karte .bs-karte { height: auto; }
  .kk-wo__liste { min-width: 0; }
  .cp .bs-gebiete { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .cp .bs-gebiet { padding: 8px 9px; gap: 8px; }
  .cp .bs-gebiet b { font-size: 12px; }
  .kk-filterzeile { flex-wrap: wrap; }
  .kk-filterzeile .kp-search { flex: 1 1 100%; }
  .kk-filterzeile .kp-kanton { flex: 1 1 100%; }
}

/* Ort-Gliederung der Standortliste — der Ort ist die Einheit, der Salon das
   Detail dahinter. Owner 05.08.: «mir gefaellt das mit den Barbers hier nicht
   rechts» und «155 Einzelpositionen — das gefaellt mir so nicht». */
/* Tabelle zu Karten, sobald der Platz nicht reicht.
   Owner 05.08.: «auf dem Smartphone hast du alles verkackt … das Smartphone
   ist genauso wichtig wie der Desktop.» Gemessen am 06.08. auf #/m/overview:
   zehn Spalten auf 390 px, sichtbar waren dreieinhalb — sieben Kennzahlen
   lagen hinter dem rechten Rand, und ein Scroll-Schatten ist kein Ersatz
   dafuer, eine Zahl lesen zu koennen.
   Opt-in per `data-label` an der Zelle: wer die Beschriftung mitgibt, bekommt
   die Kartenform; jede andere Tabelle bleibt, wie sie ist.
   ⚠️ AUSSER `.sl-table--kern`: Rechnungen und Standorte haben seit dem 01.08.
   (Karte, Position 11) ihren EIGENEN Handy-Modus — zwei Zeilen je Datensatz
   statt sieben Feldzeilen (Block bei 14053, Wächter
   scripts/_blockb_flaechen_test.mjs). Diese generische Welle hier (06.08.)
   ist spezifischer (:has zählt) und hat ihn unbemerkt überschrieben: beide
   Flächen zeigten wieder ALLE Feldzeilen PLUS den Kern-Satz doppelt
   (Bedien-Rundgang 08.08.; der Wächter war rot, lief aber in keinem
   Auslieferweg). Darum nimmt jede Regel dieses Blocks die Kern-Tabellen aus. */
@media (max-width: 640px) {
  .table-wrap:has(td[data-label]):not(:has(.sl-table--kern)) { overflow-x: visible; background: none; }
  /* `min-width` der jeweiligen Tabelle (z.B. .team-table: 640px) haelt sie
     sonst breit, obwohl sie laengst Karten sind — gemessen: 640px in einem
     390px-Fenster, 271px davon hinter dem Rand. */
  .table-wrap table:has(td[data-label]):not(.sl-table--kern) { display: block; width: 100%; min-width: 0; }
  .table-wrap table:has(td[data-label]):not(.sl-table--kern) thead { display: none; }
  .table-wrap table:has(td[data-label]):not(.sl-table--kern) tbody { display: grid; gap: 8px; }
  /* `minmax(0, 1fr)` statt `1fr`: eine 1fr-Spur ist mindestens so breit wie
     der schmalste Inhalt ihrer Zelle — ein unbrechbarer Knopf oder ein
     Betrag schob die ganze Karte 31 px ueber den Rand (Breitenprobe 03.09.,
     werbematerial@390: Zeile 391 px in 360 px). Mit 0 als Boden bleibt die
     Karte so breit wie ihre Liste; was nicht passt, bricht in der Zelle um. */
  .table-wrap table:has(td[data-label]):not(.sl-table--kern) tr {
    display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 2px 12px;
    padding: 10px 12px;
    border: 1px solid var(--border); border-radius: var(--radius-button);
    background: var(--surface);
  }
  /* `flex-wrap: wrap` + `min-width: 0` sind die Wurzel des letzten Querlaufs
     dieser Karte (gemessen 03.09., «Was man mir schuldet» auf 390 px). Die
     Zelle stand auf `nowrap`: Etikett («Gemahnt», 49.9 px, `flex: 0 0 auto`)
     und Wert mussten EINE Zeile teilen. Der Wert ist dort ein blosser
     Textknoten — ein anonymes Flex-Kind, das `min-width: auto` traegt und
     KEINE Regel annehmen kann; sein laengstes Wort («Zahlungserinnerung»,
     133 px) war damit sein Boden. 49.9 + 8 + 133 = 191 px in einer 155-px-
     Zelle: 36 px hinaus, und weil `.table-wrap` hier `overflow-x: visible`
     traegt (Zeile 1376), lief es ueber `tr`→`table`→`.table-wrap`→`.panel`
     bis in den Rumpf durch — `body.scrollWidth` 392 bei 390 px Fenster, OHNE
     Rollbalken, also unsichtbar (Hausregel: der Ueberlauf ohne Rollbalken ist
     der gefaehrlichste). Mit `wrap` faellt der Wert auf die zweite Zeile, wo
     ihm die ganze Zellbreite gehoert; `min-width: 0` nimmt der Zelle selbst
     den Boden in ihrer `minmax(0, 1fr)`-Spur, und `overflow-wrap: anywhere`
     haelt auch ein Wort, das laenger ist als die Zelle (lange Kundennamen,
     E-Mail-Adressen) drinnen. Wo Etikett und Wert heute passen, aendert sich
     nichts. */
  .table-wrap table:has(td[data-label]):not(.sl-table--kern) td {
    display: flex; align-items: baseline; justify-content: space-between;
    gap: 8px; padding: 3px 0; border: 0;
    flex-wrap: wrap; min-width: 0; overflow-wrap: anywhere;
    text-align: right !important;
  }
  /* Die erste Zelle ist der Name — sie bekommt die ganze Breite und keinen
     Beschriftungs-Vorsatz, weil «Mitarbeiter: Eric Sarpong» niemand sagt. */
  .table-wrap table:has(td[data-label]):not(.sl-table--kern) td:first-child {
    grid-column: 1 / -1; justify-content: flex-start; flex-wrap: wrap;
    padding-bottom: 7px; margin-bottom: 3px;
    border-bottom: 1px solid var(--border-subtle);
    text-align: left !important;
    font-size: 14px;
  }
  .table-wrap table:has(td[data-label]):not(.sl-table--kern) td[data-label]::before {
    content: attr(data-label);
    /* `flex: 0 0 auto`, nie `1 1 auto` mit min-width 0: das Label durfte auf
       Buchstabenbreite schrumpfen, sobald der Wert lang war — auf den
       Rechnungs-Karten stand «T i t e l» senkrecht gestapelt (Bedien-Rundgang
       08.08., 390px). Das Label behaelt seine Inhaltsbreite; der WERT bricht
       um, denn ihn will man lesen koennen. */
    flex: 0 0 auto;
    font-size: 11.5px; font-weight: 500; color: var(--text-tertiary);
    text-align: left; text-transform: none; letter-spacing: 0;
  }
  /* Steht NACH der Beschriftungs-Regel: beide sind gleich spezifisch, also
     entscheidet die Reihenfolge — davor gewann der Vorsatz und schob den Namen
     211px nach rechts. */
  .table-wrap table:has(td[data-label]):not(.sl-table--kern) td[data-label]:first-child::before { content: none; }

  /* ⚠️ AUSNAHME ZUR ERSTEN ZELLE: eine erste Zelle, die NUR ein
     Kontrollkaestchen traegt, ist kein Name — sie ist ein Griff.
     AM BILD GESEHEN (09.08., #/p/partners, 390px, scripts/_partnerliste_ui_test.mjs):
     die Regel oben gab dem leeren Auswahl-Kaestchen die ganze Kopfzeile samt
     Namens-Trennlinie und 14px; das ⋮-Menue (Spalte 2 derselben Rasterzeile)
     lag darueber statt daneben, und der Firmenname darunter wurde als
     «VP-9001 ........ Barber Nord» auseinandergezogen, weil ihn die
     Namens-Behandlung nie erreichte. Die Karte verlor damit ihre Kopfzeile.
     Also: das Kaestchen behaelt seine halbe Spalte, und die Namens-Behandlung
     wandert auf die Zelle DANEBEN. Beides steht generisch da — jede Liste mit
     Mehrfachauswahl hat dieselbe erste Zelle. */
  .table-wrap table:has(td[data-label]):not(.sl-table--kern) td:first-child:has(> input[type="checkbox"]) {
    grid-column: 1; justify-content: flex-start;
    padding-bottom: 3px; margin-bottom: 0; border-bottom: 0;
    font-size: inherit;
  }
  .table-wrap table:has(td[data-label]):not(.sl-table--kern) td:first-child:has(> input[type="checkbox"]) + td {
    grid-column: 1 / -1; justify-content: flex-start; flex-wrap: wrap;
    padding-bottom: 7px; margin-bottom: 3px;
    border-bottom: 1px solid var(--border-subtle);
    text-align: left !important;
    font-size: 14px;
  }
  .table-wrap table:has(td[data-label]):not(.sl-table--kern) td:first-child:has(> input[type="checkbox"]) + td[data-label]::before { content: none; }

  /* Eine Zelle mit LEERER Beschriftung, deren einziges Kind ein Knopf ist, hat
     keinen Gegenpart: `space-between` verteilt zwischen zwei sichtbaren Teilen,
     findet hier nur einen und legt den Griff ganz links ab — dort sieht er aus
     wie ein Wert ohne Namen. AM BILD GESEHEN (09.08., 390px): auf
     #/p/vermittlungen klebte «Öffnen →» links unten in der Karte statt rechts.
     Griffe stehen rechts, dort sucht sie der Daumen.
     ⚠️ NUR bei leerer Beschriftung. Die erste Fassung nahm JEDE Zelle mit einem
     einzelnen Knopf. Auf #/a/objections tragen «Status» und «Aktionen» aber
     eine echte Beschriftung UND einen Knopf — dort schob `flex-end` das Wort
     mit nach rechts, und die linke Beschriftungs-Kante der Karte brach auf
     halber Höhe aus (gegengeprüft am Bild, 09.08.). Wo eine Beschriftung steht,
     ist `space-between` richtig: Wort links, Griff rechts.
     Leer heisst `data-label=""` (vermittlungen, vertrieb-list, partner-detail,
     sales-signage) oder `data-label=" "` (partner-list). */
  .table-wrap table:has(td[data-label]):not(.sl-table--kern)
    td:is([data-label=""], [data-label=" "]):has(> button:only-child) {
    justify-content: flex-end;
  }
}

.kf-orte { display: grid; gap: 0; }
/* FLACH STATT KASTEN (Owner «Widget», 2026-08-13): die Ortsgruppe war eine
   umrandete, gerundete Kachel auf var(--surface). Jetzt eine flache Zeile auf
   dem Grund, von der nächsten durch eine feine Linie getrennt — der aufgeklappte
   Salon-Block darunter trägt weiter seine eigene Trennlinie (`.kf-ort > .kf-liste`). */
.kf-ort {
  border: 0; border-bottom: 1px solid var(--border); border-radius: 0;
  background: transparent;
}
.kf-ort:last-child { border-bottom: 0; }
.kf-ort__kopf {
  display: grid; grid-template-columns: minmax(0, 1fr) auto auto;
  align-items: center; gap: 10px;
  padding: 9px 11px;
}
.kf-ort__wer {
  min-width: 0; padding: 0 0 0 15px; position: relative;
  border: 0; background: transparent; color: inherit; font: inherit;
  text-align: left; cursor: pointer;
}
/* Das Dreieck sagt, dass hier etwas dahinter liegt — und in welche Richtung. */
/* SCHRIFT-BODEN, benannte Ausnahme (DESIGN.md §2 / npm run test:boden-schrift):
   10px steht hier unter dem Boden von 11px und bleibt. Was gerendert wird,
   ist kein Wort, sondern ein Zeiger — `content: '▸'`. Ein Boden fuer
   LESBARKEIT hat zu einem Richtungszeichen nichts zu sagen; auf 11px
   gehoben wuerde das Dreieck schwerer als die 12.5px-Zeile daneben. */
.kf-ort__wer::before {
  content: '▸'; position: absolute; left: 0; top: 2px;
  font-size: 10px; color: var(--text-tertiary);
  transition: transform .12s ease;
}
.kf-ort__wer[aria-expanded="true"]::before { transform: rotate(90deg); }
.kf-ort__wer:hover strong { color: var(--accent-strong); }
.kf-ort__wer strong { display: block; font-size: 13px; font-weight: 650; color: var(--text-primary); }
.kf-ort__wer small { display: block; margin-top: 2px; font-size: 11px; color: var(--text-tertiary); }
.kf-ort__kopf .kf-stepper b small {
  font-size: 11px; font-weight: 500; color: var(--text-tertiary);
}
.kf-ort > .kf-liste {
  padding: 0 11px 10px; border-top: 1px solid var(--border-subtle);
  margin-top: -1px; padding-top: 9px;
}
/* «Nicht in der Offerte» ist ebenso aufklappbar: der Ort als Ganzes ODER ein
   einzelner Salon. Owner: «einiges aus Bern, einiges aus Luzern.» */
.kf-ort--aus { opacity: .82; }
.kf-ort--aus > .kf-ort__kopf { grid-template-columns: minmax(0, 1fr) auto; }
.kf-ort--aus .kf-loc { grid-template-columns: minmax(0, 1fr) auto; padding: 7px 10px; }

/* Positionen */
.kf-pos-kopf, .kf-pos {
  display: grid; grid-template-columns: minmax(0, 1fr) auto auto auto;
  align-items: baseline; gap: 12px;
  padding: 7px 0;
  border-bottom: 1px solid var(--border);
  font-size: 12.5px; color: var(--text-secondary);
}
.kf-pos-kopf {
  font-size: 11px; font-weight: 650; letter-spacing: .05em; text-transform: uppercase;
  color: var(--text-tertiary);
}
.kf-pos b { color: var(--text-primary); font-weight: 620; font-variant-numeric: tabular-nums; }
.kf-pos em { font-style: normal; color: var(--accent-strong); font-size: 11px; }
.kf-pos.is-frei b { color: var(--text-tertiary); text-decoration: line-through; }

/* Ausgabe: drei Blöcke nebeneinander, auf schmal untereinander */
.kf-ausgabe { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 20px; }
.kf-block { min-width: 0; }
/* Der Freigabe-Riegel sitzt seit 13.08. unter dem Cockpit-Kopf statt in der
   Ausgabe: dort war er in einem eigenen Rollbereich und vom Werk verdeckt.
   Aussen bündig mit Kopf und Werk, damit er wie eine Kopfzeile wirkt. */
.kf-freigabe { flex: 0 0 auto; margin: 10px 18px 0; }
.kf-freigabe .lx-approval { margin-bottom: 0; }
@media (max-width: 1080px), (pointer: coarse) {
  .kf-freigabe { margin: 8px 12px 0; }
}

@media (max-width: 1080px), (pointer: coarse) {
  .kf-wahl { grid-template-columns: 1fr 1fr; }
  /* ⚠️ NUR `min-height` — UND DAS IST EINE HALBE REGEL. Ein Daumen ist rund:
     «alle» in der Zählregel mass 36.3 × 44 px, «max. 1» ähnlich (gemessen
     25.08.2026, Breiten-Wächter, 390-1024 px). Der Absatz zwanzig Zeilen
     tiefer sagt es für den Stepper selbst: «32px-Spalten sind auf einem Finger
     nicht sicher zu treffen». Dasselbe gilt für die kurzen Wörter der
     Segmente. */
  .kf-knopf, .kf-presets button, .kf-segment button, .kf-stepper button {
    min-height: 44px; min-width: 44px;
  }
  .kf-feld select, .kf-feld input { min-height: 44px; }
  .kf-ausgabe { grid-template-columns: 1fr; gap: 14px; }
  /* Der Stepper hielt seine HOEHE, aber nicht seine Breite: 32px-Spalten sind
     auf einem Finger nicht sicher zu treffen. Der Handy-Rundgang zaehlte am
     06.08. 114 Ziele unter 44px auf einer einzigen Flaeche — fast alle davon
     Stepper und Kreuze der Ortsliste. */
  .cp select, .cp input[type="date"], .cp input[type="number"],
  .cp input[type="search"], .cp input[type="text"] { min-height: 44px; }
  /* Die «Nur:»-Auswahlfelder der Leiste fielen auf 20px Breite zusammen —
     bedienbar nur mit dem Fingernagel. */
  .cp .kf-leiste__gruppe select { min-width: 108px; }
  .cp .kf-leiste__gruppe { flex-wrap: nowrap; }
  .kf-stepper { grid-template-columns: 44px auto 44px; }
  .kf-stepper button { min-width: 44px; }
  .kf-weg, .kf-gratis { width: 44px; height: 44px; min-width: 44px; }
  .kf-ort__wer { min-height: 44px; }
}

/* Feinheiten-Blatt: drei Spalten auf Breite, eine auf schmal. */
.kf-fein { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 24px; align-items: start; }
.kf-custom { display: grid; gap: 6px; margin-top: 8px; }
.kf-custom__zeile {
  display: grid; grid-template-columns: minmax(0, 1fr) 96px auto auto;
  align-items: center; gap: 7px;
}
.kf-custom__zeile input[type="text"], .kf-custom__zeile input[type="number"] {
  min-height: 34px; padding: 0 8px;
  border: 1px solid var(--border); border-radius: var(--radius-button);
  color: var(--text-primary); background: var(--surface-inset);
  font: inherit; font-size: 12px;
}
.kf-custom__zeile label { display: flex; align-items: center; gap: 5px; font-size: 11px; color: var(--text-tertiary); }
.kf-custom__zeile button {
  width: 28px; height: 28px; border: 0; border-radius: var(--radius-button);
  color: var(--text-tertiary); background: transparent; cursor: pointer;
}
.kf-custom__zeile button:hover { color: var(--bad); background: var(--surface-3); }

/* Eine Katalog-Zeile, die nicht mehr auf der Menge steht, aus der sie gerechnet
   wurde (31.08.2026, ZL_EINHEITEN in sales-konfigurator.js). Sie rechnet sich
   NICHT still um — sie sagt es und traegt den einen Griff, der sie richtig-
   stellt. Kein eigenes Warn-Muster: dieselbe Inset-Zeile wie ueberall, nur
   der Griff nimmt die Aufmerksamkeit (`--warn` ist die Hausfarbe fuer «schau
   hier hin, es ist nichts kaputt»). */
.kf-custom__alt {
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px;
  margin: -2px 0 4px; padding: 6px 8px;
  border-radius: var(--radius-button); background: var(--surface-inset);
  font-size: 11px; line-height: 1.35; color: var(--text-tertiary);
}
.kf-custom__alt button {
  min-height: 28px; padding: 0 10px;
  border: 1px solid var(--border); border-radius: var(--radius-button);
  color: var(--warn); background: transparent;
  font: inherit; font-size: 11px; font-weight: 600; cursor: pointer;
}
.kf-custom__alt button:hover { border-color: var(--warn); background: var(--surface-3); }

@media (max-width: 1080px), (pointer: coarse) {
  .kf-fein { grid-template-columns: 1fr; gap: 18px; }
  .kf-custom__zeile { grid-template-columns: 1fr 1fr; }
  /* Der Griff-Boden des Hauses gilt auch hier (44px, DESIGN.md). */
  .kf-custom__alt button { min-height: 44px; padding: 0 14px; }
}

/* Positionen mit Preis-Freiheit: Regelpreis daneben, damit der Gegenwert
   sichtbar bleibt, wenn jemand eine Sonderkondition setzt. */
.kf-pos-kopf, .kf-pos { grid-template-columns: minmax(0, 1fr) 78px 96px 54px 96px auto; }
.kf-pos__wer { min-width: 0; }
.kf-pos__regel { font-size: 11px; color: var(--text-tertiary); font-variant-numeric: tabular-nums; }
.kf-pos input[type="number"] {
  width: 100%; min-height: 32px; padding: 0 7px;
  border: 1px solid var(--border); border-radius: var(--radius-button);
  color: var(--text-primary); background: var(--surface-inset);
  font: inherit; font-size: 12px; font-variant-numeric: tabular-nums; text-align: right;
}
.kf-pos.is-ov input[type="number"] { border-color: var(--accent-line); color: var(--accent-strong); }
.kf-pos__tun { display: flex; gap: 4px; }
.kf-pos__tun button {
  min-height: 28px; padding: 0 8px;
  border: 1px solid var(--border); border-radius: var(--radius-button);
  color: var(--text-tertiary); background: transparent;
  font: inherit; font-size: 11px; cursor: pointer;
}
.kf-pos__tun button[aria-pressed="true"] {
  color: var(--accent-strong); border-color: var(--accent-line); background: var(--accent-soft);
}
.kf-pos__tun button:hover { color: var(--text-primary); }

/* Standort-Blatt: Suche, Gratis-Schalter, Dazunehmen */
/* DIE ORTSSUCHE DER WO-FLAECHE. Sie stand bis 09.08. in der Leiste — am
   Handy also hinter dem Regler-Symbol, waehrend die Ortsliste darunter auf
   «Suche eingrenzen» verwies (Owner-Befund c1 B15, c3 B26). Jetzt steht sie
   ueber der Liste, die sie eingrenzt, und bleibt beim Scrollen stehen: nach
   dreissig Ortsgruppen waere sie sonst wieder unauffindbar — genau der
   Befund. Das Feld selbst traegt `.kf-feld` und damit die Form jedes anderen
   Feldes der Flaeche; hier steht nur, wo es klebt. Die negativen Raender
   heben den Innenabstand der Liste auf, damit der Streifen ueber die volle
   Breite deckt und keine Zeile daneben durchscheint. */
.kf-suche {
  position: sticky; top: 0; z-index: 2;
  margin: -12px -14px 10px; padding: 12px 14px 10px;
  background: var(--bg); border-bottom: 1px solid var(--border);
}
.kf-loc { grid-template-columns: minmax(0, 1fr) auto auto auto; }
  .kf-ort__kopf { grid-template-columns: minmax(0, 1fr) auto auto; }
.kf-loc.is-aus { grid-template-columns: minmax(0, 1fr) auto; opacity: .78; }
.kf-gratis {
  min-width: 34px; min-height: 32px; padding: 0 8px;
  border: 1px solid var(--border); border-radius: var(--radius-button);
  color: var(--text-tertiary); background: transparent;
  font: inherit; font-size: 11.5px; font-weight: 650; cursor: pointer;
}
.kf-gratis[aria-pressed="true"] {
  color: var(--accent-strong); border-color: var(--accent-line); background: var(--accent-soft);
}
.kf-dazu {
  min-height: 32px; padding: 0 11px;
  border: 1px solid var(--accent-line); border-radius: var(--radius-button);
  color: var(--accent-strong); background: transparent;
  font: inherit; font-size: 11px; font-weight: 650; letter-spacing: .06em; text-transform: uppercase; cursor: pointer;
}
.kf-dazu:hover { background: var(--accent-soft); }
.kf-liste--aus { margin-top: 6px; }

/* Woraus die Offerte besteht — die Zahlen, die die Zone «Kunde & Korb»
   beantwortet. Form nach der Referenz `13_25_27.png` (Kachelblock auf dem
   Handy): grosse Zahl, kleines Wort. Ohne Icon-Quadrate (DESIGN.md-Verbot)
   und ohne Rahmen um jede Kachel — getrennt wird mit Hairlines wie im Rest
   der App. */
/* Der Leerzustand des Korbs — er zeigt den AUSGANG, statt eine schwarze
   Fläche zu sein (ZIELBILD «leere Flächen zeigen den Ausgang»).
   Am Rechner bleibt er knapp: dort ist die linke Spalte 210 px breit und
   kurz — ein Icon-Ring und zwei Knöpfe liessen sie überlaufen (der Wächter
   «keine Seitenspalte länger als ihre Höhe» misst genau das), und die Karte
   steht dort ohnehin daneben, die Wege sind also schon offen. */
/* ENTFERNT, nicht ersetzt: `.kf-leer` · `.kf-leer .empty-state__icon` ·
   `.kf-leer h3` · `.kf-leer p` · `.kf-leer__tun` (+ die ganze Handy-Fassung im
   `@media (max-width: 1080px), (pointer: coarse)`-Block).
   GEFALLEN 22.08.2026 — sie sind Zeichen fuer Zeichen nach docs/design/grund.css
   gezogen und heissen dort `.empty-state--spalte` / `.empty-state__tun`.
   WARUM: das hier war die einzige der vierzehn Eigenbauten, die den Kanon nicht
   ersetzte, sondern ihn in DIESER Flaeche neu einkleidete — Icon und Titel weg,
   linksbuendig, 11px tertiaer statt 13.5px sekundaer. Dieselbe Klasse sah damit
   im Konfigurator anders aus als ueberall sonst, und keine Namensliste konnte
   das finden (die zweite, namenlose Fassung dieser Sorte war `.gz .empty-state`
   in patch-zentrale.css). Was der Kanon je nach Breite kann, steht beim Kanon.
   Nichts an der Erscheinung aendert sich: die Regeln sind unveraendert, nur
   umbenannt und einen Ort weiter oben. */

/* Am Desktop stehen diese drei Zahlen seit jeher in der Kopfzeile der
   Standortliste und passen dort in EINE Zeile — die schmale linke Spalte
   (210 px) hat für einen Kachelblock keinen Platz und liefe über. Der Block
   ist die HANDY-Antwort auf die halbleere Zone. */
.kf-zahlen { display: none; }
@media (max-width: 1080px), (pointer: coarse) {
  /* FLACH STATT KASTEN (Owner «Widget», 2026-08-13 — Nachtrag Prüfblick):
     dieser Handy-Zahlenblock war ein gerundeter Kasten (border-radius +
     overflow:hidden) aus vier abhebenden var(--surface)-Kacheln, getrennt durch
     die 1px-Fugen einer var(--border)-Grundfläche — GENAU das Karten-Idiom, das
     für .kf-chip/.kf-register/.kf-stueck entfernt wurde, nur in Rasterform und
     nur am Handy. Am Desktop ist der Block `display:none`, deshalb blieb er auf
     den 1680-Bildern unentdeckt. Jetzt vier flache Zahl-über-Label-Paare auf
     demselben Grund, gruppiert allein durch Abstand — dieselbe Sprache wie
     .kf-chips. Kein Rahmen, kein Radius, kein abhebender Grund. */
  .kf-zahlen {
    display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 12px 20px; margin: 2px 0 6px;
    border: 0; border-radius: 0; overflow: visible;
    background: transparent;
  }
  /* … und dort tritt der Nachsatz in der Listen-Kopfzeile ab: er sagte
     dasselbe ein zweites Mal und brach auf 390 px auf zwei Zeilen. */
  .kf-kopf__zahlen { display: none; }
}
.kf-zahlen > div {
  display: flex; flex-direction: column; gap: 2px;
  /* Kein Kachel-Innenabstand mehr: die 9px/11px waren der Rand der Kachel; die
     Höhe trägt jetzt die Zahl über dem Label, der Abstand kommt vom gap. */
  padding: 0;
  background: transparent;
}
.kf-zahlen b {
  font-size: 20px; font-weight: 650; letter-spacing: -.01em;
  font-variant-numeric: tabular-nums; color: var(--text-primary);
}
.kf-zahlen span {
  font-size: 11px; font-weight: 600; letter-spacing: .05em; text-transform: uppercase;
  color: var(--text-tertiary);
}

@media (max-width: 1080px), (pointer: coarse) {
  .kf-pos-kopf { display: none; }
  /* Eine Position ist am Handy eine KARTE, keine gebrochene Tabellenzeile:
     der Name über die volle Breite, darunter Preis, Anzahl, Total und die
     Griffe in EINER Zeile. Vorher stapelten sich «× 1», «444.00» und «gratis»
     je auf eigenen Zeilen — vier Zeilen für eine Position, und auf 390 px
     passten keine drei Positionen ins Bild (Owner-Befund 5, 08.08.). */
  /* Feste erste Spalte, nicht `auto`: das Preisfeld traegt `width:100%` und
     zog eine `auto`-Spalte auf seine Wunschbreite — Total und Griffe lagen
     dann uebereinander (im Bild gesehen, 08.08.). */
  .kf-pos {
    grid-template-columns: 104px auto minmax(0, 1fr) auto;
    row-gap: 7px; column-gap: 9px; align-items: center; padding: 10px 0;
  }
  .kf-pos__regel { display: none; }
  .kf-pos > .kf-pos__wer { grid-column: 1 / -1; font-size: 13.5px; color: var(--text-primary); }
  /* Der Betrag ist der WERT dieser Zeile — er wird gelesen, nicht überflogen
     (Referenz: Werte 15–17 px). */
  .kf-pos > b { font-size: 15px; text-align: right; }
  .kf-pos input[type="number"] { min-height: 44px; font-size: 16px; }
  .kf-gratis, .kf-dazu, .kf-pos__tun button { min-height: 44px; }
  /* Der Korb-Eintrag trägt einen Namen, keine Fussnote. */
  .kf-stueck__wer strong { font-size: 15px; }
  .kf-stueck__wer small { font-size: 12px; }
  .kf-ort__wer strong { font-size: 15px; }
  .kf-ort__wer small { font-size: 12px; }
}

.kf-feld textarea {
  width: 100%; min-height: 68px; padding: 8px 10px;
  border: 1px solid var(--border); border-radius: var(--radius-button);
  color: var(--text-primary); background: var(--surface-inset);
  font: inherit; font-size: 12.5px; line-height: 1.45; resize: vertical;
}
.kf-feld textarea:focus-visible, .kf-feld input[type="date"]:focus-visible {
  outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px rgba(var(--accent-rgb), .20);
}
.kf-feld input[type="date"], .kf-feld input[type="text"], .kf-feld input[type="search"] {
  width: 100%; min-height: 38px; padding: 0 10px;
  border: 1px solid var(--border); border-radius: var(--radius-button);
  color: var(--text-primary); background: var(--surface-inset);
  font: inherit; font-size: 13px;
}
@media (max-width: 1080px), (pointer: coarse) {
  .kf-feld input[type="date"], .kf-feld input[type="text"], .kf-feld input[type="search"] { min-height: 44px; }
}

/* Kalkulator im Cockpit: die Regler stehen in schmalen Zonen untereinander,
   nicht im Raster — ein Raster erzwingt dort dreizeilige Beschriftungen. */
.calc-felder { display: grid; gap: 10px; }
.calc-felder .field, .calc-felder .field--narrow, .calc-felder .field--wide {
  display: block; width: 100%; max-width: none;
}
.calc-felder .field > span {
  display: block; margin-bottom: 4px;
  font-size: 11px; font-weight: 600; letter-spacing: .04em; text-transform: uppercase;
  color: var(--text-tertiary);
}
.calc-felder input, .calc-felder select {
  width: 100%; min-height: 38px; padding: 0 10px;
  border: 1px solid var(--border); border-radius: var(--radius-button);
  color: var(--text-primary); background: var(--surface-inset);
  font: inherit; font-size: 13px; font-variant-numeric: tabular-nums;
}
.calc-felder .so-hint { margin-top: 3px; font-size: 11px; color: var(--text-tertiary); }
@media (max-width: 1080px), (pointer: coarse) {
  .calc-felder input, .calc-felder select { min-height: 44px; }
}

.calc-felder--breit { grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 14px; }

/* Die Leiste ueber allen Zonen — traegt, was ueberall gilt (Gebiet, Zaehlregel).
   Sie bleibt sichtbar, egal in welcher Zone gearbeitet wird. */
.cp__leiste {
  flex: 0 0 auto;
  display: flex; align-items: center; flex-wrap: wrap; gap: 10px 18px;
  padding: 10px 18px;
  border-bottom: 1px solid var(--border);
  background: var(--surface-1);
}
@media (max-width: 1080px), (pointer: coarse) {
  .cp__leiste { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; padding: 9px 12px; }
  .cp__leiste::-webkit-scrollbar { display: none; }
}

/* ---- Leiste: was über allen Zonen gilt ----------------------------------- */
.kf-leiste__gruppe { display: flex; align-items: center; gap: 8px; }
.kf-leiste__wort {
  font-size: 11px; font-weight: 600; letter-spacing: .05em; text-transform: uppercase;
  color: var(--text-tertiary); white-space: nowrap;
}
.kf-leiste__gruppe .kf-segment { margin: 0; }
.kf-leiste__gruppe select {
  min-height: 32px; padding: 0 9px;
  border: 1px solid var(--border); border-radius: var(--radius-button);
  color: var(--text-primary); background: var(--surface-inset);
  font: inherit; font-size: 12px;
}

/* ---- Der Korb: woraus die Offerte besteht -------------------------------- */
/* FLACH STATT KASTEN (Owner «Widget», 2026-08-13): jedes Korb-Stueck war eine
   akzent-hinterlegte, umrandete Karte. Jetzt eine flache Zeile auf dem Grund,
   von der naechsten nur durch eine feine Linie getrennt — genau wie die
   Standortliste (`.kf-loc`). Das Akzent-Symbol links bleibt das Zeichen, dass
   das Stueck in der Offerte liegt; kein Rahmen, kein Radius, kein Grund. */
.kf-korb { display: grid; gap: 0; }
.kf-stueck {
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center; gap: 8px;
  padding: 8px 2px;
  border: 0; border-bottom: 1px solid var(--border); border-radius: 0;
  background: transparent;
}
.kf-stueck:last-child { border-bottom: 0; }
.kf-stueck .cp__ic { width: 17px; height: 17px; color: var(--accent-strong); }
.kf-stueck__wer { min-width: 0; }
.kf-stueck__wer strong { display: block; font-size: 12.5px; font-weight: 620; color: var(--text-primary); }
.kf-stueck__wer small { display: block; margin-top: 2px; font-size: 11px; color: var(--text-secondary); }
.kf-stueck button {
  width: 26px; height: 26px; border: 0; border-radius: var(--radius-button);
  color: var(--text-secondary); background: transparent; font: inherit; cursor: pointer;
}
.kf-stueck button:hover { color: var(--bad); background: var(--surface-3); }

/* ---- Wo: Karte UND Liste zusammen, nicht auf zwei Blättern --------------- */
/* Die Kartenspalte ist so breit, wie die Karte bei dieser Hoehe wirklich
   braucht — nicht breiter. Owner 05.08.: «Die schwarze leere Flaeche, das
   hasse ich» und «keine unlogischen, leeren Raeume». Gemessen am 06.08. stand
   die Karte 428px breit in einer 600px-Spalte: 172px schwarzes Nichts links
   und rechts, waehrend die Standortliste daneben um 198px ueberlief.
   `aspect-ratio` loest das ohne eine Zeile JavaScript: die Hoehe bestimmt die
   Breite, der Rest gehoert der Liste. */
/* DURCHGEHENDE FLÄCHE, KEIN GERASTERTER KASTEN (Owner «Widget», 2026-08-13):
   `.kf-wo` trug `gap:1px` auf `background:var(--border)` und zog damit eine
   Rinne zwischen Werkzeug-Leiste und der Karte-Liste-Fläche — zusammen mit der
   senkrechten Rinne (Karte|Liste) las sich das wie der obere Rand eines
   Kastens. Die Werkzeug-Leiste fliesst jetzt ohne Linie in die Fläche; getrennt
   wird nur noch Karte von Liste (die eine begründete feine Linie, `.kf-wo__flaeche`).
   Der Grund wird transparent, weil ohne Rinne keine Randfarbe mehr durchscheinen
   soll (am Handy sonst ein heller Streifen unter einer kurzen Liste). */
.kf-wo {
  display: flex; gap: 0; height: 100%; min-height: 0;
  background: transparent;
}
.kf-wo__karte {
  display: grid; place-items: center;
  flex: 0 1 auto; aspect-ratio: 1000 / 640; max-width: 62%; min-width: 0;
  padding: 8px; overflow: hidden; background: var(--bg);
}
.kf-wo__karte .bs-karte { max-width: none; width: 100%; height: 100%; margin: 0; }
.kf-wo__liste {
  flex: 1 1 0; min-width: 280px; min-height: 0;
  padding: 12px 14px 18px; overflow: auto; background: var(--bg);
}

.kf-block--breit { grid-column: span 2; }

@media (max-width: 1080px), (pointer: coarse) {
  .kf-wo { flex-direction: column; }
  /* Owner-Befund 6 (08.08.): «Karte fix 190 px mit unlesbaren Labels, obwohl
     das Werk 512 px frei hat.» Zwei Fehler in einer Zeile.
     (1) `height: 38%; min-height: 190px` war ein GERATENES Mass. Die Karte
     zeichnet aber nach viewBox 1000×640 und passt sich hinein: in einem
     205 px hohen Kasten auf 352 px Breite blieb der Massstab bei 0.32 statt
     0.352 — oben und unten schwarze Balken, und JEDE Beschriftung schrumpfte
     mit. Jetzt bestimmt die Breite die Höhe (`aspect-ratio`), die Karte füllt
     ihren Kasten randlos, und die frei werdende Höhe geht an die Standort-
     liste — an Inhalt, nicht an Leere.
     (2) Die Schriften sind viewBox-Einheiten: 26 Einheiten × Massstab 0.352
     sind 9 px, die Stadtnamen (17) waren 6 px. Darum werden sie hier
     hochgesetzt, bis sie über dem 11-px-Floor (DESIGN §2) liegen. */
  .kf-wo__karte {
    flex: 0 0 auto; max-width: none; height: auto; min-height: 0;
    aspect-ratio: 1000 / 640; padding: 4px;
  }
  .kf-wo__karte .bs-karte { height: auto; }
  .kf-wo__liste { min-width: 0; }
  .kf-stueck button { width: 44px; height: 44px; }
  .kf-block--breit { grid-column: auto; }
}

/* Die Beschriftungen der Karte auf schmalen Schirmen. Gilt für JEDE
   `.bs-karte` (Konfigurator und Kundenportal) — beide zeichnen dieselbe
   Geometrie in derselben viewBox. */
@media (max-width: 560px) {
  .bs-kanton__zahl { font-size: 38px; }
  .bs-ort__zahl, .bs-ort__wort, .bs-punkt__wort { font-size: 34px; }
  .bs-ort__wort, .bs-punkt__wort { stroke-width: 6px; }
  /* Die neun Städte sind ausdrücklich «stille Orientierung», kein Inhalt.
     Auf 352 px Kartenbreite waren ihre Namen 6 px hoch und lagen zu neunt
     übereinander; gross genug gesetzt verdecken sie die Kantonszahlen, die
     die eigentliche Aussage tragen. Der Punkt bleibt als Landmarke, das Wort
     tritt ab — die Kantonsflächen sind auf dieser Grösse die Orientierung. */
  .bs-stadt__wort { display: none; }
}

/* Selteneres öffnet sich, statt dauerhaft eine Spalte zu belegen. */
.kf-mehr { margin-top: 10px; border-top: 1px solid var(--border); padding-top: 8px; }
/* Knapp: kein eigener Rahmen, keine Extra-Zeile — der Aufklapper hängt an der
   letzten Kondition statt eine eigene zu sein. */
.kf-mehr--knapp { margin-top: 2px; padding-top: 0; border-top: 0; }
.kf-mehr--knapp > summary { padding: 2px 0; }
.kf-mehr > summary {
  list-style: none; cursor: pointer;
  font-size: 11px; font-weight: 650; letter-spacing: .05em; text-transform: uppercase;
  color: var(--text-tertiary); padding: 6px 0;
}
.kf-mehr > summary::-webkit-details-marker { display: none; }
.kf-mehr > summary::after { content: " ▾"; }
.kf-mehr[open] > summary::after { content: " ▴"; }
.kf-mehr > summary:hover { color: var(--accent-strong); }
.kf-mehr .kf-fein { grid-template-columns: 1fr; gap: 14px; }

.kf-leiste__gruppe input[type="date"] {
  min-height: 32px; padding: 0 9px;
  border: 1px solid var(--border); border-radius: var(--radius-button);
  color: var(--text-primary); background: var(--surface-inset);
  font: inherit; font-size: 12px;
}
.kf-pruefen {
  min-height: 32px; padding: 0 11px;
  border: 1px solid var(--accent-line); border-radius: var(--radius-button);
  color: var(--accent-strong); background: transparent;
  font: inherit; font-size: 11.5px; font-weight: 620; cursor: pointer;
}
.kf-pruefen:hover { background: var(--accent-soft); }
.kf-pruefen:disabled { opacity: .5; cursor: default; }
.kf-zeile b.is-warn { color: var(--bad); }
.kf-belegt { display: grid; gap: 4px; margin-top: 6px; }
@media (max-width: 1080px), (pointer: coarse) {
  .kf-leiste__gruppe input[type="date"], .kf-pruefen { min-height: 44px; }
  /* Touch-Floor, der WIRKT (Bedien-Rundgang 08.08., WebKit 390: Selects
     108×32, Zonen-Anker und kf-add-Knoepfe 36px, Schalter-Label 30px).
     Der 44er-Block bei «.cp select …» steht VOR diesen Basisregeln und
     verliert bei gleicher Spezifitaet — Hausgesetz «Mobile-@media NACH der
     Basis» (Memory project_css_cascade_mobile). Darum stehen die Ziele hier,
     am Ende der Konfigurator-Basis, ein zweites Mal. */
  .kf-leiste__gruppe select { min-height: 44px; }
  .kf-add { min-height: 44px; }
  .cp__zonenwahl button { min-height: 44px; }
  .kf-schalter { min-height: 44px; }
}

/* Positionen: der Kunde sieht Orte. Die Salons dahinter klappen auf — nichts
   verschwindet, aber die Offerte hat 40 Zeilen statt 155. */
.kf-pos-titel { display: flex; align-items: center; justify-content: space-between; gap: 14px; flex-wrap: wrap; }
.kf-pos-titel .kf-kopf { margin: 0; }
.kf-segment--klein button { min-height: 28px; font-size: 11.5px; padding: 0 9px; }
.kf-pos__auf > summary {
  list-style: none; cursor: pointer;
  font-size: 12.5px; color: var(--text-primary);
}
.kf-pos__auf > summary::-webkit-details-marker { display: none; }
/* SCHRIFT-BODEN, benannte Ausnahme (wie `.kf-ort__wer::before` oben): das
   Auf-/Zu-Dreieck des Deckels ist ein Zeichen, kein Text. */
.kf-pos__auf > summary::after { content: " ▾"; color: var(--text-tertiary); font-size: 10px; }
.kf-pos__auf[open] > summary::after { content: " ▴"; }
.kf-pos__auf > summary:hover { color: var(--accent-strong); }
.kf-pos__subs {
  display: grid; grid-template-columns: minmax(0, 1fr) auto auto;
  gap: 3px 12px; margin: 6px 0 2px 10px; padding-left: 10px;
  border-left: 2px solid var(--border);
  font-size: 11px; color: var(--text-tertiary);
}
.kf-pos__subs b { color: var(--text-secondary); font-variant-numeric: tabular-nums; font-weight: 600; }
@media (max-width: 1080px), (pointer: coarse) {
  /* 03.09., Owner-Bild 390 px: «ORT» lag über «STANDORT». Vier Versal-Wörter
     teilten sich die Restbreite neben dem Titel; jeder Knopf bekam ~60 px,
     «STANDORT» braucht 90. Die Wahl nimmt am Handy die volle Zeile und bricht
     um, wenn es doch nicht reicht. */
  .kf-segment--klein { flex: 1 1 100%; flex-wrap: wrap; }
  .kf-segment--klein button { flex: 1 1 auto; min-height: 44px; }
  .kf-pos__subs { grid-template-columns: 1fr auto; }
}

/* Der Finger-Vertrag der Karte (FORENSIK BM/M2). Pauschal `none` machte sie am
   Handy zur toten Fläche: kein Pinch ⇒ nie Zoom ⇒ nie Pan — und ein Finger
   darauf bewegte nicht einmal die Zone weiter, obwohl die Karte 38 % der
   Bühnenhöhe belegt. Der Grundzustand gehört deshalb der Umgebung; die Karte
   nimmt sich ZWEI Finger selbst (schweiz-karte.js, `fingerAn`) und beansprucht
   den einen erst, wenn wirklich gezoomt ist. Das gilt auch für Karten ohne
   Zoom-Verdrahtung (Portalkarten) — die waren ebenso unbewischbar. */
.bs-karte[data-karte-zoombar] { touch-action: pan-x pan-y; }
.bs-karte[data-karte-zoombar][data-karte-gezoomt="true"] { touch-action: none; }
.bs-karte[data-karte-zoombar]:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

body.lx-einbau .cp__kopf { grid-template-columns:auto minmax(0,1fr) auto; }
body.lx-einbau .cp__kopf>.cp__marke { display:none; }
body.lx-einbau .cp__zurueck { display:inline-flex; align-items:center; justify-content:center; flex:0 0 44px; width:44px; height:44px; padding:0; border:1px solid var(--line); border-radius:var(--radius-button); background:transparent; color:var(--text); cursor:pointer; }
body.lx-einbau .cp__zurueck .cp__ic { width:20px; height:20px; }
body.lx-einbau .cp__zurueck:focus-visible { outline:2px solid var(--accent); outline-offset:2px; }
body.lx-einbau .cp__zurueck:hover { background:var(--surface); }

/* ============================================================
   Patch-Integration — Namensraum lx-offertenliste; Quelle: docs/design/patch-offertenliste.css
   Der Block wird bei Integration als GANZES ersetzt, nie editiert.
   Die Offerten-Liste am Handy (Owner-Befund 08.08.): eigene Fläche,
   eigene Datei — der Rechner-Block darüber trägt `cp-/kf-`, hier hängt
   jede Regel an `body.lx-offertenliste`. Steht am Dateiende und damit
   NACH allen Basisregeln (Memory project_css_cascade_mobile).
   ============================================================ */
/* `.vk-kopf__akt` ist am 19.08.2026 gefallen: mit `sales-offers.js` trug die
   LETZTE Fläche ihren eigenen Kopf. Die Zeilen sind nicht gelöscht, sondern
   umgehängt — auf den Handgriff-Bereich des EINEN Seitenkopfs innerhalb der
   Marke `.vk-kopf`. So bleibt das Handy-Bild genau, wie es war, und es gibt
   trotzdem nur noch eine Hülle. */
/* ===========================================================================
   FLÄCHE 2 — DIE OFFERTEN-LISTE AM HANDY (`#/v/offers`)
   ---------------------------------------------------------------------------
   GRENZE: alles hier hängt an `body.lx-offertenliste` (gesetzt von
   sales-offers.js, abgeräumt in destroy()) UND am Handy-Breakpoint. Der
   Desktop sieht keine einzige dieser Regeln. Der `vk-`-Block weiter oben ist
   als «wird als GANZES ersetzt, nie editiert» gekennzeichnet — deshalb steht
   hier nichts drin, sondern alles hier unten.

   NUR-HANDY-BAUTEILE, am Desktop aus. Die Zeile steht bewusst AUSSERHALB
   des @media-Blocks: stünde sie darin, hätte das Element am Desktop gar
   keine Regel und stünde dort als unformatierter Kasten (derselbe Schaden
   wie bei `.cp__zurueck`, style.css:15287).

   ⚠️ SIE HÄNGT AN `--handy`, NICHT AN `.vk-suche`. Beim ersten Anlauf stand
   hier `.vk-suche { display: none; }` — und schaltete damit das Suchfeld der
   KUNDENLISTE ab, auf dem Desktop wie am Handy. `.vk-suche` ist ein geteiltes
   Bauteil (sales-customers.js:121, wissen.js:87, style.css:13142). Gefunden
   hat es der Geometrie-Abzug gegen HEAD: `#/v/customers` verlor bei 1440 px
   fünf Elemente. Ohne diesen Abzug wäre der Schaden mit ausgeliefert worden —
   niemand sieht beim Handy-Umbau auf die Kundenliste.
   Die Offerten-Liste bekommt das Feld nur am Handy, weil nur dort die
   Befehlszeile aus dem Kopf gefallen ist; am Desktop findet ⌘K weiterhin
   alles, und ein zweites Suchfeld daneben wäre die verbotene zweite Tür
   (EINHEIT §3.1).

   GEMESSEN 08.08. am echten Mass 390×620, vor diesem Block:
     Navigation 165 px (Kopfzeile 52 · Tür-Reiter 45 · Daumenleiste 68)
     + Seitentitel «Offerten» + Knopfblock + vier Kennzahl-Kacheln
     = der erste Bildschirm zeigte NICHT EINE Offerte. Die Filterzeile lag
     unter der Daumenleiste, der schwebende Plus-Knopf schnitt die Kachel
     «Auftragswert im Bes…» ab.
   =========================================================================== */
.vk-suche--handy { display: none; }

/* 05.09.: `(pointer: coarse)` ist aus dieser Abfrage gefallen — der Arm hat
   nie etwas anderes gemeint als «schmal» (jede Begruendung in diesem Block
   nennt Hoehe und 390 px), aber er zog das Telefon-Raster auf JEDES grobe
   Zeigegeraet: Tafel quer (1366 px) und Beruehrbildschirm (1920 px) standen
   ohne Werkzeugzeile da. Der Griff-Boden bleibt, wo er hingehoert — im
   Schirm (grund.css:831/:998). Die JS-Seite haelt denselben Wert
   (HANDY_ABFRAGE, views/sales-offers.js). */
@media (max-width: 1080px) {

  /* 1 — DER DOPPELTE KOPF FÄLLT.
         «Offerten» stand dreimal auf demselben Bildschirm: in der Kopfzeile,
         im aktiven Tür-Reiter und als Seitentitel. Der aktive Reiter sagt es
         bereits — ein Titel, der nur wiederholt, ist verlorene Höhe. Der
         Knopf «+ Neue Offerte» fällt mit, weil der schwebende Plus-Knopf
         (`.qc`) genau das schon tut; zwei Wege zum selben Ziel, zwei
         Fingerbreit Platz. */
  /* DER KNOPF ZUM NEUANLEGEN STEHT IN DER FILTERZEILE — null zusätzliche Höhe,
     und nichts schwebt über dem Inhalt.
     Der Weg dahin: `.vk-kopf` und `.vk-leiste` sind Geschwister im selben
     Behälter. Ein Raster auf dem Behälter setzt beide in DIESELBE Zeile,
     ohne eine einzige Zeile Markup zu ändern (und damit ohne den Desktop
     anzufassen, der dieses Raster nie sieht).
     Die drei Fassungen davor und warum sie fielen — gemessen, nicht geraten:
       · eigenes Knopfband oben: 46 px, und darauf stand NUR ein Knopf,
         rechtsbündig auf leerer Fläche — genau die Rüge in neuer Form;
       · schwebender Plus-Knopf: null Höhe, aber er deckte das Zustands-
         Abzeichen der zweiten Karte zu («Gesen…»), und ein Element, das
         Inhalt verdeckt, um eine sichtbare Handlung anzubieten, hat keinen
         Grund;
       · Knopf weglassen: dann führt vom Handy kein Weg zur neuen Offerte. */
  /* NACHTRAG 08.08., ZWEITE RUNDE — der Knopf stand in der FILTERZEILE.
     Owner-Befund am Bild: «Die Filterzeile wird vom ‹+ Neu› verdeckt —
     ‹Angenommen› bricht zu ‹A…› hinter dem Knopf ab.» Nachgemessen auf
     390×620: die vier Chips brauchen 334 px, die Zeile hatte neben dem Knopf
     noch 247 px — «Angenommen» lief 88 px über die Kante und verschwand
     zusätzlich unter der Blende. Ein Knopf, der einen Filter verschluckt, ist
     schlimmer als ein Knopf woanders.
     Der Knopf zieht darum eine Zeile höher — zum SUCHFELD, das der Kopf-
     Umbau ohnehin in die Fläche bringt (die Lupe ist aus dem Handy-Kopf
     gefallen). Zwei Handgriffe teilen sich eine Zeile, die es sowieso gibt;
     die Filterzeile bekommt die volle Breite, ohne dass eine Zeile dazukommt. */
  body.lx-offertenliste .vk {
    display: grid;
    /* DREI Spalten (05.09., Runde 2): Suchfeld · Griff «Ansicht» · «+ Neu» —
       Begruendung im Abschnitt «DREI SPALTEN» unten. Der Wert steht HIER,
       weil derselbe Waehler zweimal im Blatt eine Doppelung waere, die der
       Doppel-Waechter (`_stil_einmalig_test.mjs`) zaehlt. */
    grid-template-columns: minmax(0, 1fr) auto auto;
    align-items: center;
    column-gap: 10px;
  }
  /* Drei Zeilen statt vier: die Werkzeugzeile ist weg (Abschnitt 3 unten),
     der Kachelblock trägt jetzt Zahlen UND Filter. */
  /* 03.09., Owner: «ich will ja OBEN einstellen, was will ich als erstes» —
     die Umfangswahl (Meine · Alle · Externer Vertrieb · Wessen) steht zuoberst. */
  /* DREI SPALTEN, WEIL DER GRIFF «ANSICHT» MITFAEHRT (05.09.2026, Runde 2).
     Er stand auf dieser Flaeche als einziger der vierzehn Listen ueberhaupt
     nicht — «bildschirm grössee dürfen nie ein hinderniss sein» (25.08.).
     Er bekommt KEINE eigene Zeile: die Suchzeile gibt es ohnehin, sie traegt
     schon «+ Neu», und der Griff ist ein Knopf von 44 px. Gemessen auf
     390 px: Suchfeld 1fr, Griff ~72 px, «+ Neu» ~70 px. Die Spalten selbst
     stehen in der `.vk`-Regel oben (ein Waehler, eine Regel). */
  body.lx-offertenliste .vk > [data-slot="sicht"] { grid-column: 1 / -1; grid-row: 1; }
  body.lx-offertenliste .vk > [data-slot="kpis"]  { grid-column: 1 / -1; grid-row: 2; }
  body.lx-offertenliste .vk > .vk-suche--handy    { grid-column: 1;      grid-row: 3; }
  body.lx-offertenliste .vk > .vk-leiste          { grid-column: 2;      grid-row: 3; }
  body.lx-offertenliste .vk > .vk-kopf            { grid-column: 3;      grid-row: 3; }
  body.lx-offertenliste .vk > [data-slot="table"] { grid-column: 1 / -1; grid-row: 4; min-width: 0; }

  /* Das Suchfeld ist das Bauteil aus style.css:13142 (Kundenliste, Wissen) —
     hier nur auf Fingermass gebracht. Es ersetzt am Handy die Lupe aus dem
     Kopf, und zwar richtig: dort war es ein Knopf, der die Befehlspalette
     öffnete (für eine Tastatur gebaut), hier ist es ein Feld, das die Liste
     vor den Augen kürzer macht. */
  body.lx-offertenliste .vk-suche--handy {
    display: flex; height: auto; min-height: 44px; max-width: none;
    margin: 0 0 8px;
  }
  body.lx-offertenliste .vk-suche--handy input {
    /* 16px ist keine Geschmacksfrage: unter 16px zoomt iOS beim Antippen in
       das Feld hinein, und die ganze Fläche steht danach verrutscht da. */
    font-size: 16px;
  }
  body.lx-offertenliste .vk-kopf {
    display: block; margin: 0 0 12px; min-height: 0;
  }
  body.lx-offertenliste .vk-kopf h1 { display: none; }
  body.lx-offertenliste .vk-kopf .lx-seitenkopf__akt { width: auto; margin: 0; }
  /* NUR NOCH DA, WO ES DEN GRIFF UEBERHAUPT GIBT (05.09.2026): steht die
     Daumenleiste mit «Neu» am Boden, ist dieser Griff aus (grund.css,
     `[data-neu-handgriff]`) — auf 390 px las man sonst zweimal «NEU» auf
     EINER Flaeche und musste raten, ob beide dasselbe tun (Owner-Gesetz
     03.09.). Eine Rolle ohne Leiste (weniger als zwei Tueren) behaelt ihn,
     und fuer sie bleibt die kurze Beschriftung unten richtig. */
  body.lx-offertenliste:not(:has(.lx-unten)) .vk-kopf .lx-seitenkopf__akt .primary-btn {
    display: inline-flex; align-items: center; justify-content: center;
    white-space: nowrap; padding: 0 14px; min-height: 44px;
    /* «+ Neue Offerte» nahm 215 der 366 px dieser Zeile — von vier
       Filter-Chips blieben zwei erreichbar, und «Gesendet» wurde an der
       Kante zerschnitten. Auf einer Fläche, die zweimal «Offerten» heisst,
       sagt «Neu» dasselbe in einem Drittel der Breite.
       Der volle Text bleibt IM DOM und wird vorgelesen — nur die sichtbare
       Beschriftung ist kürzer. Kein Icon ohne Wort: das Wort bleibt. */
    font-size: 0;
  }
  body.lx-offertenliste:not(:has(.lx-unten)) .vk-kopf .lx-seitenkopf__akt .primary-btn::after {
    content: "+ Neu"; font-size: 14px; font-weight: 650; letter-spacing: .01em;
  }
  /* UND DANN IST DER KOPF LEER. Die Ueberschrift ist auf dieser Flaeche seit
     jeher aus (`h1 { display: none }`, die Reiterzeile sagt schon «Offerten»),
     der Griff ist jetzt in der Leiste — es bliebe ein Kasten von 0x0 px, der
     auf jeder anderen Breite 1132x39 px misst. Genau die Geister-Kachel, die
     das Hausgesetz «jede Bildschirmgroesse ist normal» verbietet (gemessen
     vom Breiten-Waechter, 05.09.: `offerten@390 zusammengefallen
     header.page-head … 0x0`). Ein Bauteil ohne Inhalt wird nicht klein — es
     wird weggelassen. */
  /* PRUEFBEFUND 05.09.2026 — DIE GRENZE MUSS DIE DER LEISTE SEIN.
     Diese Regel stand nackt im 1080er-Block. `:has(.lx-unten)` fragt aber den
     BAUM, nicht die Sichtbarkeit: das `nav` steht auf JEDER Breite darin
     (main.js, `montiereUnterleiste`), waehrend die Leiste selbst nur bis
     900 px gezeichnet wird (patch-chrome.css, `#lx-unten`) und `.qc` ab
     901 px ganz aus ist (grund.css:5429). Zwischen 901 und 1080 px war damit
     der Kopf weg UND die Leiste weg UND der schwebende Knopf weg — auf
     `#/v/offers` gab es dort KEINEN Weg mehr zu einer neuen Offerte.
     Gemessen auf der Buehne (Kopf/Leiste/Knopf je Breite):
       901 px  Kopf AUS · Leiste AUS · Knopf AUS -> WEGE: keiner
      1024 px  Kopf AUS · Leiste AUS · Knopf AUS -> WEGE: keiner   (iPad quer!)
      1080 px  Kopf AUS · Leiste AUS · Knopf AUS -> WEGE: keiner
     1024 px ist eine der neun Geraetebreiten des Hauses (Owner-Gesetz 25.08.).
     Die Schachtelung bindet die Regel an die Breite, auf der die Leiste
     wirklich steht — ueber 900 px kommt der Kopf mit seinem Griff zurueck.

     UMGEZOGEN 05.09.2026, Runde 2 — ERSETZT, NICHT DANEBENGEBAUT: die Regel
     stand hier als Sonderfall EINER Flaeche, und die Kundenliste hatte
     denselben leeren Kasten (gemessen 390 px als Rolle «caller»: 362 x 0 px
     mit 8 px Rand). Zwei Abschriften derselben Frage sind eine zu viel. Sie
     steht jetzt EINMAL am Kopf selbst — docs/design/patch-seitenkopf.css,
     Abschnitt «Ein Kopf, dessen einziger Griff in die Daumenleiste gezogen
     ist» — und gilt fuer beide Flaechen. Die Begruendung oben bleibt hier
     stehen, weil sie die Geschichte dieser Flaeche ist; die Grenze (900 px,
     die Breite der Leiste) ist dort dieselbe. */
  /* NUR DER SCHWEBENDE KNOPF, NIE DIE HUELLE (05.09.2026). Hier stand
     `.qc { display: none }` — seit «Neu» in der Daumenleiste sitzt, wohnt in
     `.qc` das MENUE dieses Ziels. Die Huelle zu verstecken hiesse: auf der
     Offertenliste tippt der Berater «Neu» an und es passiert nichts — ein
     toter Griff, den keine Probe je bemerkt haette (die Bedien-Probe tippt
     auf der Kundenliste). Dieselbe Korrektur wie in patch-pool.css und bei
     `so-editor-open`. */
  body.lx-offertenliste .qc__fab { display: none; }
  /* Die Seite selbst nimmt sich am Handy weniger Rand — 30 px Polster über
     einer Liste sind eine halbe Karte. Oben jetzt 2 statt 10: die
     Reiterzeile darüber zieht bereits ihre Linie, und die Kachelreihe
     bringt ihren eigenen Abstand mit. */
  body.lx-offertenliste .admin-page { padding: 2px 12px 0; }

  /* 2 — DIE KENNZAHLEN IN EINE REIHE.
         Vier Kacheln à zwei Zeilen mit Zeichen und Unterzeile füllten den
         halben Schirm. Was zählt, ist die Zahl mit ihrem Wort; das Zeichen
         wiederholt nur, was das Wort sagt, und die Unterzeile erklärt eine
         Kachel, die sich selbst erklärt. Auf dem Desktop bleibt beides. */
  /* ENTFERNT 04.09.2026 — ERSETZT, NICHT UEBERSCHRIEBEN: hier standen
     `body.lx-offertenliste .vk-kacheln` (2x2) und `.vk-kachel` (Polsterung).
     Beides sagt jetzt EINE Regel fuer alle Flaechen: «DIE EINE ZEILE»
     (docs/design/patch-handy-verkauf.css, Abschnitt 1+2). Die alte 2x2-
     Begruendung («bei vier Spalten bleiben 88 px je Kachel») bleibt wahr —
     die Antwort darauf ist heute der Rollweg, nicht die zweite Reihe.
     GEMESSEN am 04.09.: solange diese Regel hier stand, schlug ihre hoehere
     Spezifitaet die Systemregel, die zwei ausdruecklichen Spalten schrumpften
     auf 26 px, und `test:handy-verkauf:ui` meldete «jede Tapflaeche haelt
     44px — 26px». Zwei Antworten auf dieselbe Frage sind immer eine zu viel. */
  /* ENTFERNT 25.08. (Rueckweg git): `…:nth-child(2n + 1) { padding-left: 0 }`.
     Am 390er-Bild vom 25.08. klebte die Zahl der linken Spalte an der
     Kartenkante — die Regel gehoerte zur kantenlosen Kachel von 13.08. */
  /* DIE KACHEL IST HIER DER FILTER (Owner-Auftrag 08.08. nach DAS-SYSTEM
     Gesetz 5: «eine Überladen-Beschwerde ist ein Löschauftrag, nie ein
     Umbau-Auftrag»). Die Chipzeile darunter sagte dreimal dasselbe Wort wie
     die Kacheln, vierzig Pixel entfernt, und kostete 54 px.
     Die filternden Kacheln kommen als `<button>` aus der Fläche
     (sales-offers.js, `alsKnopf`) — also müssen die Vorgaben des Browsers
     weg, sonst stünde dort ein zentrierter Systemknopf statt der Kachel.
     «Offen» bleibt ein `<div>`: sie summiert dieselbe Menge, die «Gesendet»
     zählt, und hätte als Knopf kein eigenes Ergebnis. */
  body.lx-offertenliste .vk-kachel--filter {
    width: 100%; font: inherit; text-align: left; cursor: pointer;
    -webkit-appearance: none; appearance: none;
  }
  /* WAS DRÜCKBAR IST, MUSS ANDERS AUSSEHEN ALS WAS ES NICHT IST.
     Am ersten Bild sahen alle vier Kacheln gleich aus — drei filtern, «Offen»
     nicht. Wer sie antippt, bekommt nichts und hält die Fläche für kaputt;
     das ist «sichtbar ist nicht bedienbar» in umgekehrter Richtung.
     ⚠️ Der erste Versuch nahm «Offen» den Rahmen weg. Am Bild angesehen: das
     2×2 zerfiel, die rahmenlose Kachel sah nach Rendering-Fehler aus statt
     nach Absicht — und «vier Kacheln 2×2» ist gesetzt. Also umgekehrt: alle
     vier behalten ihren Rahmen, und die drei GRIFFE tragen die türkise
     Haarlinie, die im ganzen Haus «hier ist Bedienung» heisst (dieselbe
     Kante wie Seitenleiste und Kopfzeile, `--lx-kante`). «Offen» behält die
     stille graue. Ein Unterschied, der nicht schreit, aber da ist — und beim
     ersten Antippen bestätigt ihn der kräftige Aktiv-Zustand. */
  /* FLACH STATT KASTEN (13.08.) — DIESE AFFORDANZ DARF NICHT MIT DEM RAHMEN
     VERSCHWINDEN. Der Rahmen war hier nicht Zierde, sondern Aussage: «die
     drei Griffe tragen die tuerkise Haarlinie, ‹Offen› die stille graue».
     Ohne Rahmen traegt die Aussage jetzt die Akzentkante links — dasselbe
     Zeichen, das das Haus ueberall fuer «hier bist du / hier ist Bedienung»
     benutzt (EINHEIT §4.5, `.stat[aria-current]`, `.kf-loc.is-gratis`). Sie
     haengt nicht an der Rasterposition: auch die Kachel ganz links, die keine
     Trennlinie hat, zeigt ihren Griff. */
  body.lx-offertenliste .vk-kachel--filter { box-shadow: inset 2px 0 0 rgba(var(--accent-rgb), .38); }
  /* Den aktiven Zustand muss man SEHEN, nicht erraten — auf 390 px und auch
     für Augen, die Türkis-Abstufungen nicht trennen. Farbe allein ist eine
     Nuance; Kante plus Fläche plus Zahl in Akzentfarbe ist eine Aussage.
     Dieselbe Lehre wie beim gewählten Kanton in der Karte (style.css:7955). */
  body.lx-offertenliste .vk-kachel--filter.is-aktiv {
    background: var(--accent-soft); box-shadow: inset 2.5px 0 0 var(--accent);
  }
  body.lx-offertenliste .vk-kachel--filter.is-aktiv .stat__value { color: var(--accent-strong); }
  body.lx-offertenliste .vk-kachel--filter.is-aktiv .stat__label { color: var(--accent); }
  body.lx-offertenliste .vk-kachel--filter:active { background: var(--surface-hover); }
  body.lx-offertenliste .vk-kachel--filter:focus-visible {
    outline: 2px solid var(--accent); outline-offset: 2px;
  }

  /* DER WEG ZURÜCK, ALS WORT.
     Nochmals antippen hebt den Filter auf — das weiss man aber erst, wenn man
     es einmal getan hat. Diese Zeile sagt es, und sie kostet nur Höhe,
     SOLANGE gefiltert ist: ungefiltert steht sie gar nicht im Baum. Ein
     dauerhaftes Chip-Band mit «Alle» wäre genau die Zeile, die eben gefallen
     ist. */
  body.lx-offertenliste .vk-gefiltert {
    display: flex; align-items: center; justify-content: space-between; gap: 10px;
    margin: 0 0 6px; padding: 0;
    font-size: 12.5px; color: var(--text-secondary);
  }
  body.lx-offertenliste .vk-gefiltert__was b { color: var(--text-primary); font-weight: 650; }
  body.lx-offertenliste .vk-gefiltert__weg {
    flex: 0 0 auto; min-height: 44px; padding: 0 10px;
    border: 0; background: transparent; cursor: pointer;
    color: var(--accent); font: 600 13px/1 inherit;
    text-decoration: underline; text-underline-offset: 3px;
  }
  body.lx-offertenliste .vk-gefiltert__weg:active { color: var(--accent-strong); }

  body.lx-offertenliste .vk-kachel .gz-ic,
  body.lx-offertenliste .vk-kachel .stat__sub:not(.stat__sub--bleibt) { display: none; }
  /* Die Ausnahme des Hauses: eine Unterzeile, die ihre Zahl EINSCHRAENKT,
     schweigt nie (Begruendung und Messung: grund.css bei `.stat-strip`). */
  body.lx-offertenliste .vk-kachel .stat__value {
    font-size: 18px; line-height: 1.15;
    /* Eine Zahl bricht NIE. Lieber schrumpft die Kachel als dass «5'600.00»
       auf zwei Zeilen zerfällt. */
    white-space: nowrap;
  }
  body.lx-offertenliste .vk-kachel .stat__label {
    font-size: 11px; letter-spacing: .06em; white-space: nowrap;
  }

  /* 3 — DIE WERKZEUGZEILE FÄLLT GANZ.
         ---------------------------------------------------------------------
         Die Geschichte dieser Zeile in einem Tag, weil sie erklärt, warum am
         Ende gelöscht statt geschoben wurde:
           · Erst lag der «+ Neu»-Knopf darin und schnitt «Angenommen» ab
             (der Chip lief 88 px über die Kante). Der Knopf zog in die
             Suchzeile.
           · Dann sprengte der Zähler «6 von 6 Offerten» sie: 465 px Inhalt in
             338 px Zeile, also Blende genau über dem letzten Filter.
           · Dann passten die vier Chips mit 336 px in 338 px — zwei Pixel
             Vorsprung, und im Wächter (318 px Zeile) war es prompt wieder rot.
             Polster 12 → 8 machte 301 px daraus.
         Jede Runde war ein Umbau. Der Owner hat dann seine eigene Regel
         angewandt (DAS-SYSTEM Gesetz 5): «Nicht überladen; eine
         Überladen-Beschwerde ist ein Löschauftrag, nie ein Umbau-Auftrag.»
         Die Kacheln direkt darüber heissen Entwürfe · Gesendet · Offen ·
         Angenommen — die Chips hiessen Alle · Entwürfe · Gesendet ·
         Angenommen. Drei Wörter zweimal, vierzig Pixel auseinander.
         Also: die Kachel filtert (Regeln oben), und diese Zeile ist weg.
         54 px zurück, und kein Filtername kann mehr abbrechen, weil es keine
         Filterzeile mehr gibt.
         Am DESKTOP bleibt sie unverändert stehen — dort ist Platz für beides,
         und die Kachel ist dort eine Anzeige (sales-offers.js, `alsKnopf`).

         NACHTRAG 05.09., RUNDE 2 — SIE IST NICHT MEHR GANZ WEG, SIE IST LEER
         BIS AUF EINEN KNOPF. `renderToolbar()` schreibt hier unter 1080 px nur
         noch den Halter der gespeicherten Ansichten hinein; Umschalter, Chips
         und Zaehler bleiben gestrichen. `display: none` waere jetzt falsch —
         es haette den einzigen Weg zu «Ansicht wählen / sichern / umbenennen /
         teilen / als Start / löschen» wieder zugemacht, denselben, den die
         anderen elf Listen laengst haben. Sie nimmt keine eigene Zeile: sie
         steht im Raster oben in derselben Zeile wie Suchfeld und «+ Neu», und
         ihr Aussenabstand faellt hier weg. */
  body.lx-offertenliste .vk-leiste {
    display: flex; margin: 0 0 8px; min-width: 0; flex-wrap: nowrap;
  }
  /* Der Halter selbst ist ein blosser Kasten um den Griff. */
  body.lx-offertenliste .vk-leiste > [data-slot="ansichten"] { min-width: 0; }
  /* 46 vw ist dieselbe Obergrenze wie auf «Heute/Leads» (patch-telefon-griffe):
     der Name einer Ansicht darf kuerzen, er steht ganz im Blatt. */
  body.lx-offertenliste .vk-leiste .aw-griff { max-width: 46vw; }

  /* 4 — UNTEN KEIN LEERRAUM MEHR.
         Hier standen 86 px Polster, damit der schwebende Plus-Knopf die
         letzte Karte nicht verdeckt. Den Knopf gibt es nicht mehr (er steht
         als «+ Neu» in der Suchzeile), und die Schale hält unter der
         Daumenleiste ohnehin `70px + var(--sab)` frei (style.css:12828) —
         die 86 px waren seither ein zweites Mal derselbe Abstand. */
  body.lx-offertenliste .vk-raster { padding-bottom: 8px; gap: 8px; }

  /* 5 — DIE KARTE BEANTWORTET VIER FRAGEN, IN DIESER REIHENFOLGE:
         für wen · was und welche Akte · wie viel und bis wann · was ist jetzt
         dran. Alles andere tritt zurück. */
  body.lx-offertenliste .vk-karte { padding: 9px 12px; gap: 5px; }
  /* Das Zeichen links ist auf JEDER Karte dasselbe Dokument-Symbol — es
     unterscheidet nichts und kostet 44 px Breite. Gemessen 08.08.: genau
     deshalb wurde «Barbershop Zentral GmbH» zu «Barbershop Zentral G…»
     abgeschnitten, und ein abgeschnittener Kundenname ist auf einer Fläche,
     deren erste Frage «für wen?» lautet, der teuerste Fehler. Am Desktop
     bleibt das Zeichen (dort prüft der Wächter es ausdrücklich). */
  body.lx-offertenliste .vk-karte__kopf > .gz-ic { display: none; }
  body.lx-offertenliste .vk-karte__wer { min-width: 0; }
  body.lx-offertenliste .vk-karte__titel,
  body.lx-offertenliste .vk-karte__sub { min-width: 0; }
  /* Die Chipzeile «Erstellt 06.08.2026 · Sazan Deskaj» kostete eine ganze
     Zeile und beantwortete keine der vier Fragen. Das Datum, das zählt,
     steht in der Fusszeile: «Gültig bis». Am Desktop bleibt beides. */
  body.lx-offertenliste .vk-karte__chips { display: none; }
  /* 21.08. — ZWEI ZAHLEN WAREN MIT DRIN, DIE ZU DEN VIER FRAGEN GEHÖREN.
     Die Regel oben nimmt die ganze Zeile weg. Gemessen am 21.08. mit
     `_geldweg_test.mjs` (B13/B14) hing daran mehr als Schmuck:
       · «Offen CHF 6'000.00» — der Rest, den der nächste Schritt meint.
         Am Telefon stand «Restbetrag offen — Zahlung erfassen» und daneben
         CHF 12'000.00, der GANZE Betrag. Frage 3 lautet «wie viel», und die
         Antwort war die falsche Zahl.
       · «Plätze reserviert — noch 5 Tage» / «Reservierung verfallen» — die
         Frist, an der die gebuchten Werbeplätze hängen (Befund 17.08.).
         Sie erreicht den Berater nur am Telefon, und genau dort fiel sie aus.
     Also nicht die Regel zurücknehmen, sondern sie genau machen: die Zeile
     kommt zurück, WENN eine dieser zwei Angaben darin steht — und dann zeigt
     sie auch nur diese. «Erstellt …», der Name und das Mail-Abzeichen
     bleiben aus (Wächter B15). */
  body.lx-offertenliste .vk-karte__chips:has(.vko-chip--offen),
  body.lx-offertenliste .vk-karte__chips:has([data-reservierung]) { display: flex; }
  body.lx-offertenliste .vk-karte__chips > *:not(.vko-chip--offen):not([data-reservierung]) { display: none; }
  /* ZWÖLF PIXEL JE KARTE UM EIN LEERES ELEMENT HERUM.
     Gemessen 08.08.: `.vk-karte__mitte` war 0 px hoch (die Chipzeile darin
     ist aus, Zeile oben) — aber sie blieb ein Kind der Karte, und die Karte
     legt 6 px Abstand zwischen JEDE zwei Kinder. Also zweimal 6 px Luft um
     nichts, auf jeder Karte. `:empty` griff nicht: das Element ist nicht
     leer, es enthält den ausgeblendeten Kasten.
     `display: contents` löst genau das: die Hülle verschwindet aus dem
     Fluss, ihre Kinder werden Kinder der Karte. Steht dort doch etwas — der
     Verrechnungsbalken einer angenommenen Offerte —, bekommt es seinen
     normalen Abstand und geht nicht verloren. */
  body.lx-offertenliste .vk-karte__mitte { display: contents; }
  body.lx-offertenliste .vk-karte__titel { font-size: 16px; line-height: 1.2; }
  body.lx-offertenliste .vk-karte__sub { font-size: 12px; }
  /* Der Betrag ist die zweite Antwort und war die kleinste Schrift auf der
     Karte — grau, in einer Fliesszeile mit Laufzeit und Frist. */
  body.lx-offertenliste .vk-karte__fuss > span:first-child {
    font-size: 15px; font-weight: 650; color: var(--text);
  }
  /* Die Fusszeile trug oben 8 px Polster, obwohl die Karte zwischen ihren
     Kindern schon Abstand hält — der Abstand stand also zweimal da. */
  body.lx-offertenliste .vk-karte__fuss { gap: 8px; row-gap: 2px; padding-top: 3px; }
  /* Die Aktionszeile trug oben und unten je einen halben Fingerbreit Luft,
     ohne dass etwas darin stand. Die Knöpfe selbst bleiben bei 44 px — die
     Tapfläche ist nicht verhandelbar (Wächter 390px). */
  body.lx-offertenliste .vk-karte__akt { margin: 2px 0 0; gap: 5px; }
  /* EINE Reihe, nie zwei. Gemessen 08.08. auf 390×620, nachdem die Knöpfe
     ihre Handlung statt «Mail» tragen: die Karte mit drei Handgriffen
     («Annehmen …» · «Nachfassen» · «Dokument») brauchte 334 von 312 px und
     brach um — 50 px Höhe für nichts, auf jeder zweiten Karte.
     Zwei gemessene Stellschrauben statt einer geratenen: Polster 14 → 11
     (−18 px über drei Knöpfe) und Schrift 13.5 → 13 (−4 % Textbreite).
     Zusammen: 334 → 307 px. Die 44 px Tapfläche bleiben unangetastet — die
     ist nicht verhandelbar, sie ist der Grund, warum die Zeile so hoch ist.
     Schmaler geht nur noch über Wörter, und die tragen die Bedeutung. */
  body.lx-offertenliste .vk-karte__akt .ghost-btn,
  body.lx-offertenliste .vk-karte__akt .primary-btn {
    min-height: 44px; padding: 0 10px; font-size: 13px;
  }
}

/* Der nächste Schritt gilt auf JEDER Breite — er ist kein Handy-Zusatz,
   sondern die Antwort auf «was ist jetzt dran», die der Liste bisher fehlte. */
.vk-karte__schritt {
  display: flex; align-items: baseline; gap: 6px;
  margin: 0; font-size: 12.5px; line-height: 1.35; color: var(--text-secondary);
}
.vk-karte__schritt-wort {
  flex: 0 0 auto;
  font-size: 11px; font-weight: 700; letter-spacing: .07em; text-transform: uppercase;
  color: var(--text-tertiary);
}

/* ============================================================
   Patch-Integration — Namensraum kachelpass; Quelle: docs/design/patch-kachelpass.css
   Der Block wird bei Integration als GANZES ersetzt, nie editiert.
   W5.2 «Der Kachel-Pass» — die Kennzahl-Pille der Flaeche «Heute» als Link.
   ============================================================ */
/* ============================================================
   W5.2 · Der Kachel-Pass — jede Kennzahl fuehrt irgendwohin
   Namensraum: keiner eigener — dies sind ZWEI Zustaende an bestehenden
               Bauformen (.stat, .kpi-pill), kein neues Aussehen.
   Befund:     docs/berichte/ganzes-bild/C-ist-und-auffindbarkeit.md, Klasse I —
               14 von 17 Flaechen tragen einen Kennzahl-Streifen, und keine
               Zahl war klickbar.
   Bauteil:    public/src/components/kennzahl-kachel.js
   ============================================================

   WARUM DIESER PATCH SO KLEIN IST. Die Kachel .stat war seit je fuer den
   Link-Fall gestaltet (style.css: `text-decoration: none`, `color: inherit`,
   `a.stat:hover`, `.stat:focus-visible`) — zentrale.js hat sie als einzige
   Flaeche im Haus so benutzt. Fuer die dreizehn anderen Kachel-Flaechen war
   deshalb KEINE Zeile CSS noetig.

   Genau eine Bauform war nicht vorbereitet: die Kennzahl-PILLE der Flaeche
   «Heute» (.kpi-pill, docs/design/grund.css). Sie setzt Hintergrund, Rahmen und
   Radius bewusst zurueck und traegt ihre Trennung als linke Haarlinie — aber
   sie hat nie `text-decoration` oder `color` gesetzt, weil sie nie ein Link
   war. Als <a> haette sie unterstrichen und in Linkfarbe dagestanden.

   Was hier steht, ist darum kein Aussehen, sondern die Ruecknahme der
   Browser-Vorgabe plus dieselben zwei Zustaende, die .stat schon hat:
   ein ruhiger Hover und der Fokusring der Tastaturbedienung. Kein
   box-shadow, kein Leucht-Hof, keine neue Farbe. */

a.kpi-pill { text-decoration: none; color: inherit; }
/* Derselbe Hover wie an der Kachel (.stat:hover) — eine Nuance Flaeche, keine
   Farbe. Die Pille sitzt auf transparentem Grund; --surface-2 ist genau der
   Ton, mit dem sich .stat unter dem Zeiger hebt. */
a.kpi-pill:hover { background: var(--surface-2); }
/* Der Fokusring ist Bedienbarkeit, nicht Schmuck (_d03_geraete_test.mjs misst
   ihn). `outline-offset` liegt hier NACH innen: die Pillen stehen ohne Abstand
   nebeneinander, ein aeusserer Ring wuerde den Nachbarn ueberdecken. */
a.kpi-pill:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

/* ============================================================
   Patch-Integration — Namensraum ko-/kk-; Quelle: docs/design/patch-meine-offerten.css
   Der Block wird bei Integration als GANZES ersetzt, nie editiert.
   W8.3 / SB5 — «Meine Offerten» im Kundenportal. Der Block lag ohne
   Integrationskopf in style.css; damit fiel er in den Kachelpass-Block
   davor und machte test:stil rot. Nur der Kopf und die Spiegel-Datei sind
   neu — an den Regeln selbst wurde kein Zeichen geaendert (W8.3 gehoert
   seinem Bauer; wer den Block aendert, aendert die Spiegel-Datei mit).
   ============================================================ */
/* ===========================================================================
   MEINE OFFERTEN im Kundenportal (W8.3 / SB5, 2026-08-10)
   ---------------------------------------------------------------------------
   Die Fläche, an der die Verkaufskette bisher die Software verliess: der
   Kunde sieht sein Angebot und nimmt es an. Sie erfindet KEINE Optik — sie
   nutzt die Anatomie, die im Portal schon steht:

   Aus dem Bestand (nicht neu definiert): .panel/__header/__title,
   .panel-row/__main/__sub, .kk-panel, .kk-rechnung, .kk-betrag, .kk-stand,
   .kk-versprechen, .kk-kopf__rechts, .kk-zurueck, .kp-count, .kp-zahl,
   .bs-preis/__total (die EINE Preis-Bauart, EINHEIT 5.7), .kp-abschluss,
   .kp-pruefen/__satz, .bs-buchen, .bs-warum, .bs-agb, .field, .sl-badge*,
   .so-hint, .empty-state, .load-error, .primary-btn, .ghost-btn.

   Neu ist nur, was es hier zum ersten Mal gibt: die Zeile als sichtbare Tür,
   die Positionsliste, die Standortliste, die Folge-Liste des Annahme-Panels
   und der Weg-Knopf in der Zeile der Übersicht.
   =========================================================================== */

/* DIE ANGEBOTS-ZEILE IST EINE TÜR — und muss sich auch so anfühlen.
   Gefunden von der eigenen UI-Probe (10.08.): die Zeile trägt role="button",
   tabindex und einen Klick-Weg ins Blatt, hob sich aber unter dem Zeiger mit
   keinem Pixel ab. Die übrigen .kk-rechnung-Zeilen des Portals sind reine
   ANZEIGE — sie haben nie eine Hover-Regel gebraucht, und deshalb fehlte sie
   hier. Der Ton ist derselbe Akzent wie überall im Haus, nur sehr leise; der
   Fokusring folgt der globalen Regel (style.css:258), damit die Tür auch mit
   der Tastatur sichtbar bleibt.

   ZWEI AGENTEN, EIN BEFUND (10.08.2026): dieser Block und ein zweiter, wortnah
   gleicher, standen kurzzeitig nebeneinander — beide entstanden am selben Tag
   aus derselben Messung (scripts/_kunde_annahme_ui_test.mjs, «Die Zeile zeigt,
   dass sie eine Tür ist»). Zusammengelegt auf DIESEN, weil sein Ton dem
   Vorbild für Tür-ZEILEN folgt (`.sl-table tr[data-id]:hover td`, :2743-2758)
   statt dem für Karten. Gestrichen wurde dabei die eigene :focus-visible-Regel:
   sie wiederholte die globale (:258) Wert für Wert — und der Satz darüber
   behauptete gleichzeitig, sie käme von dort. Ein Kommentar, der dem Code
   widerspricht, ist teurer als eine fehlende Zeile. Dass der Ring weiterhin
   steht, misst die Probe («…mit sichtbarem Fokus (WCAG 2.4.11)»). */
.panel-row[data-offerte] {
  cursor: pointer;
  border-radius: var(--radius-card);
  transition: background-color .15s ease;
}
.panel-row[data-offerte]:hover { background: rgba(var(--accent-rgb), .07); }

/* … UND SIE MUSS AUCH IM STILLSTAND WIE EINE AUSSEHEN (EINHEIT 1.4).
   Zweiter Befund, diesmal vom Kreativ-Review (10.08.): der Knopf auf der
   Übersicht heisst «Ansehen und annehmen» und führt auf eine Liste, in der
   keine Zeile eine sichtbare Handlung trägt. Hover und Fokus helfen nur, wer
   schon weiss, dass da etwas ist. Das Winkelzeichen sagt es im Ruhezustand —
   dasselbe Mittel wie in den Listen der Innenwelt (.sl-table). */
.ko-zeile { grid-template-columns: minmax(0, 1fr) auto auto auto; }
.ko-zeile__weg {
  display: inline-flex; align-items: center; justify-self: end;
  color: var(--text-tertiary);
}
.ko-zeile__weg svg { width: 18px; height: 18px; }
.ko-zeile:hover .ko-zeile__weg { color: var(--accent); }

/* Die eine Zeile, die eine Entscheidung verlangt, ist die einzige mit einer
   Kante. Der Akzent-Strich links ist das Mittel des Hauses für «hier bist du
   dran» (Inset-Bar, nie ein Leucht-Hof). */
.ko-zeile--offen {
  box-shadow: inset 2.5px 0 0 var(--accent);
  background: rgba(var(--accent-rgb), .04);
}

/* Was nach der Annahme passiert — drei kurze Zeilen statt eines Satzgeflechts
   (EINHEIT 1.6). Kein Aufzählungspunkt: die Zeilen sind Aussagen, keine
   Optionen. */
.ko-folge {
  margin: 0 0 14px; padding: 0; list-style: none;
  font-size: 14px; line-height: 1.75; color: var(--text-secondary);
}
.ko-folge li { padding-left: 18px; position: relative; }
.ko-folge li::before {
  content: ""; position: absolute; left: 4px; top: 11px;
  width: 5px; height: 5px; border-radius: 50%; background: var(--accent);
}

/* Der Nachsatz zum Startdatum: er betrifft einen Randfall und steht darum
   leiser und dichter am Feld, nicht im Weg zum Knopf. */
.ko-nachsatz { margin: 6px 0 0; }

/* Der Weg aus dem Erfolgszustand (EINHEIT 5.12): zwei Knopfstufen statt drei
   eingebetteter Textlinks. Die 44px stehen hier auf JEDER Breite, nicht erst
   am Handy: gemessen wurden 38px, und dieser Knopf ist der Weiterweg aus dem
   wichtigsten Moment des Portals — auf einem Touch-Notebook wird er genauso
   getippt wie auf dem Telefon (Touch-Floor, Memory project_tablet_touch_breakpoint). */
.ko-weiter { margin-top: 16px; }
.ko-weiter .primary-btn, .ko-weiter .ghost-btn {
  min-height: 44px; display: inline-flex; align-items: center; justify-content: center;
}

/* Positionen und Rechnungen im Blatt: dieselbe Zeilen-Anatomie wie überall im
   Portal, nur ohne Zustands-Abzeichen — eine Position hat keinen Zustand. */
.ko-posten { margin-top: 14px; }
/* Drei Spalten, nicht zwei: die Rechnungszeile des Erfolgszustands traegt seit
   dem Kreativ-Review einen Zustands-Chip (Befund B1). Mit zwei Spalten fiel er
   in eine eigene Zeile und zog sich ueber die volle Breite — ein Abzeichen,
   das aussieht wie ein Balken. Positionszeilen haben nur zwei Kinder; die
   dritte Spalte faellt dort auf null zusammen. */
.ko-posten__zeile {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  align-items: center;
  gap: 4px 14px;
}
.ko-posten__zeile .kk-betrag { justify-self: end; }
.ko-posten__zeile .sl-badge { justify-self: end; }

/* Die Standorte. Bewusst eine schlichte Liste: der Kunde zählt hier, er
   vergleicht nicht. Der Hinweis zur Maskierung steht darunter und ist leiser
   als die Liste — er erklärt, er entschuldigt nicht. */
.ko-orte { margin-top: 18px; }
/* KEINE VERSALIEN (EINHEIT 1.5). Sie tragen im Haus genau eine Aufgabe: den
   Tabellenkopf. Hier stand mit 11px/700/uppercase eine vierte Versalien-Rolle
   auf derselben Fläche — neben dt-Labels, Feldbeschriftung und (bis heute)
   dem Panel-Titel «Annehmen». Abschnittslabel ist jetzt Panel-Titel-Grad:
   13px, gemischt. */
.ko-orte__titel {
  margin: 0 0 8px;
  font-size: 13px; font-weight: 600; letter-spacing: 0;
  color: var(--text-primary);
}
.ko-orte__liste {
  margin: 0; padding: 0; list-style: none;
  font-size: 14px; line-height: 1.7; color: var(--text-secondary);
}
.ko-orte__hinweis { margin-top: 10px; }

/* Der Weg-Knopf in der Angebots-Zeile der Übersicht. Er trägt die Handlung,
   nicht das Ziel — «Ansehen und annehmen», nicht «Offerten». */
.kk-offerte__weg { justify-self: end; white-space: nowrap; }

/* Handy (Memory project_css_cascade_mobile): am 390-px-Gerät bricht der Betrag
   unter den Text, damit die Nummer nicht abgeschnitten wird — dieselbe Regel,
   die .kr-zeile dort schon fährt. */
@media (max-width: 560px) {
  /* Am Handy bricht der Betrag unter den Text; das Abzeichen behaelt seine
     eigene Breite, statt sich als Balken ueber die Zeile zu legen. */
  .ko-posten__zeile { grid-template-columns: minmax(0, 1fr) auto; }
  .ko-posten__zeile .sl-badge { justify-self: start; }
  /* Das Winkelzeichen bleibt am rechten Rand, auch wenn Betrag und Abzeichen
     darunter umbrechen: es ist die Ansage «hier geht es weiter» und verliert
     seinen Sinn, sobald es mitten im Text steht. */
  .ko-zeile { grid-template-columns: minmax(0, 1fr) auto; }
  .ko-zeile__weg { grid-row: 1 / -1; grid-column: 2; align-self: center; }
  .kk-offerte__weg { justify-self: start; }
  /* Zwei Knöpfe untereinander statt nebeneinander — auf 390 px passt keine
     Zeile mit «Zu meinen Buchungen» und «Zahlungsangaben ansehen». */
  .ko-weiter { display: grid; gap: 8px; }
  .ko-weiter .primary-btn, .ko-weiter .ghost-btn { width: 100%; min-height: 44px; }
}

/* ============================================================
   Patch-Integration — Namensraum lq-/ma-; Quelle: docs/design/patch-liquiditaet.css
   Der Block wird bei Integration als GANZES ersetzt, nie editiert.
   E-F7 Liquiditaetsvorschau + SB14 Monatsabschluss-Kette auf der Finanz-Startseite.
   ============================================================ */
/* ============================================================
   E-F7 · Die Liquiditaetsvorschau  +  SB14 · Der Monatsabschluss
   Namensraum: lq-  (Wochenraster der Vorschau)
               ma-  (die Kette des Monatsabschlusses)
   Flaeche:    public/src/views/finanzen.js
   Befund:     docs/berichte/video-audit-2026-08-09/20-finanz-lueckenkarte.md:470
               docs/berichte/ganzes-bild/E-bedien-dramaturgie.md:330
   ============================================================

   KEIN DIAGRAMM-WERKZEUG. Zwoelf Wochen brauchen kein Chart-Framework —
   sie brauchen zwoelf Zeilen, in denen zwei Balken dasselbe Mass teilen.
   Die Bauform ist die des Hauses: eine Spur mit einer Fuellung, genau wie
   `.soll-ist__bar`/`.soll-ist__fill` (style.css) und `.stat__bar > i`. Neu
   ist nur, dass hier ZWEI Spuren uebereinander stehen — Eingang oben,
   Ausgang unten —, weil eine gestapelte Einzelspur die Frage «wie viel geht
   raus» erst nach Kopfrechnen beantwortet.

   KEINE NEUE FARBE. Eingang ist `--good`, Ausgang ist `--bad`, beides in
   derselben Semantik wie `.pnl-pos`/`.pnl-neg` (docs/design/grund.css). Der
   Grund der Spur ist derselbe Tint-Kanal wie in `.stat__bar`.

   KEIN LEUCHT-HOF (Owner-Befund 03.08.): kein box-shadow ausser der
   bestehenden Hairline; die Trennung traegt `--border`, wie ueberall.

   DIE ZEILE IST EIN KNOPF, kein <div> mit einem Klick-Ereignis. Damit
   funktioniert sie mit der Tastatur, sagt per `aria-expanded`, ob ihre
   Posten offen sind, und haelt auf dem Handy ihre 44 Pixel.
   ============================================================ */

/* --- Die Vorschau ------------------------------------------------------- */
/* Der Ausgangspunkt ist ein SATZ, keine zweite Anzeigezahl: der Kontostand
   steht schon als Kachel darueber. Zweimal dieselbe Zahl in Anzeigegroesse
   liest sich als zwei Zahlen (Pruefblick 10.08., Befund C1). */
.lq-kopf { margin: 0 0 12px; font-size: 12.5px; color: var(--text-secondary); }
.lq-kopf b { color: var(--text-primary); font-weight: 650; font-variant-numeric: tabular-nums; }

/* Die Warnung sitzt im Panel-Kopf, damit sie am Handy im ERSTEN Bildschirm
   liegt — sie ist die einzige Zahl der Flaeche, die zum Handeln zwingt. */
.lq-warnchip { flex: 0 0 auto; font-variant-numeric: tabular-nums; }

.lq-wochen { list-style: none; margin: 0; padding: 0; }
.lq-gap { border-bottom: 1px solid var(--border); }
.lq-gap:last-child { border-bottom: 0; }
.lq-gap__summary {
  display: flex; align-items: center; flex-wrap: wrap; gap: 12px 18px;
  min-height: 64px; padding: 14px 0; cursor: pointer; list-style: none;
}
.lq-gap__summary::-webkit-details-marker { display: none; }
.lq-gap__summary:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.lq-gap__summary:hover { background: var(--surface-2); }
.lq-gap__period { display:flex; flex-direction:column; gap:3px; flex:var(--lq-period-flex,0 0 118px); font-size:13px; }
.lq-gap__period > span, .lq-gap__description > span { color: var(--text-secondary); font-size: 12px; }
.lq-gap__description { display:flex; flex-direction:column; gap:3px; flex:var(--lq-description-flex,1 1 200px); order:var(--lq-description-order,0); font-size:13px; }
.lq-gap__balance { margin-left:var(--lq-balance-margin,0px); font-size: 14px; font-variant-numeric: tabular-nums; }
.lq-gap__action { order:var(--lq-action-order,0); min-height:var(--lq-action-height,auto); display: flex; align-items: center; gap: 10px; color: var(--accent); font-size: 12px; }
.lq-gap details[open] > summary .lq-pfeil { transform: rotate(90deg); }
.lq-gap__weeks { padding-left: 14px; border-left: 2px solid var(--border); }
.lq-woche { border-bottom: 1px solid var(--border); }
.lq-woche:last-child { border-bottom: 0; }

.lq-woche__kopf {
  display: flex; align-items: center; gap: 8px 14px; flex-wrap: wrap;
  width: 100%; min-height: 44px; padding: 10px 0;
  border: 0; background: transparent; color: inherit; font: inherit;
  text-align: left; cursor: pointer;
  transition: background var(--transition);
}
.lq-woche__kopf:hover { background: var(--surface-2); }
.lq-woche__kopf:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.lq-woche__kopf[disabled] { cursor: default; }

.lq-woche__wann { display: flex; flex-direction: column; gap: 1px; flex: 0 0 118px; min-width: 0; }
.lq-woche__wann > b { font-weight: 600; font-size: 13px; color: var(--text-primary); }
.lq-woche__wann > span { font-size: 11.5px; color: var(--text-tertiary); font-variant-numeric: tabular-nums; }

/* ZWEI SPUREN, EIN MASS — und jede Spur traegt ihre eigene Zahl NEBEN sich.
   Beide Breiten sind Prozent derselben groessten Wochenzahl; zwei Massstaebe
   wuerden einen kleinen Ausgang so lang zeichnen wie einen grossen Eingang.
   Die Zahl neben der Spur ist der Grund, warum der Balken auf jeder Breite
   als Messung lesbar bleibt: am 390er lag er vorher allein ueber der
   Trennlinie der naechsten Woche und las sich als Strich (Befund A2). */
.lq-balken { display: flex; flex-direction: column; gap: 4px; flex: 1 1 220px; min-width: 150px; }
.lq-balken__zeile { display: flex; align-items: center; gap: 10px; }
.lq-balken__spur {
  display: block; flex: 1 1 auto; height: 7px; border-radius: 4px;
  background: rgba(var(--tint-rgb), .10); overflow: hidden;
}
.lq-balken__ein, .lq-balken__aus { display: block; height: 100%; border-radius: 4px; }
.lq-balken__ein { background: var(--good); }
.lq-balken__aus { background: var(--bad); }
.lq-balken__wert {
  flex: 0 0 auto; min-width: 88px; text-align: right;
  font-size: 12px; font-variant-numeric: tabular-nums;
}
.lq-balken__wert.lq-ein { color: var(--good-strong); }
.lq-balken__wert.lq-aus { color: var(--bad-strong); }

.lq-woche__saldo {
  flex: 0 0 auto; min-width: 118px; text-align: right;
  font-weight: 650; font-variant-numeric: tabular-nums;
  color: var(--text-primary);
}
/* Der negative Saldo bleibt rot — das ist dieselbe Regel wie .pnl-neg im
   ganzen Haus. Die FLAECHE der Zeile ist es nicht mehr: rote Flaeche, rote
   Zahl und roter Satz waren drei Warnstufen fuer einen Umstand (Befund C2,
   EINHEIT 1.3 «Rot sparsam»). Geblieben sind der Chip im Kopf und die Zahl. */
.lq-woche.is-eng .lq-woche__saldo { color: var(--bad-strong); }

.lq-woche__auf { flex: 0 0 auto; display: inline-flex; align-items: center; gap: 8px; margin-left: auto; }
.lq-woche__anzahl { color: var(--text-tertiary); font-size: 11px; white-space: nowrap; }
/* Das Aufklapp-Zeichen. Gleiche Bauform wie .mi-klapp__pfeil (style.css) —
   ein Dreieck aus Rahmen, das sich beim Oeffnen dreht. Vorher stand statt
   dessen eine Bedienanleitung im Panel-Kopf (Befund B3). */
.lq-pfeil {
  width: 0; height: 0; border-left: 6px solid currentColor;
  border-top: 5px solid transparent; border-bottom: 5px solid transparent;
  color: var(--text-tertiary); transition: transform var(--transition);
}
.lq-woche__kopf[aria-expanded="true"] .lq-pfeil { transform: rotate(90deg); color: var(--accent); }

/* Die Posten einer Woche — dieselbe Zeilensprache wie ueberall, nur
   eingerueckt, damit sichtbar bleibt, wozu sie gehoeren. */
.lq-posten { padding: 0 0 12px 14px; border-left: 2px solid var(--border); margin: 0 0 4px 8px; }
.lq-posten .panel-row { padding: 9px 0; }
.lq-posten .panel-row:last-child { border-bottom: 0; }
.lq-posten__mehr { font-size: 12px; color: var(--text-tertiary); padding: 6px 0 0; }

/* Was die Vorschau NICHT weiss — als POSITIONSLISTE, nicht als Satzgeflecht.
   Drei Ausschluesse in einem Semikolon-Satz waren am 390er vierzehn Zeilen
   Fliesstext ohne auffindbare Zahl (Befund B5). */
.lq-hinweis {
  margin: 14px 0 0; padding: 12px 14px;
  background: var(--surface-inset); border-radius: var(--radius-card);
  font-size: 12.5px; line-height: 1.5; color: var(--text-secondary);
}
.lq-hinweis__titel {
  margin: 0 0 8px; font-size: 11px; font-weight: 700; letter-spacing: .08em;
  text-transform: uppercase; color: var(--text-tertiary);
}
.lq-nicht { list-style: none; margin: 0; padding: 0; }
.lq-nicht__zeile {
  display: flex; align-items: baseline; gap: 4px 14px; flex-wrap: wrap;
  padding: 9px 0; border-bottom: 1px solid var(--border);
}
.lq-nicht__zeile:last-child { border-bottom: 0; }
.lq-nicht__main { display: flex; flex-direction: column; gap: 2px; flex: 1 1 200px; min-width: 0; }
.lq-nicht__main > b { color: var(--text-primary); font-weight: 600; }
.lq-nicht__warum { color: var(--text-tertiary); font-size: 12px; }
.lq-nicht__wert {
  flex: 0 0 auto; margin-left: auto; font-weight: 650;
  font-variant-numeric: tabular-nums; color: var(--text-primary);
}
.lq-nicht__weg { flex: 0 0 auto; font-size: 12px; white-space: nowrap; }
.lq-hinweis__fuss { margin: 10px 0 0; }

/* --- Die Kette des Monatsabschlusses ------------------------------------ */
.ma-kette { list-style: none; margin: 0; padding: 0; counter-reset: none; }
.ma-schritt { display: flex; align-items: stretch; gap: 12px; border-bottom: 1px solid var(--border); }
.ma-schritt:last-child { border-bottom: 0; }

.ma-schritt__nr {
  flex: 0 0 26px; align-self: center;
  display: inline-flex; align-items: center; justify-content: center;
  width: 26px; height: 26px; border-radius: 999px;
  background: rgba(var(--tint-rgb), .08); border: 1px solid var(--border);
  font-size: 12px; font-weight: 700; color: var(--text-secondary);
  font-variant-numeric: tabular-nums;
}
.ma-schritt.is-erledigt .ma-schritt__nr {
  background: rgba(var(--good-rgb), .13); border-color: transparent; color: var(--good-strong);
}
/* Der Schritt, der JETZT dran ist — die einzige Hervorhebung der Kette. */
.ma-schritt.is-dran .ma-schritt__nr {
  background: var(--accent); border-color: transparent; color: #04191c;
}

.ma-schritt__weg {
  display: flex; align-items: center; gap: 8px 14px; flex-wrap: wrap;
  flex: 1 1 auto; min-width: 0; min-height: 44px; padding: 12px 0;
  text-decoration: none; color: inherit;
  transition: background var(--transition);
}
.ma-schritt__weg:hover { background: var(--surface-2); }
.ma-schritt__weg:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

/* `flex: 1 1 0` — die Null ist der Punkt. Mit `240px` ODER `auto` ist die
   Flex-Basis die Breite des laengsten Titels; bei `flex-wrap: wrap` entscheidet
   der Browser den Zeilenumbruch an der BASIS, bevor er ans Schrumpfen denkt.
   Der Chip fiel darum am 390er unter den Text, waehrend er auf dem Desktop
   danebenstand — ein Baustein, zwei Anordnungen (Pruefblick 10.08., Befund A1).
   Mit Basis 0 passen Text und Chip immer auf eine Zeile; der Titel bricht um. */
.ma-schritt__main { display: flex; flex-direction: column; gap: 2px; flex: 1 1 0; min-width: 0; }
.ma-schritt__main > b { font-weight: 600; color: var(--text-primary); }
.ma-schritt__stand { font-size: 12.5px; color: var(--text-secondary); font-variant-numeric: tabular-nums; }
.ma-schritt.is-erledigt .ma-schritt__stand { color: var(--good-strong); }
/* «Zuerst fehlt Schritt N» — der Satz aus dem Abnahme-Drehbuch D-O4. Er warnt
   in Bernstein, weil er nichts verbietet: er ordnet nur ein. Rot waere ein
   Fehler, und einen Fehler macht hier niemand. */
.ma-schritt__zuerst { font-size: 12px; color: var(--warn-strong); }
/* EINE Anordnung auf jeder Breite. Vorher hob der 640er `margin-left: auto`
   auf — dadurch rutschte der Chip bei kurzen Titeln unter den Text nach links
   und blieb bei langen rechts oben: ein Baustein, zwei Anordnungen im selben
   Block (Pruefblick 10.08., Befund A1). */
.ma-schritt__marke { flex: 0 0 auto; margin-left: auto; align-self: flex-start; }
/* Die sichtbare Tuer am dranen Schritt — die primaere Handlung der Flaeche
   war vorher nur ein Satz im Kopf (Befund B3). Kein zweites Klickziel: sie
   liegt IM umschliessenden Link. */
.ma-schritt__tuer {
  flex: 0 0 auto; display: inline-flex; align-items: center;
  min-height: 32px; padding: 0 14px; border-radius: var(--radius-button);
  background: var(--accent); color: #04191c;
  font-size: 12.5px; font-weight: 650; white-space: nowrap;
}
.ma-schritt__weg:hover .ma-schritt__tuer { background: var(--accent-strong); }

@media (max-width: 640px) {
  /* Am Handy stapelt die Wochenzeile: Name+Saldo oben, darunter die beiden
     Balken MIT ihren Zahlen. Der Chip der Kette behaelt seine Anordnung —
     nur der Knopf darf umbrechen, damit er seine 44 px behaelt. */
  .lq-woche__wann { flex: 1 1 auto; }
  .lq-gap > details { --lq-period-flex:1 1 auto; --lq-description-flex:1 1 100%; --lq-description-order:2; --lq-balance-margin:auto; --lq-action-order:3; --lq-action-height:24px; }
  .lq-balken { flex: 1 1 100%; order: 3; min-width: 0; }
  .lq-woche__saldo { min-width: 0; margin-left: auto; }
  .lq-woche__auf { order: 2; margin-left: 0; }
  .lq-nicht__wert { margin-left: 0; }
  /* Der Knopf nimmt am Handy die volle Breite — damit forderte er aber den
     Zeilenumbruch VOR dem Chip an, und ausgerechnet der drane Schritt trug
     seinen Chip wieder unter dem Text (Befund A1, zweite Schicht). `order`
     entscheidet die Zeilenverteilung: Text und Chip zuerst, Knopf darunter. */
  .ma-schritt__main  { order: 1; }
  .ma-schritt__marke { order: 2; }
  .ma-schritt__tuer  { order: 3; flex: 1 1 100%; justify-content: center; min-height: 44px; }
}

/* ============================================================
   Patch-Integration — Namensraum vpa-; Quelle: docs/design/patch-vertriebsportal.css
   Der Block wird bei Integration als GANZES ersetzt, nie editiert.
   P14-2 Vertriebsportal: Firmen-Postfach (#/vp) und Mein Team (#/vp/team).
   ============================================================ */
/* ============================================================
   P14-2 · Das Vertriebsportal der externen Firma
   Namensraum: vpa-  (Vertriebsportal-Admin)
   Flaechen:   public/src/views/vertrieb-portal.js  (#/vp, Postfach)
               public/src/views/vertrieb-arbeit.js  (#/vp/team, Mein Team)
   Befund:     Kreativ-Review 10.08. gegen docs/design/EINHEIT.md
   ============================================================

   ZWOELF ZEILEN STATT EINER BIBLIOTHEK. Die beiden Flaechen bauen fast
   vollstaendig aus dem Bestand: .panel, .panel__header, .panel__title,
   .panel-row, .stat, .sl-badge, .primary-btn, .ghost-btn,
   .ghost-btn--danger. Was hier steht, ist genau das, was der Bestand NICHT
   hergibt — und jede Regel traegt ihren Befund.

   1) GEMISCHTE FELD-LABEL (EINHEIT 1.5). Das Haus-Idiom `.field span` ist
      gesperrte Versalien — richtig fuer ein Formular-Mikro-Label neben einem
      Zahlenfeld, falsch fuer einen ganzen Satz («Wer uebernimmt ‹Alpha
      Coiffure›?»). Die Vertraege-Flaeche vom selben Tag loest das mit
      `.lx-neu-form label` in gemischter Schreibung; dieselbe Absicht, hier
      als Modifikator statt als zweites Formular-System. Versalien behalten
      damit ihre EINE Aufgabe: Spaltenkopf.

   2) EINE META-ZEILE, DIE KEIN SPALTENKOPF IST. `.jetzt__wozu` traegt die
      Metazeile der Jetzt-Karte in gesperrten Versalien — und stand als
      ERSTE Zeile ueber dem Namen. Die Karte bekommt darum den Panel-Kopf
      des Hauses («Was jetzt») und die Metazeile gemischt DARUNTER. Die
      Haus-Klasse bleibt unangetastet: die interne Berater-Flaeche
      (advisor-leads.js) benutzt sie ebenfalls.

   3) FESTE HANDLUNGS-SPALTE. Die Zeilen von «Mein Team» tragen bis zu vier
      Griffe. Rechtsbuendig gekettet sprang «Anteil» von Zeile zu Zeile an
      eine andere x-Position — das Auge findet denselben Griff dann jedes
      Mal neu. Eine feste Mindestbreite haelt die Spalte ruhig; auf dem Handy
      faellt sie bewusst in eine eigene volle Zeile, statt zu schrumpfen.

   4) ZAHL UND WORT BLEIBEN EIN GEFUEGE. «0» und «ueberfaellig» zerrissen auf
      390 px ueber zwei Zeilen. Der Zustand ist jetzt EIN Chip (`.sl-badge`),
      und dieser Chip bricht nicht.
   ============================================================ */

/* 1) Gemischte Label — nur in den Formularen dieser beiden Flaechen. */
.vpa-form .field > span {
  text-transform: none; letter-spacing: 0;
  font-size: 12.5px; font-weight: 500; color: var(--text-secondary);
}

/* 2) Die Metazeile der Jetzt-Karte: gemischt, ruhig, unter dem Namen. Sie
      steht IM Namens-Block, nicht daneben — sonst braeche sie die Zeile auf
      und schoebe den Knopf in eine dritte Reihe. */
.vpa-meta {
  display: block; margin-top: 2px;
  font-size: 12.5px; font-weight: 400; letter-spacing: 0; text-transform: none;
  color: var(--text-secondary);
}

/* 3) Die Handlungs-Spalte. `flex: 0 0 auto` statt `1 1` — sie darf wachsen,
      wenn ein Griff dazukommt, aber nie am Inhalt links ziehen. */
.vpa-akt {
  display: inline-flex; align-items: center; justify-content: flex-end;
  gap: 8px; flex: 0 0 auto; min-width: 300px; margin-left: auto;
}
.vpa-akt > * { flex: 0 0 auto; }
/* Gleich breite Griffe: «Zugang sperren» und «Zugang öffnen» sind verschieden
   lange Wörter. Ohne feste Breite verschiebt schon dieser Unterschied jeden
   Griff links davon — und genau das war der Befund. Das Mass ist der laengste
   Griff dieser Flaeche, gemessen statt geschaetzt: 140 px bei 13 px gemischter
   Schrift; seit v394 (Knopfwoerter 12 px/650/.1em in Versalien) misst «Zugang
   sperren» 164 px, «Zugang oeffnen» 156 px (mess-griffe.mjs, 03.09.). */
.vpa-akt .ghost-btn { min-width: 164px; justify-content: center; }

/* Eine Tuer im Fliesstext ist ein Knopf, kein Wort in Absatzgrau
   (EINHEIT 1.4): sie traegt Rand, Flaeche und die volle Tapgroesse. */
.vpa-tuer { display: inline-flex; align-items: center; margin-top: 8px; }

/* 4) Der Zustands-Chip bricht nicht. */
.vpa-stand { white-space: nowrap; }

/* Die Formulare stehen unter ihrer Zeile, nicht neben ihr — sonst schoebe
   ein offenes Formular die Handlungs-Spalte der Nachbarzeile aus dem Bild. */
.vpa-unterform { flex: 1 1 100%; margin-top: 10px; }

@media (max-width: 1024px), (pointer: coarse) {
  /* Auf dem Handy gehoert der Spalte die ganze Zeile: vier Griffe nebeneinander
     unter 390 px waeren vier Griffe, die keiner trifft. */
  .vpa-akt { min-width: 0; width: 100%; justify-content: flex-start; flex-wrap: wrap; }
  /* Auf dem Handy zaehlt die Zeile, nicht die Spalte: die feste Griffbreite
     wuerde hier nur Umbrueche erzwingen. */
  .vpa-akt .ghost-btn { min-width: 0; }
  .vpa-tuer { width: 100%; justify-content: center; }
}

/* Connected portal workspaces: common structure, separate business access. */
.portal-workspace { max-width:1480px; margin-inline:auto; }
.portal-workspace .work-tabs { margin-bottom:24px; }
.portal-work-layout { display:grid; grid-template-columns:minmax(0,1.7fr) minmax(280px,1fr); gap:24px; align-items:start; }
.portal-work-main,.portal-work-side { min-width:0; }
.portal-workspace .panel { background:var(--panel); border:1px solid var(--border); border-radius:12px; box-shadow:none; }
.portal-workspace .panel__title,.portal-workspace .jetzt__wozu { font-size:15px; font-weight:650; text-transform:none; letter-spacing:0; }
.portal-workspace .panel__hint { font-size:13px; line-height:1.5; }
.portal-workspace :is(.primary-btn,.ghost-btn) { min-height:44px; height:auto; white-space:normal; text-transform:none; letter-spacing:0; font-size:14px; }
.portal-workspace .jetzt { grid-template-columns:minmax(0,1fr) auto; }
.portal-workspace .jetzt__wozu { grid-column:1/-1; color:var(--text-secondary); }
.portal-workspace .jetzt__was { font-size:24px; line-height:1.25; }
.portal-workspace .jetzt__tun { grid-column:2; grid-row:2; align-self:center; }
.portal-workspace .vt-row__actions { flex-wrap:wrap; }
.portal-workspace .vpa-akt { min-width:0; }
.portal-work-side>.panel:first-child,.portal-work-main>.panel:first-child { margin-top:0!important; }
.portal-shortcuts { display:grid; border-block:1px solid var(--border); margin-bottom:20px; }
.portal-shortcuts a { display:flex; justify-content:space-between; align-items:center; gap:12px; min-height:48px; padding:10px 4px; font-size:14px; color:var(--text); border-bottom:1px solid var(--border); text-decoration:none; }
.portal-shortcuts a:last-child { border-bottom:0; }
.portal-shortcuts a:hover { color:var(--accent); background:var(--accent-soft); }
.portal-workspace :is(button,a,summary):focus-visible { outline:2px solid var(--accent); outline-offset:3px; }
.portal-workspace .doc-toolbar button { min-height:44px; padding:10px 14px; font:inherit; }
@media(max-width:800px) {
  .portal-work-layout { grid-template-columns:minmax(0,1fr); gap:20px; }
  .portal-workspace .jetzt { display:grid; grid-template-columns:minmax(0,1fr); gap:12px; }
  .portal-workspace .jetzt__tun { grid-column:1; grid-row:auto; justify-self:stretch; justify-content:center; }
  .portal-workspace .work-tabs { margin-bottom:16px; }
  .portal-workspace .work-tabs button { font-size:13px; padding-inline:10px; }
  .portal-workspace .doc-toolbar { display:flex; flex-wrap:wrap; gap:8px; }
}

.portal-home .kk-kacheln { display:grid; grid-template-columns:repeat(4,minmax(0,1fr)); gap:0; margin-bottom:24px; border-block:1px solid var(--border); }
.portal-home .kk-stat { min-height:0; height:auto; min-width:0; padding:18px 16px; border:0; border-right:1px solid var(--border); border-radius:0; background:transparent; box-shadow:none; position:relative; }
.portal-home .kk-stat:last-child { border-right:0; }
.portal-home .kk-stat .gz-ic { width:26px; height:26px; margin-bottom:4px; border-radius:6px; }
.portal-home .kk-stat .stat__value { font-size:28px; line-height:1.2; }
.portal-home .kk-stat .stat__label { white-space:normal; line-height:1.4; }
.portal-home .kk-stat .stat__bar { margin-top:10px; }
.portal-home .portal-work-main>.panel,.portal-home .portal-work-side>.panel { margin-bottom:16px; }
.portal-home .kk-kampagne { display:grid; grid-template-columns:minmax(0,1fr) auto; gap:12px; align-items:start; }
.portal-home .kk-kampagne .panel-row__main { grid-column:1; min-width:0; }
.portal-home .kk-zustand { grid-column:2; grid-row:1; }
.portal-home .kk-kampagne .kk-tun { grid-column:auto; grid-row:auto; width:auto; min-width:0; }
.portal-home .kk-schnell .kk-wege { display:grid; gap:0; }
.portal-home .kk-schnell .kk-karte { padding:14px 0; border:0; border-bottom:1px solid var(--border); background:transparent; border-radius:0; min-height:64px; }
.portal-home .kk-schnell .kk-karte:last-child { border-bottom:0; }
.portal-home .kk-schnell .gz-ic { color:var(--accent); background:var(--accent-soft); }
.portal-home .be-entwurf { flex-wrap:wrap; gap:10px; }
.portal-home .be-entwurf .panel-row__main { flex-basis:100%; }
.portal-home .be-entwurf :is(.primary-btn,.ghost-btn) { flex:1; }
.portal-history { border-top:1px solid var(--border); margin-top:24px; }
.portal-history>summary { display:list-item; cursor:pointer; padding:16px 0; min-height:52px; font-size:15px; font-weight:600; }
.portal-history[open]>summary { margin-bottom:8px; }
.portal-home .portal-records { margin-top:24px; }
@media(max-width:800px) {
  .portal-home .kk-kacheln { grid-template-columns:repeat(2,minmax(0,1fr)); margin-bottom:20px; }
  .portal-home .kk-stat { padding:14px 10px; }
  .portal-home .kk-stat:nth-child(2n) { border-right:0; }
  .portal-home .kk-stat:nth-child(n+3) { border-top:1px solid var(--border); }
  .portal-home .kk-kampagne { display:flex; flex-direction:column; align-items:stretch; }
  .portal-home .kk-zustand { order:-1; align-self:flex-start; }
  .portal-home .kk-kampagne .kk-tun { width:100%; }
}

.portal-campaign-actions { grid-column:1/-1; display:flex; justify-content:flex-end; flex-wrap:wrap; gap:8px; }
.portal-home .portal-campaign-actions .kk-tun { min-width:100px; flex:0 0 auto; }
.portal-home .kk-zustand { margin:0; width:auto; justify-content:flex-start; }
@media(max-width:800px) {
  .portal-campaign-actions { width:100%; order:3; }
  .portal-home .portal-campaign-actions .kk-tun { width:100%; }
}

/* ============================================================
   Patch-Integration — Namensraum stat (Handy); Quelle: docs/design/patch-vertraege.css
   Der Block wird bei Integration als GANZES ersetzt, nie editiert.
   Pruefblick 10.08. (A3/C2): Kachel-Wort abgeschnitten, Betrag umgebrochen,
   Suchfeld hoeher als seine Nachbarn.
   ============================================================ */
/* EINHEIT 4.1 am schmalsten Gerät — Prüfblick 10.08., Befund A3.
   Gemessen an 390 px auf der Fläche «Verträge»: das Kachel-Wort stand als
   «Jahreskosten aus Vertr…» abgeschnitten da, der Betrag brach mitten in
   «CHF 31'920.00» um. Beides widerspricht der Regel, die 4.1 mit genau
   dieser Begründung aufstellt: «nie Symbol neben dem Label — auf 390 px
   bleibt sonst kein Platz fürs Wort.»

   Die Ursache liegt in der Haus-Kachel selbst (`.stat`, style.css:1255-1256),
   nicht in einer Fläche: `.stat__label` trägt `white-space: nowrap` mit
   Ellipse, `.stat__value` trägt gar keine Umbruch-Regel. Bis 640 px greift
   bereits eine Handy-Stufe (Wert 22 px); darunter reicht sie nicht.

   Darum hier zwei Zeilen, hausweit und ohne neue Klasse:
     · Das WORT darf umbrechen statt abzureissen. Zwei kurze Zeilen sind
       lesbar, ein abgeschnittenes Wort ist es nicht.
     · Der BETRAG bleibt eine Zahl. Er bricht nicht mehr um und wird dafür
       eine Stufe kleiner — eine zerrissene Geldzahl ist schlimmer als eine
       kleinere.
   Keine neue Farbe, kein neuer Abstand, keine Ausnahme für eine Fläche. */
@media (max-width: 640px) {
  .stat__label { white-space: normal; overflow: visible; text-overflow: clip; }
}
@media (max-width: 420px) {
  /* 25.08.: 20px → 19px. Seit die Kachel wieder eine Karte mit Kante ist,
     bleiben auf 390px 127px statt 131px Innenbreite; «CHF 1'200.00» lief
     gemessen 10px hinaus. Eine Stufe kleiner haelt den Satz oben: die Zahl
     bleibt ganz. */
  .stat__value { font-size: 19px; white-space: nowrap; }
}

/* Prüfblick 10.08., Befund C2: im Erfassen-Formular sass das Label
   «Standort suchen» vier Pixel höher als «Kanton» und «Ort» daneben.
   GEMESSEN statt vermutet (Playwright, 1400 px, dieselbe Form mit je einem
   Feld je Art): Text 40 px · Datum 40 px · Auswahl 40 px · SUCHE 36 px. Die
   Form richtet ihre Reihe unten aus, also hängt das Suchfeld-Label 4 px
   daneben.
   Die Ursache ist nicht der Abstand, sondern die Bauart: ein Suchfeld
   rendert mit `appearance: searchfield` und damit einer anderen inneren
   Geometrie als ein Textfeld — dieselbe Polsterung ergibt eine andere Höhe.
   Zwei Ursachen, beide gemessen: die Bauart (`appearance: searchfield`) UND
   die globale Tap-Regel `input[type="search"] { min-height: 44px }`
   (style.css:2707), die auch am Zeigegerät greift und das Feld auf 44 px
   hebt, während seine Nachbarn 40 px hoch sind.
   Das Feld bekommt hier die Bauart des Textfelds und den Boden seiner
   Nachbarn. Die 40 px sind KEINE gewählte Zahl, sondern die gemessene Höhe
   von Text-, Zahl-, Datums- und Auswahlfeld in derselben Reihe — ohne sie
   fällt das Suchfeld auf 36 px und hängt 4 px daneben.
   Am Handy und an jedem Grobzeiger gilt weiter die Trefffläche von 44 px,
   in genau der Bedingung, in der die Form sie ohnehin für ALLE ihre Felder
   setzt (style.css:5380-5384). */
.lx-pay-form input[type="search"],
.lx-neu-form input[type="search"] {
  -webkit-appearance: textfield; appearance: textfield; min-height: 40px;
}
@media (max-width: 1024px), (pointer: coarse) {
  .lx-pay-form input[type="search"],
  .lx-neu-form input[type="search"] { min-height: 44px; }
}

/* ============================================================
   Patch-Integration — Namensraum kp-kontakt; Quelle: docs/design/patch-kontakt.css
   Der Block wird bei Integration als GANZES ersetzt, nie editiert.
   Befund W8a (10.08.2026): im ganzen Kundenportal gab es keinen Weg zu uns —
   kein mailto, keine Nummer, keine RPC, die eine liefert. Die Kontakt-Tuer
   (#/k/kontakt, RPC portal_kontakt, 20260810200410) schliesst ihn.
   ============================================================ */
/* DIE WEGE SIND TÜREN, ALSO KNOPFSTUFEN (EINHEIT 1.4).
   Bauform aus dem Bestand: `.ghost-btn--block` (docs/design/grund.css) — Titel fett,
   Angabe darunter, volle Breite. Zwei Dinge fehlen ihr für diese Fläche, und
   beide sind gemessen, nicht gewählt:

   1. `.ghost-btn--block` setzt ausdrücklich `min-height: 0` und hebt damit
      den Touch-Boden von 44 px auf (style.css:623 gilt nur für die
      unmodifizierte `.ghost-btn`). Auf einer Fläche, die AUS Türen besteht,
      ist das genau die Stelle, an der der Boden zählt — also steht er hier
      wieder da, an jedem Gerät, nicht nur am Grobzeiger.
   2. Sie ist eine Spalte (`flex-direction: column`); das Zeichen läge über
      dem Wort statt daneben. Zwei Spalten (Zeichen · Text) sind hier richtig,
      weil das Zeichen die Art des Weges trägt — Brief, Hörer, Erdkugel.

   `--gz-feld` wird gesetzt, nicht das Bauteil kopiert: dieselbe Zeile wie in
   `.kk-kacheln` (docs/design/patch-kundenzentrale.css). Die Kundenwelt ist EIN Bereich, ihre
   Zeichenfelder sind türkis. */
.kp-kontakt { display: grid; gap: 10px; --gz-feld: var(--accent-rgb); }
.kp-kontakt__weg {
  display: grid; grid-template-columns: auto minmax(0, 1fr);
  align-items: center; column-gap: 12px; row-gap: 2px;
  min-height: 44px; white-space: normal;
}
/* Das Zeichen steht über beide Textzeilen — sonst richtet es sich am Titel
   aus und sitzt bei zweizeiliger Adresse schief. */
.kp-kontakt__weg .gz-ic { grid-row: 1 / span 2; --gz-ic-gr: 28px; }
.kp-kontakt__weg > strong,
.kp-kontakt__weg > span:not(.gz-ic) { grid-column: 2; }
/* Eine lange Adresse bricht, statt die Zeile zu sprengen: `finance@…` und
   `+41 62 391 31 31` sind Zeichenketten ohne Leerzeichen zum Umbrechen, und
   die Fläche wird auf 390 px gelesen. */
.kp-kontakt__weg > span:not(.gz-ic) { overflow-wrap: anywhere; }

/* C3 (Prüfblick 10.08.): auf 1400 px stand eine Visitenkarte im Saal — drei
   Zeilen Inhalt und 500 px Nichts daneben. Eine Fläche mit genau EINER Aussage
   braucht keine Saalbreite; 640 px ist die Breite, in der die längste Zeile
   («Nenn uns die Nummer deiner Offerte oder Rechnung — …») ohne Umbruch steht
   und die Türen noch als Türen wirken. Auf dem Handy greift die Regel nie:
   `max-width` über der Gerätebreite ist wirkungslos. */
.kp-kontakt-blatt { max-width: 640px; }

/* DER NUTZEN-SATZ STEHT VOR DEN TÜREN, nicht als Fussnote dahinter — und
   damit auch nicht mehr ausserhalb des Panels, wo er 23 px links von allem
   anderen hing (Befund B9). Er ist die Anweisung an den Kunden, kein
   Nachsatz: darum Sekundär- statt Tertiärfarbe und die Lesegrösse der
   Fläche. */
.kp-kontakt__nutzen {
  margin: 0 0 12px; color: var(--text-secondary); font-size: 13px; line-height: 1.45;
}

/* Der juristische Name als Absenderzeile: klein, leise, ganz unten — er
   beantwortet «von wem kommt das», nicht «was tue ich hier» (Befund A6). */
.kp-kontakt__absender {
  margin: 12px 0 0; color: var(--text-tertiary); font-size: 11.5px; line-height: 1.45;
}

/* GEWICHTUNG (Befund B10): «Unsere Website» ist kein Weg zu uns, sondern ein
   Verweis. Sie behält ihre volle Trefffläche — nur nicht dasselbe Gewicht:
   kein farbiges Zeichenfeld, leiserer Titel, ein Hauch weniger Raum. */
.kp-kontakt__weg--leise { padding-top: 8px; padding-bottom: 8px; }
.kp-kontakt__weg--leise .gz-ic {
  background: transparent; color: var(--text-tertiary); --gz-ic-gr: 24px;
}
.kp-kontakt__weg--leise > strong { font-weight: 500; color: var(--text-secondary); }

/* ============================================================
   Patch-Integration — Namensraum zl-; Quelle: docs/design/patch-zusatzleistungen.css
   Der Block wird bei Integration als GANZES ersetzt, nie editiert.
   W9.4 «Der Zusatzleistungs-Katalog» — der Abschnitt in den Preisregeln,
   aus dem der Verkauf QR-Codes, Funnels, Landingpages, Panels, Auswertungen
   und Spot-Produktion in eine Offerte legt.
   ============================================================ */
/* ===========================================================================
   ZUSATZLEISTUNGS-KATALOG (W9.4 · Gesetz 14, 2026-08-10)
   ---------------------------------------------------------------------------
   Der Abschnitt «Was es zusaetzlich zu kaufen gibt» in den Preisregeln
   (#/v/pricing). Er erfindet KEINE Optik — er nutzt die Anatomie, die die
   Flaeche und das Haus schon tragen:

   Aus dem Bestand (hier nicht neu definiert): .pr-gruppe, .pr-zeile__wirkung,
   .panel, .panel-row/__main/__sub/__meta/__val/__tag, .stat, .stat-strip,
   .stat-strip--auto, .sl-badge (+ --aktiv/--pipeline/--still), .primary-btn,
   .ghost-btn, .empty-state, .load-error, .is-void, .zweite-reihe.

   NEU sind genau drei Dinge, und jedes hat einen Grund:
     .zl-leiste    Der Satz «was hier gilt» und der eine primaere Knopf stehen
                   in EINER Zeile. Auf 390 px bricht der Knopf darunter und
                   nimmt die volle Breite — sonst stuende er als 90-px-Stummel
                   am rechten Rand und riss den Satz auf drei Zeilen.
     .zl-verlauf   Die Preisgeschichte einer Zeile. Sie haengt UNTER ihrer
                   Zeile, eingerueckt und durch eine Haarlinie abgesetzt: so
                   ist auf den ersten Blick zu sehen, dass sie zu der Zeile
                   darueber gehoert und nicht die naechste ist.
     .zl-zeile     Nur eine Ausnahme am Bestand: die Zeile traegt am Handy
                   VIER Angaben (Einheit, Betrag, Zustand, Handlungen), und
                   .panel-row bricht sie sonst so um, dass der Betrag unter
                   dem Chip landet. Hier bleibt der Betrag an der Kante.
     .zl-rueckweg  Der Weg zurueck aus dem gefilterten Blick der Kachel.

   KEIN Primaerknopf je Zeile: die eine primaere Handlung gehoert dem
   Abschnitt («Zusatzleistung anlegen»), alles in den Zeilen ist sekundaer
   (EINHEIT 1.4). Das ist eine Entscheidung im Markup, nicht im CSS — sie
   steht hier nur, damit niemand spaeter `.zl-zeile .ghost-btn` zu einem
   Primaerknopf umlackiert.

   BEKANNTE GRENZE (nicht behoben, mit Grund): beim Oeffnen der zweiten Reihe
   wandert ihr Ausloeser «··· Mehr» vom rechten Rand auf eine eigene Zeile
   links. Das ist die Haus-Bauform und ausdruecklich so entschieden
   (patch-zweite-reihe.css: `[open] { width:100%; flex: 1 0 100% }`, nach zwei
   gescheiterten Anlaeufen mit schwebendem Fach — «kein z-index, kein
   Viewport-Rand»; und: «Dass die Zeile beim Oeffnen aufgeht, ist hier sogar
   richtig»). Sie hier allein anders zu machen hiesse: zwei Bauformen fuer
   dieselbe Sache. Was dieser Abschnitt tun konnte, hat er getan — seit dem
   Pruefblick liegt nur noch EINE Handlung im Fach, und nur an aktiven Zeilen.

   KEIN Leucht-Hof, keine neue Farbe, kein eigener Radius (_stil_integration_
   test.mjs prueft beides). Tapflaechen bleiben bei den 44 px des Hauses.
   =========================================================================== */

/* Die Kachelzeile steht dicht ueber ihrer eigenen Liste — sie ist Teil des
   Abschnitts, nicht ein zweiter Kopf darueber.

   Sie traegt GENAU EINE Kachel («welche Preise habe ich nie selbst gesetzt?»).
   `.stat-strip--auto` verteilt seine Spalten gleichmaessig ueber die volle
   Breite; eine einzelne Kachel waere damit ein 1400 px breiter Kasten um eine
   einstellige Zahl. Darum hier eine Obergrenze und linksbuendig — am Handy
   nimmt sie wieder die ganze Spalte, weil daneben nichts steht. */
.zl-kacheln { margin-bottom: 10px; grid-auto-columns: minmax(240px, 380px); justify-content: start; }
@media (max-width: 720px) {
  .zl-kacheln { grid-template-columns: minmax(0, 1fr); grid-auto-columns: auto; }
}

/* Der Rueckweg aus dem gefilterten Blick. Er steht ueber der Liste, sagt was
   gerade fehlt und traegt den Weg zurueck — ohne ihn waere die Kachel eine
   Sackgasse mit weniger Zeilen (EINHEIT 4.11: «Kein Treffer» und «noch nichts
   angelegt» sind zwei verschiedene Saetze). */
.zl-rueckweg {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; flex-wrap: wrap; margin: 0 0 10px;
  font-size: 12.5px; color: var(--text-tertiary);
}

.zl-leiste {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  margin: 0 0 10px;
}
/* Der Satz darf schrumpfen, aber nie unter Lesbreite: darunter bricht er in
   Ein-Wort-Zeilen. */
.zl-leiste .pr-zeile__wirkung { flex: 1 1 220px; min-width: 0; }
.zl-leiste .primary-btn { flex: 0 0 auto; }

.zl-liste { padding: 0; }

/* Der Betrag ist die Zahl, wegen der man herschaut — Tabellenziffern, damit
   die Kante ueber alle Zeilen haelt (EINHEIT 4.9). */
.zl-zeile .panel-row__val { font-variant-numeric: tabular-nums; white-space: nowrap; }

/* Eine abgeschaltete Zeile ist nicht kaputt, sie steht nur nicht im Angebot.
   `.is-void` traegt die Daempfung schon; hier bleibt nur der Betrag lesbar,
   weil er die Auskunft ist, die man auch dann sucht. */
.zl-zeile.is-void .panel-row__val { opacity: 1; }

/* Im Fach der zweiten Reihe liegt hier GENAU EINE Handlung. Die Hausregel
   `.lx-zweite-reihe__fach > button { width: 100% }` macht daraus einen ueber
   1300 px breiten Knopf — er saehe aus wie die Hauptsache der Flaeche, waehrend
   er das Gegenteil ist. Die Bauform bleibt, nur die Breite wird gedeckelt.
   Am Handy nicht: dort ist volle Breite die Tapflaeche. */
@media (min-width: 641px) {
  .zl-zeile .lx-zweite-reihe__fach { align-items: flex-start; }
  .zl-zeile .lx-zweite-reihe__fach > button { width: auto; min-width: 220px; }
}

.zl-verlauf {
  margin: -4px 0 8px;
  padding: 8px 14px 10px 26px;
  border-left: 2px solid var(--border);
}
.zl-verlauf__zeile {
  display: flex;
  flex-direction: column;
  gap: 1px;
  margin: 0 0 8px;
  font-size: 12.5px;
  color: var(--text-secondary);
}
.zl-verlauf__zeile:last-child { margin-bottom: 0; }
.zl-verlauf__zeile b { color: var(--text-primary); font-variant-numeric: tabular-nums; }
.zl-verlauf__zeile span { font-size: 11.5px; color: var(--text-tertiary); }

/* Handy: der Knopf nimmt die volle Breite und die volle Tapflaeche. Ein
   Primaerknopf, den man mit dem Daumen verfehlt, ist keiner. */
@media (max-width: 640px) {
  .zl-leiste { align-items: stretch; }
  .zl-leiste .primary-btn { flex: 1 1 100%; min-height: 44px; }
  .zl-verlauf { padding-left: 18px; }
}
/* ============================================================
   Patch-Integration — Namensraum ax + wv (Ausnahmen, Wirkungsvorschau); Quelle: docs/design/patch-ausnahmen.css
   Der Block wird bei Integration als GANZES ersetzt, nie editiert.
   W9.1 «Das Ausnahme-Werk» + W9.2 «Wirkungsvorschau als Pflicht jeder
   Einstellflaeche»: die Flaeche #/a/ausnahmen, das Bauteil auf sechs
   Flaechen — und am Ende die Wurzel-Reparatur am Fenster-Koerper
   (Pruefblick 10.08., Befund A7: `.modal__body` konnte nicht scrollen).
   ============================================================ */
/* W9.1 «Ausnahmen» + W9.2 «Wirkungsvorschau».

   ZWEI NAMENSRAEUME, EIN BLOCK — weil sie zusammen entstanden sind und die
   Vorschau auf JEDER Einstellflaeche steht, nicht nur auf der Ausnahmen-Seite:
     .ax-*  die Flaeche «Ausnahmen» (#/a/ausnahmen)
     .wv-*  das Bauteil «Wirkungsvorschau» (components/wirkungsvorschau.js)
     .pr-wirkung  ihr Platz in den Preisregeln

   KEINE NEUE FARBE, KEIN NEUER ABSTAND. Alles kommt aus den Tokens:
   --surface-inset, --border, --text-primary/-secondary/-tertiary, --accent.
   Zustaende sind gerahmte Chips der bestehenden Bauart (.sl-badge, EINHEIT
   4.7); Knoepfe sind .primary-btn/.ghost-btn (1.4). Der Seitentitel kommt aus
   .admin-page__head und wird hier NICHT angefasst (1.5, 26 px).

   HANDY ZUERST GEDACHT. Jede Reihe darf umbrechen, jede Zelle traegt
   min-width: 0, jeder lange Grund bricht im Wort statt die Seite zu
   verbreitern. Auf 390 px steht die Zahl der Vorschau ueber ihrem Text statt
   daneben — sonst bliebe fuer das Wort kein Platz (dieselbe Ueberlegung wie
   in EINHEIT 4.1 fuer die Kachel). */

/* --- Die Flaeche «Ausnahmen» ---------------------------------------------- */
.ax-page .ax-kacheln { margin-bottom: 18px; }

.ax-liste { list-style: none; margin: 0; padding: 0; }
.ax-zeile {
  padding: 14px 16px;
  border-top: 1px solid var(--border);
  min-width: 0;
}
.ax-liste > .ax-zeile:first-child { border-top: 0; }
.ax-zeile__kopf {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
  min-width: 0;
}
.ax-regel { color: var(--text-primary); font-size: 14px; min-width: 0; }
.ax-ebene { color: var(--text-secondary); font-size: 12.5px; min-width: 0; }
.ax-wert { margin: 6px 0 0; color: var(--text-primary); font-size: 13px; }
.ax-gueltig { margin: 2px 0 0; color: var(--accent-strong); font-size: 12.5px; }
.ax-grund {
  margin: 4px 0 0; color: var(--text-secondary); font-size: 12.5px;
  overflow-wrap: anywhere;
}
.ax-grund--zurueck { color: var(--text-tertiary); }
.ax-zeile__akt { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }
/* Der Rueckweg ist keine Zerstoerung: die Zeile bleibt lesbar. Darum die
   normale Sekundaerstufe und NICHT die rote destruktive (EINHEIT 1.4). */
.ax-zeile__akt .ghost-btn { min-height: 36px; }

.ax-verlauf {
  list-style: none; margin: 10px 0 0; padding: 10px 0 0;
  border-top: 1px dashed var(--border);
}
.ax-verlauf li {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 8px;
  padding: 4px 0; font-size: 12.5px; color: var(--text-secondary);
  min-width: 0;
}
.ax-verlauf__wann { color: var(--text-tertiary); font-variant-numeric: tabular-nums; }
.ax-verlauf__wer { color: var(--text-primary); }
.ax-verlauf__grund { overflow-wrap: anywhere; }

.ax-form__felder {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 12px; padding: 0 16px 4px;
}
.ax-form__felder .field--wide { grid-column: 1 / -1; }
.ax-form__akt { display: flex; flex-wrap: wrap; gap: 8px; padding: 14px 16px; }

.ax-register summary { cursor: pointer; padding: 14px 16px; }
.ax-register summary h3 { display: inline; margin: 0; }
.ax-register__liste { list-style: none; margin: 0; padding: 0 16px 14px; }
.ax-register__liste li {
  display: grid; gap: 2px; padding: 10px 0;
  border-top: 1px solid var(--border); min-width: 0;
}
.ax-register__wo {
  color: var(--text-tertiary); font-size: 12px;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  overflow-wrap: anywhere;
}
.ax-register__warum {
  color: var(--text-secondary); font-size: 12.5px; overflow-wrap: anywhere;
}

/* --- Das Bauteil «Wirkungsvorschau» --------------------------------------- */
.wv {
  background: var(--surface-inset);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  padding: 12px 14px;
  min-width: 0;
}
.wv-kopf { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.wv-summe { color: var(--text-secondary); font-size: 12.5px; min-width: 0; }
.wv-titel {
  margin: 12px 0 4px; color: var(--text-tertiary);
  font-size: 12px; font-weight: 600;
}
.wv-liste { list-style: none; margin: 8px 0 0; padding: 0; }
.wv-zeile {
  display: flex; align-items: baseline; gap: 10px;
  padding: 5px 0; min-width: 0;
}
.wv-zahl {
  flex: 0 0 auto; min-width: 34px;
  color: var(--text-primary); font-size: 18px; font-weight: 650;
  font-variant-numeric: tabular-nums;
}
.wv-zeile--ruhig .wv-zahl, .wv-zeile--offen .wv-zahl { color: var(--text-tertiary); }
.wv-text { display: grid; gap: 2px; min-width: 0; }
.wv-was { color: var(--text-primary); font-size: 13px; }
.wv-zeile--ruhig .wv-was, .wv-zeile--offen .wv-was { color: var(--text-secondary); }
.wv-hinweis { color: var(--text-tertiary); font-size: 12px; overflow-wrap: anywhere; }
.wv-laedt { margin: 0; color: var(--text-tertiary); font-size: 12.5px; }
.wv--fehler .ghost-btn { margin-top: 8px; }

/* Ihr Platz in den Preisregeln: eigener Streifen zwischen Kopf und
   Sprungleiste, damit «gilt sofort, trifft N» im Blick steht, bevor jemand
   auf «Speichern» zielt. */
.pr-wirkung { margin: 0 0 14px; }
.pr-wirkung[hidden] { display: none; }

@media (max-width: 640px) {
  .ax-form__felder { grid-template-columns: 1fr; }
  /* Am schmalen Gerät stehen Wirkung und Grund UNTEREINANDER. Nebeneinander
     blieben für die Vorschau 150 px — die Zahl bricht dann in drei Zeilen und
     das Grund-Feld wird schmaler als sein eigener Platzhalter (gemessen am
     390-px-Bild, 10.08.). Die Reihenfolge bleibt: erst wen es trifft, dann
     warum. */
  .ax-form__entscheid { grid-template-columns: 1fr; }
  .ax-zeile { padding: 14px 12px; }
  .ax-form__felder, .ax-form__entscheid, .ax-form__akt,
  .ax-register summary, .ax-register__liste { padding-left: 12px; padding-right: 12px; }
}

/* Grobzeiger: jede Tuer traegt die Treffflaeche des Hauses (>= 44 px). */
@media (max-width: 1024px), (pointer: coarse) {
  .ax-zeile__akt .ghost-btn,
  .ax-form__akt .primary-btn, .ax-form__akt .ghost-btn,
  .wv--fehler .ghost-btn { min-height: 44px; }
}

/* Auf dem schmalsten Geraet steht die Zahl UEBER ihrem Wort: nebeneinander
   bliebe bei «Standortbetreiber ohne eigene Vereinbarung» kein Platz, und ein
   abgeschnittenes Wort ist schlimmer als eine Zeile mehr. */
@media (max-width: 420px) {
  .wv-zeile { display: grid; grid-template-columns: 1fr; gap: 0; }
  .wv-zahl { min-width: 0; }
}

/* --- Ihr Platz auf den übrigen Einstellflächen (Nachschnitt W9.2) ---------
   Vier Flächen, dieselbe Bauform, kein eigenes Aussehen: die Vorschau bringt
   ihre Gestaltung aus `.wv` oben mit. Hier steht nur, WO sie sitzt und wie
   viel Luft sie zu ihren Nachbarn hält.
     .lx-policy__wirkung  Regeln & Freigaben (components/policy-switches.js)
     .lx-satz-wirkung     neuer Mehrwertsteuer-Satz (buchhaltung-kontenplan.js)
     .vt2-form__wirkung   Abmachung mit einem Vertrieb (vertrieb-detail.js)
     .tm-wirkung          Deal mit einem Standortbetreiber (partner-detail.js)
   Jede von ihnen steht ÜBER den Knöpfen: gelesen wird vor dem Klick. */
.lx-policy__wirkung { margin: 0 0 14px; }
.lx-satz-wirkung { margin: 12px 0 0; }
/* `.vt2-form` ist ein Grid (docs/design/patch-vertriebe.css) — die Vorschau nimmt die ganze
   Breite, sonst stünde sie als schmale Spalte neben einem Feld. */
.vt2-form__wirkung { grid-column: 1 / -1; margin: 4px 0 0; }
.tm-wirkung { margin: 10px 0 0; }
.lx-policy__wirkung[hidden], .lx-satz-wirkung[hidden],
.vt2-form__wirkung[hidden], .tm-wirkung[hidden] { display: none; }

/* --- Prüfblick 10.08. · die benannten Nachschnitte ------------------------
   B1  «Gilt ab» und «Gilt bis» sind EIN Wert mit zwei Enden. Im freien
       Raster (auto-fit, minmax 220px) rissen sie über zwei Reihen
       auseinander und lasen sich wie zwei unabhängige Fragen.
   B3  Das native Aufklapp-Dreieck an «Regeln, die woanders gepflegt werden»
       ist das einzige im ganzen Haus geblieben — die fünf anderen `details`
       (`.so2-advanced`, `.sof-freiheit`, `.sof-feinheiten`, `.pnl-block`,
       `.so-loclist`) setzen es zurück und zeichnen ihren eigenen Winkel.
   B16 Ein Stichtag ist keine Warnung. «Gilt ab 01.01.2027» trug die
       Bernstein-Marke der Mahnstufen; das Auge las ein Problem, wo eine
       Terminangabe stand. Neutrale Marke, ohne neue Farbe.
   Dramaturgie: der Pflichtgrund — das Einzige, was diese Fläche auditierbar
       macht — stand als schmalstes Feld unter der Vorschau. Er steht jetzt
       neben ihr: links wen es trifft, rechts warum. */

.ax-zeitraum {
  grid-column: 1 / -1;
  display: grid; gap: 12px;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  align-items: end;
}

.ax-form__entscheid {
  display: grid; gap: 12px; align-items: start;
  grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr);
  padding: 4px 16px 0;
}
.ax-form__grund { min-width: 0; }
.ax-form__grund textarea { resize: vertical; min-height: 88px; }

/* B3 — Marker-Reset in der Bauart der fünf anderen `details` des Hauses
   (Muster `.sof-freiheit`, docs/design/patch-offerte.css): Dreieck weg, eigener Winkel
   rechts, der beim Öffnen kippt. */
.ax-register > summary { list-style: none; cursor: pointer; display: flex; align-items: center; }
.ax-register > summary::-webkit-details-marker { display: none; }
.ax-register > summary::after {
  content: '';
  margin-left: auto;
  width: 8px; height: 8px;
  border-right: 1.6px solid var(--text-tertiary);
  border-bottom: 1.6px solid var(--text-tertiary);
  transform: rotate(45deg) translate(-2px, -2px);
  transition: transform var(--dur-fast) var(--ease);
}
.ax-register[open] > summary::after { transform: rotate(-135deg) translate(-2px, -2px); }

/* B16 — die Marke eines Stichtags. Gerahmter Chip wie jeder andere
   (EINHEIT 4.7), aber in der neutralen Leiter statt in Bernstein. */
.wv-marke--datum {
  background: rgba(var(--tint-rgb), .10);
  color: var(--text-primary);
  border-color: var(--line-strong);
}

/* --- A7 · NACHGEMESSEN: hier war KEINE Reparatur nötig --------------------
   Der Prüfblick meldete am 390-px-Gerät im Betreiber-Dossier: Knöpfe 63 px
   über der Vorschau, Text 84 px unter der Fensterkante, «nichts scrollt».

   NACHGEMESSEN am 10.08. mit `scripts/lib/buehnen-mass.mjs` — und zwar am
   `.modal__body`, nicht am `.modal` darum:
     390 x 844   abgeschnitten 351 px, scrollt = true
     1400 x 560  abgeschnitten 388 px, scrollt = true
   Der Körper SCHRUMPFT und scrollt an beiden Breiten. Er darf das auch ohne
   zusätzliche Regel: ein Flex-Kind mit `overflow-y: auto` bekommt als
   automatische Mindestgrösse 0, nicht seine Inhaltshöhe. Eine Zeile
   `min-height: 0` stand hier eine Stunde lang und wurde wieder entfernt,
   nachdem die Gegenprobe zeigte, dass ihr Abschalten NICHTS ändert
   (`_ausnahmen_ui_test.mjs`, Abschnitt 14c) — eine Regel, die nichts
   bewirkt, ist eine Behauptung.

   Die 63 px sind ebenfalls kein Befund: `.modal-actions` ist unter 720 px
   `position: sticky; bottom: 0` (style.css:1215) — eine klebende Leiste
   LIEGT über dem Inhalt, dafür ist sie gebaut. Die Geometrie-Probe kennt
   den Unterschied inzwischen und wertet klebende Überdeckung nicht als
   Mangel.

   WAS BLEIBT, ist die Messung: dass dieses Fenster scrollt und dass seine
   Knöpfe erreichbar bleiben, steht ab jetzt in einer Probe statt in einem
   Screenshot — an sechs Flächen, nicht an einer. */

/* ============================================================
   Patch-Integration — Namensraum lx-firma; Quelle: docs/design/patch-firma.css
   Der Block wird bei Integration als GANZES ersetzt, nie editiert.
   Nachschnitt zum Kontaktweg W8a (10.08.2026): die Absenderzeile des Hauses
   (sales_settings.key='firma') war an keiner Stelle pflegbar.
   ============================================================ */
/* DIE FELD-BESCHRIFTUNG STEHT IN GEMISCHTER SCHREIBUNG (EINHEIT 1.5).
   Seit der Schlichtung vom 10.08. (Prüfblick W9, Querschnitt Q1) trägt die
   Haus-Klasse `.field span` die gemischte Form selbst (style.css, Kern) —
   der Opt-out, der zuerst hier stand, ist an die Wurzel eingezogen. */

/* Eine Reihe je Panel. Die Felder tragen ihre eigene Breite (`.field--wide`,
   `.field--narrow`, style.css:501-502); unter 1024 px zieht die Haus-Regel
   jedes Feld ohnehin auf volle Breite (style.css:1207) — hier wird nichts
   nachgebaut, nur der Abstand gesetzt. */
.lx-firma__reihe { display: flex; flex-wrap: wrap; gap: 12px 14px; align-items: flex-start; }
/* Zwei Reihen brauchen Luft dazwischen: ohne sie klebte die Hilfe der
   ersten Reihe an der Beschriftung der zweiten (am Bild gesehen). */
.lx-firma__reihe + .lx-firma__reihe { margin-top: 14px; }

/* Die Hilfe steht AM FELD, nicht als Erklärabsatz unter dem Titel (EINHEIT
   1.6). Sie sagt genau eine Sache: die Grenze, an der es später sonst
   scheitert — «höchstens 70 Zeichen», «CH oder LI, 21 Zeichen». */
.lx-firma__hilfe { color: var(--text-tertiary); font-size: 11.5px; line-height: 1.35; }

/* Fuss: der eine Knopf und daneben der Satz, WO die Angaben ab jetzt stehen.
   Auf 390 px untereinander, damit der Knopf seine ganze Breite behält. */
.lx-firma__fuss { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 14px; margin-top: 4px; }
.lx-firma__fuss .primary-btn { min-height: 44px; }
.lx-firma__wirkung { margin: 0; color: var(--text-secondary); font-size: 13px; line-height: 1.4; }
.lx-firma__wirkung:empty { display: none; }
@media (max-width: 640px) {
  .lx-firma__fuss { flex-direction: column; align-items: stretch; }
  .lx-firma__fuss .primary-btn { width: 100%; }
}

/* Der Stern und seine Legende (Befund B13). Der Stern stand an drei Feldern
   und erklärte sich nirgends; jetzt trägt er einen Titel für die Maus und die
   Legende steht unter der Gruppe, in der er vorkommt. `text-decoration: none`,
   weil `<abbr>` sonst gepunktet unterstreicht — hier ist der Stern die
   Markierung, nicht ein Wort mit Erklärung. */
.lx-firma__stern { color: var(--accent); text-decoration: none; margin-left: 2px; }
.lx-firma__legende {
  margin: 10px 0 0; color: var(--text-tertiary); font-size: 11.5px; line-height: 1.4;
}

/* Der Abschluss ist ein Panel wie die anderen — der Knopf gehört zu etwas.
   Die Vorschau steht darüber, weil man die Wirkung liest, BEVOR man drückt. */
.lx-firma__vorschau { margin-bottom: 12px; }
.lx-firma__vorschau:empty { display: none; }

/* ============================================================
   Patch-Integration — Namensraum pr-; Quelle: docs/design/patch-fristen.css
   Der Block wird bei Integration als GANZES ersetzt, nie editiert.
   ============================================================ */
/* =========================================================================
   Fristen (#/v/pricing, Gruppe «Fristen und Mahnstufen») — W9.3, Nachtrag
   aus dem unabhängigen Prüfblick vom 10.08.2026 (Befunde A3, B5, C1 und die
   Dramaturgie-Anmerkung zur Mahnstaffel).

   Namensraum: `pr-` (die Fläche hat ihn seit patch-preise.css) — hier kommen
   genau drei Regeln dazu, keine neue Farbe, kein neues Mass ausserhalb des
   bestehenden Rasters.

   WAS DIE DREI BEFUNDE WAREN:

   A3 — «Gelb», «Orange» und «Rot» standen alle drei in TÜRKIS. Ursache:
   `.pr-zeile__satz b { color: var(--accent-strong) }` (patch-preise.css) —
   die Akzentregel gilt der ZAHL im Satz, ihr eigener Kommentar sagt das. Der
   Stufenname lag aber ebenfalls in `<b>`. Dreimal die falsche Farbe auf einem
   Bild, auf dem der Owner am Bild urteilt.
   Behoben in `sales-pricing.js` (der Name ist jetzt ein Chip, die Zahl bleibt
   `<b>`) — hier steht nur, wie der Chip IM SATZ sitzt. Die Farben sind
   zeichengleich die der Rechnungsliste (`VERZUG_BADGE`,
   sales-invoices.js:65): derselbe Chip an der Regel wie an ihrer Wirkung.

   B5 — DIE FELDSPALTE FLATTERTE. Gemessen auf 1680 px: die «Werktage»-Zelle
   war 167 px breit, alle «Tage»-Zellen 138 px; die linke Kante der Spalte
   sprang zwischen 1480 px und 1509 px. Der Kommentar über `.pr-schalter`
   verspricht ausdrücklich «derselbe Platz rechts, damit die Spalte hält» —
   für das Feld selbst stand die Regel nie da. Sie steht jetzt: ein festes
   Mass für den Block, das Zahlenfeld füllt den Rest. Damit enden ALLE Zahlen
   und ALLE Einheiten auf derselben Linie, unabhängig vom längsten Wort.
   Bewusst NUR in dieser Gruppe: die Preismatrix und die Vergütungen tragen
   kurze Einheiten und brauchen die Reserve nicht.

   C1 — DIE KUNDENSCHUTZ-ZEILE war die einzige Zeile der Gruppe ohne
   Akzentzahl (sie ist ein Verweis: gepflegt wird die Nachfrist im
   Regel-Zentrum). In der Zahlenspalte war das ein sichtbares Loch, und
   ausgerechnet die eine Zahl, die man NICHT hier setzt, sah aus wie keine
   Zahl. Behoben in `sales-pricing.js` (`wortHtml`); hier nichts zu tun —
   `.pr-zeile__satz b` gilt für Verweiszeilen ohnehin.

   DRAMATURGIE — die drei Mahnstufen hängen voneinander ab: Gelb vor Orange
   vor Rot, sonst weist der Server sie ab (`verzug_schwellen`,
   20260808000047:463). Als drei gleichrangige Zeilen gelesen, sieht man das
   nicht. Kleinste Form, die es zeigt: eine Einrückung und eine durchgehende
   senkrechte Linie an ihrer linken Kante — eine Treppe, kein Umbau. Kein
   neues Bauteil, keine Überschrift, kein Erklärtext.
   ========================================================================= */

/* A3 · Der Zustands-Chip sitzt IM Satz, ohne die Zeile höher zu machen.
   `.sl-badge` bringt Rahmen, Farbe und Radius mit (EINHEIT 4.7) — hier nur
   die Ausrichtung auf die Schriftlinie des Satzes und ein Hauch Luft danach. */
.pr-zeile__satz .sl-badge {
  vertical-align: 1px;
  margin-right: 2px;
  letter-spacing: .02em;
}

/* B5 · Die Feldspalte hält. 172 px = das breiteste gemessene Feld dieser
   Gruppe («Werktage», 167 px) plus zwei Pixel Luft auf jeder Seite. Das
   Zahlenfeld gibt seine feste Breite auf und füllt den Rest — so bleibt die
   Zahl rechtsbündig am selben Punkt, egal wie lang die Einheit ist. */
.pr-gruppe[data-slot="fristen"] .pr-feld {
  width: 172px;
  justify-content: flex-end;
}
.pr-gruppe[data-slot="fristen"] .pr-feld input {
  flex: 1 1 auto;
  width: auto;
  min-width: 0;
}

/* Dramaturgie · Die Mahnstaffel als Treppe.
   Die Linie läuft durch alle drei Zeilen durch (jede trägt sie, die erste
   beginnt sie) — dadurch liest sich die Gruppe als EIN Ding mit drei Stufen.
   `--line-strong` statt einer Signalfarbe: die Linie ordnet, sie warnt nicht;
   die Farbe tragen die Chips. */
.pr-zeile--stufe {
  padding-left: 14px;
  border-left: 2px solid var(--line-strong);
  margin-left: 2px;
}
.pr-zeile--stufe-erste { border-top-left-radius: 3px; }

/* Handy: die Einrückung bleibt (sie ist die Aussage), die Feldbreite nicht —
   dort steht das Feld ohnehin unter dem Satz und nimmt die volle Zeile. */
@media (max-width: 640px) {
  .pr-gruppe[data-slot="fristen"] .pr-feld { width: 100%; }
  .pr-zeile--stufe { padding-left: 10px; }
}

/* ============================================================
   Patch-Integration — Namensraum stat/kpi-pill (Aktiv-Zustand); Quelle: docs/design/patch-kennzahl-kachel.css
   Der Block wird bei Integration als GANZES ersetzt, nie editiert.
   Pruefblick 10.08., Befund A2: `aria-current="page"` stand seit W5.2 im
   Bauteil, hatte aber keinen sichtbaren Zustand — der gewaehlte Filter war
   fuer das Auge unsichtbar.
   ============================================================ */
/* DER SICHTBARE AKTIV-ZUSTAND DER KENNZAHL-KACHEL
   (Prüfblick 10.08., Befund A2 — Bauteil-CSS, kein Flächen-CSS.)

   DER BEFUND. Seit dem Kachel-Pass (W5.2) setzt `components/kennzahl-kachel.js`
   auf der Kachel, die den gerade geltenden Filter meint, `aria-current="page"`.
   Die Vorlese-Hilfe erfährt damit, welcher Ausschnitt unten steht — das AUGE
   erfuhr es nirgends: einen `[aria-current]`-Stil für `.stat` gab es in der
   ganzen Datei nicht. Auf der Fläche «Ausnahmen» standen vier Kacheln
   nebeneinander, eine davon war der aktive Filter, und nichts zeigte welche.

   WARUM ER HIER STEHT UND NICHT IN EINER FLÄCHE. Vierzehn Flächen tragen
   diesen Streifen, und alle bauen ihn aus demselben Bauteil. Ein Aktiv-Zustand
   je Fläche wären vierzehn Zustände, die auseinanderlaufen — die Kachel ist
   EIN Bauteil, also hat sie EINEN Aktiv-Zustand. Jede Fläche, die den Pass
   schon besteht, erbt ihn ohne eine Zeile Arbeit.

   DIE FORM. EIN Akzent (EINHEIT 1.3): Türkis trägt im Haus den aktiven
   Zustand. Kante und Soft-Fläche aus den bestehenden Tokens `--accent-line`
   und `--accent-soft`, dazu die Inset-Bar links, die das Haus überall für
   «hier bist du» benutzt (EINHEIT 4.5). Kein Leucht-Hof — die Bar ist eine
   Kante mit Weichzeichnung 0 und bleibt damit im erlaubten Bereich
   (`scripts/_stil_integration_test.mjs`, Klasse KANTE).

   KEIN VERWECHSELN MIT HOVER. Die Hover-Fläche des Hauses ist neutral
   (`--surface-3`); der Aktiv-Zustand ist farbig. Wer mit der Maus über eine
   fremde Kachel fährt, sieht darum weiterhin einen anderen Zustand als den
   gewählten Filter. */
.stat[aria-current="page"] {
  border-color: var(--accent-line);
  background: var(--accent-soft);
  box-shadow: inset 2.5px 0 0 var(--accent);
}
.stat[aria-current="page"] .stat__label {
  color: var(--accent-strong);
}
/* Der Zustand überlebt den Hover: wer die aktive Kachel überfährt, darf nicht
   den Eindruck bekommen, sie sei es nicht mehr. */
.stat[aria-current="page"]:hover {
  border-color: var(--accent-line);
  background: var(--accent-soft);
}

/* Dieselbe Aussage an der zweiten Bauform des Hauses — der Kennzahl-Pille
   («Heute», `.kpi-pill`). Sie trägt keine Box, sondern eine linke Haarlinie;
   der aktive Zustand färbt genau diese Linie und das Wort darüber. */
.kpi-pill[aria-current="page"] {
  border-left-color: var(--accent);
}
.kpi-pill[aria-current="page"] > span {
  color: var(--accent-strong);
}

/* ===========================================================================
   Patch-Integration — Namensraum kf-; Quelle: docs/design/patch-konfigurator-w10.css
   =========================================================================== */
/* ===========================================================================
   W10.1 · P12 — DER ABLAUF-UMBAU DES OFFERTEN-KONFIGURATORS
   ===========================================================================
   Eigener Block. Der bestehende `patch-konfigurator.css` bleibt unangetastet;
   was hier steht, ergänzt ihn oder überschreibt bewusst einzelne Regeln (dann
   steht der Grund an der Regel). Zeichengleich gespiegelt am Ende von
   `public/style.css`.

   Bildreferenz: `docs/design/referenzen/konfigurator-greenfield-2026-08-10/`
   — seit dem 03.09.2026 AUCH FARBTREU. Bis dahin stand hier «richtungstreu,
   nie farbtreu; das Blau der Referenz kommt nicht ins Haus» (F-Karte Nr. 28,
   Verbotsliste 4, aus EINHEIT §1.3 vom Juli). Der Owner hat den Türkis-Bau
   gesehen und geurteilt: «das UI, die Farbe etc. hast du falsch verstanden».
   Die Farbwelt der Referenz (blauschwarzer Grund, Haarlinien, gesperrte
   Versalien, eisheller Hauptknopf, Blau-Tönung für «gewählt», Grün/Bernstein
   für den Stand) steht seither als Tokens in `grund.css` (:root) und gilt
   im ganzen Haus. Die alte Verbotsliste ist damit überholt, nicht gelöscht.

   Owner-Präzisierung 10.08., wörtlich: «auch als UI/UX sauber, geräumig,
   wirkt professionell, nicht überladen, nicht einfach draufgeklebt, kein
   komisches Verhalten». Deshalb hier: keine neue Farbe, keine neue
   Schriftgrösse ausserhalb der Haus-Skala, kein zweiter Akzent — nur Raum,
   Reihenfolge und Hierarchie.
   =========================================================================== */


/* Band, fünf Blätter, Galerie und Korb-Streifen (02.09.2026) stehen in
   patch-konfigurator-blaetter.css — eigenes Blatt, direkt nach diesem in der
   Kaskade (Grund: Kopf jenes Blatts). */

/* ---- Eine Wahl, die umbricht statt überzulaufen -------------------------
   `.kf-segment` ist die Einfachwahl dieser Fläche (Körnung, Zählregel,
   Gliederung). Für den Bedarf und den Spot-Weg stehen dort Wörter statt
   Kürzel, und die Spalten sind 210–310 px breit: ohne Umbruch quetschte
   `flex: 1 1 0` drei Wörter auf je 60 px. Die Variante bricht um und lässt
   jedem Knopf seine Wortbreite. */
.kf-segment--brechend { flex-wrap: wrap; }
.kf-segment--brechend > button {
  flex: 1 1 auto;
  min-width: 0; max-width: 100%;
  white-space: normal; overflow-wrap: anywhere;
  padding: 8px 10px; line-height: 1.4;
  text-align: center;
}

/* ---- Die Zusammenfassungs-Chips (Referenz Szene 5) ----------------------
   Je Chip eine beantwortete Frage: kleines Wort, kräftige Antwort. Gerahmt
   und in gemischter Schreibung — Versalien bleiben dem Tabellenkopf
   vorbehalten. Was noch keine Antwort hat, steht gestrichelt da und sagt
   «offen»: eine Lücke, die man sieht, ist besser als eine, die fehlt. */
/* FLACH STATT KASTEN (Owner «Widget», 2026-08-13): jede beantwortete Frage war
   ein kleines umrandetes Kaestchen auf var(--surface). Jetzt Label + Wert als
   reiner Text, die Paare durch grosszuegigen Abstand getrennt — kein Rahmen,
   kein Radius, kein Grund. Das kleine Label ueber dem kraeftigen Wert gruppiert
   jedes Paar fuer sich. */
.kf-chips { display: flex; flex-wrap: wrap; gap: 6px 14px; margin-top: 2px; }
.kf-chip {
  /* 7px = 6px altes Padding + 1px alter Rahmen: gleiche Hoehe, kein Kasten. */
  display: grid; gap: 1px;
  padding: 7px 10px 7px 0; border: 0; border-radius: 0; background: transparent;
  min-width: 0;
}
.kf-chip small {
  font-size: 11px; font-weight: 600; letter-spacing: .01em;
  color: var(--text-tertiary);
}
.kf-chip b {
  font-size: 12.5px; font-weight: 650;
  color: var(--text-primary);
}
/* Ohne Antwort: kein gestrichelter Kasten mehr, nur ein gedaempfter Wert. */
.kf-chip.is-offen b { font-weight: 600; color: var(--text-tertiary); }

/* ---- Das Wahrheits-Register --------------------------------------------
   Drei Sätze, drei Stufen: was gerechnet ist, was offen ist, was nicht
   enthalten ist. Sie lagen an drei Orten der Fläche; hier stehen sie
   untereinander an einem. */
/* FLACH STATT KASTEN (Owner «Widget», 2026-08-13): die drei Wahrheiten
   (berechnet / offen / nicht enthalten) standen je in einem umrandeten, teils
   gefaerbten Kasten. Jetzt drei Textzeilen untereinander, durch Abstand
   getrennt; die Stufe bleibt ueber die Farbe erkennbar (Akzent-Leitwort =
   berechnet, Warn-Text = offen) — ohne Rahmen, Radius und Grund. Padding und
   Marge bleiben wie zuvor: entfernt ist nur die Kasten-Optik, die Hoehe der
   Ausgabe traegt unveraendert (klebender Positionskopf, Roll-Raster). */
.kf-register {
  margin: 6px 0 0;
  /* 8px = die 7px Padding PLUS die 1px des alten Rahmens: dieselbe senkrechte
     Hoehe wie der Kasten, nur ohne Rahmen — so bleibt die Ausgabe-Anatomie
     (Roll-Raster, klebender Positionskopf) millimetergenau wie zuvor. */
  padding: 8px 10px;
  border: 0; border-radius: 0; background: transparent;
  font-size: 11.5px; line-height: 1.45;
  color: var(--text-secondary);
}
.kf-register b { font-weight: 650; color: var(--text-primary); }
.kf-register--gut b { color: var(--accent-strong); }
.kf-register--offen { color: var(--warn-strong); }
.kf-register--offen b { color: var(--warn-strong); }

/* ---- Die lebende Preisleiste -------------------------------------------
   Die Referenz stellt den Preis gross an den Anfang ihrer Prüf-Szene. Bei
   uns stand er als vierter Block ganz rechts. Er steht jetzt an zweiter
   Stelle — und trägt die Grösse, die eine Endzahl verdient. Ein Grad über
   `.kf-zeile.is-stark b` (18px), kein zweiter Seitentitel. */
.kf-block--preis .kf-zeile.is-stark b { font-size: 25px; letter-spacing: -.015em; }

/* Die Positionen sind eine Tabelle mit sechs Spalten. Seit die Ausgabe acht
   Blöcke trägt, sind zwei Spuren zu wenig: «Coiffure Bellevue · Zürich · 3
   Bildschirme» brach über vier Zeilen. Drei Spuren geben ihr die Breite
   zurück, die sie vor dem Umbau hatte. */
.kf-block--positionen { grid-column: span 3; }
@media (max-width: 1080px), (pointer: coarse) {
  .kf-block--positionen { grid-column: auto; }
}

/* DER SOCKEL TRÄGT DIE FÜHRUNG (Runde 3, C-2).
   Hier stand die Markenzeile «Precision. Presence. Impact.» und daneben die
   Zusammensetzung des Totals — die achte Wiederholung derselben Aussage auf
   EINEM Bildschirm. Jetzt steht dort der nächste fehlende Schritt als Satz,
   wie in der Referenz («AUSSPIELUNG FESTLEGEN →»). Die Versalien des Hauses
   bleiben: das ist kein Fliesstext, sondern eine Marke am Blattende — und
   sie trägt jetzt die Farbe des Akzents, weil sie eine Aufforderung ist und
   keine Zierde. `span` (die zweite, leise Zeile) gibt es auf dieser Fläche
   nicht mehr; die Regel dafür ist ersatzlos entfallen. */
.cp:has(.kf-wo) .cp__signatur strong { color: var(--accent-strong); }

/* Zwei Griffe nebeneinander statt zwei Zeilen: «+ Zusatzleistung» und
   «+ Freie Position» sind dieselbe Art Handlung. */
.kf-tunreihe { display: flex; flex-wrap: wrap; gap: 6px; }
.kf-tunreihe .kf-add { margin-top: 6px; }

/* Wort links, Zahl rechts — in EINER Zeile. Für kurze Zahlenfelder in den
   schmalen Spalten; das Hausmuster `.kf-feld` stellt sie sonst untereinander
   und kostet je Feld eine Zeile. */
.kf-feld--eng {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
}
.kf-feld--eng > span { margin: 0; flex: 1 1 auto; min-width: 0; }
.kf-feld--eng > input { flex: 0 0 auto; width: 84px; text-align: center; }

/* ---- W10-6 · Der Pfad und der eine Sammel-Griff -------------------------
   Beide stehen zwischen Suchfeld und Liste — in JEDER Tiefe an derselben
   Stelle. Die Referenz setzt genau darauf: derselbe Griff, dieselbe Stelle,
   drei Zustände. */
.kf-pfad {
  display: flex; align-items: center; justify-content: space-between;
  flex-wrap: wrap; gap: 6px 10px;
  margin: 6px 0 4px;
}
.kf-pfad__weg { display: flex; align-items: center; flex-wrap: wrap; gap: 3px; min-width: 0; }
.kf-pfad__weg > span {
  font-size: 12px; color: var(--text-tertiary);
}
.kf-pfad__weg > button {
  min-height: 28px; padding: 0 7px;
  border: 0; border-radius: var(--radius-badge);
  color: var(--text-secondary); background: transparent;
  font: inherit; font-size: 12px; font-weight: 600; cursor: pointer;
}
.kf-pfad__weg > button:hover { color: var(--accent-strong); background: var(--surface-3); }
.kf-pfad__weg > button[aria-current="location"] {
  color: var(--accent-strong); background: var(--accent-soft);
}
.kf-sammeln {
  min-height: 30px; padding: 0 11px;
  border: 1px solid var(--accent-line); border-radius: var(--radius-button);
  color: var(--accent-strong); background: var(--accent-soft);
  font: inherit; font-size: 11px; font-weight: 650; letter-spacing: .06em; text-transform: uppercase; cursor: pointer;
  white-space: nowrap;
}
.kf-sammeln:hover { border-color: var(--accent); }
.kf-sammeln.is-voll {
  border-color: var(--border); color: var(--text-secondary); background: var(--surface);
}
.kf-sammeln small { font-weight: 600; opacity: .8; }

/* «›» — eine Tiefe hinunter. Eigener Griff neben der Zeile, damit «öffnen»
   und «wählen» sich nicht ins Gehege kommen (F Teil 5 Nr. 9). */
.kf-tiefe-auf {
  flex: 0 0 auto;
  /* 24 × 24 ist der Boden der Maus (WCAG 2.2 «Target Size (Minimum)»); am
     Finger gilt weiter unten 44 (Zeile «.kf-tiefe-auf { min-width: 44px }»).
     Hier stand 22 — zwei Pixel unter dem Boden, gemessen am 25.08.2026 vom
     Breiten-Waechter auf allen fuenf Tisch-Breiten. */
  min-width: 24px; min-height: 27px; padding: 0 6px;
  border: 1px solid var(--border); border-radius: var(--radius-button);
  color: var(--text-tertiary); background: transparent;
  font: inherit; font-size: 15px; line-height: 1; cursor: pointer;
}
.kf-tiefe-auf:hover { color: var(--accent-strong); border-color: var(--accent-line); }

/* ===========================================================================
   RUNDE 3 · B-1 — DAS WERKZEUG GEHÖRT IN DIE SZENE, NICHT ÜBER ALLES
   ===========================================================================
   BEFUND (Prüfblick 10.08.): über der Arbeit lagen ZWEI vollbreite Bänder —
   die Filterleiste («Legt an / Zählt je Standort / NUR / Grössen …», auf
   1280 px zweizeilig, drei Chip-Systeme in 110 px) und direkt darunter die
   Schrittleiste. Sie konkurrierten optisch, und keines davon war die Arbeit.

   Kein Griff der Filterleiste gilt «über allem»: jeder wirkt auf die AUSWAHL.
   Also steht die Leiste jetzt IN der Wo-Szene, über Karte und Liste. Die
   Szene wird dafür zur Spalte, ihre alte Zeile (Karte | Liste) bekommt einen
   eigenen Kasten. Alle bestehenden Regeln zu `.kf-wo__karte` und
   `.kf-wo__liste` sind Nachfahren-Regeln und gelten unverändert weiter.

   AM HANDY IST DAS DER EIGENTLICHE GEWINN: dort zog die Leiste der Schale in
   ein Blatt hinter «Einstellen» — also hinter einen Aufklapper, und genau
   davor stand der Owner am 09.08. («Suche eingrenzen? Welche Suche?»). Jetzt
   steht sie offen in der Szene und rollt mit ihr weg (`.kf-wo` scrollt dort
   als Ganzes), statt Dauer-Chrome zu sein. */
.kf-wo { flex-direction: column; }
.kf-wo__zeug {
  flex: 0 0 auto;
  display: flex; align-items: center; gap: 6px 14px;
  padding: 7px 14px;
  /* Kein abhebender Streifen (Owner «Widget», 2026-08-13): das Werkzeug lag auf
     var(--surface-1), einer eigenen (dunkleren) Fläche über dem Grund. Jetzt
     sitzt es auf demselben Grund wie Karte und Liste — vom Bild darunter trennt
     es nur die 1px-Rinne von `.kf-wo` (feine Linie, kein Kasten). */
  background: var(--bg);

  /* ===================================================================
     EINE ZEILE — AUF JEDER BREITE, NICHT NUR AM HANDY (25.08.2026)
     ===================================================================
     Der Absatz darunter («KEIN GRIFF BRICHT AUF ZWEI ZEILEN») steht seit dem
     10.08. hier und rechnete mit «rund 1250 px» Szenenbreite. AUF EINEM ECHTEN
     LAPTOP GIBT ES DIE NIE. Gemessen am 25.08. auf der echten Schale:

       Fenster   Wo-Szene   Werkzeugzeile   Karte darunter
       1280 px     504 px    176 px (4 Zeilen)     9 × 0 px
       1366 px     561 px    176 px (4 Zeilen)     9 × 0 px
       1440 px     606 px    176 px (4 Zeilen)     9 × 0 px
       1680 px     753 px     92 px (2 Zeilen)   110 × 64 px
       1920 px     962 px     92 px (2 Zeilen)   110 × 64 px

     Die Szene bekommt in der Höhe nur ~172 px. Bricht die Zeile auf vier
     Zeilen um, ist sie mit 176 px GRÖSSER als die ganze Szene — und
     `.kf-wo__flaeche` darunter, die alles trägt (Karte UND Standortliste),
     bleibt auf null. Auf einem MacBook Pro 14" konnte niemand einen Standort
     auf der Karte wählen: die Fläche war da, sie war nicht ausgeblendet, sie
     war NULL GROSS. Kein Wächter hat es je bemerkt, weil zwischen 391 und
     1399 px nie jemand gemessen hat (scripts/_jede_breite_test.mjs schliesst
     genau diese Lücke).

     Die Regel des Hauses für diese Zeile lautete von Anfang an «eine Zeile,
     nie umbrechen» — sie galt nur unter `(max-width: 1080px)`. Sie gilt ab
     jetzt überall: die Mechanik ist Zeichen für Zeichen dieselbe, die der
     Handy-Block vorher trug (nowrap, wischen, Blende, `contain`, Schnappen je
     Gruppe). Das ist keine neue Gestalt, sondern dieselbe Bauform an der
     Stelle, an der sie schon immer hingehörte.

     ⚠️ `overscroll-behavior-x: contain` ist Pflicht, nicht Kosmetik: diese
     Zeile liegt IM waagrecht schnappenden Zonen-Streifen (`.cp[data-spalten]
     .cp__werk`). Ohne sie reicht ein Wisch, der hier am Ende ankommt, den Rest
     an den Elternteil weiter und wirft die ganze Fläche in die nächste Zone. */
  flex-wrap: nowrap;
  overflow-x: auto;
  scrollbar-width: none;
  overscroll-behavior-x: contain;
  /* ⚠️ DAS SCHNAPPEN BLEIBT AM FINGER (Block «max-width: 1080px» weiter unten).
     Es ist für den WISCH gebaut: «nie mitten im Wort enden» (Owner-Befund 4).
     Am Tisch gibt es keinen Wisch — dort rollt man mit Rad oder Leiste, und
     ein Kasten, der danach von selbst weiterrückt, ist genau das «komische
     Verhalten», gegen das diese Fläche gebaut ist. Gemessen am 25.08.2026:
     mit Schnappen am Tisch meldete `scripts/_fundament_bilder.mjs` auf 1400 px
     prompt «VERDECKTER HANDGRIFF: «max. 3» unter SELECT» — das Schnappen
     schiebt den Knopf nach `scrollIntoView` wieder aus dem Bild, und die
     Messung sieht an seiner Stelle den Nachbarn. Der Waechter hatte recht:
     WER MIT DER MAUS DORTHIN ROLLT, DEM RUTSCHT ES EBENSO WEG. */
  scroll-padding-left: 14px;
  /* «DA GEHT ES WEITER» — und zwar sichtbar. Die Fahne der Schale hängt an
     IHREN Leisten (cockpit.js, `fahneAn`) und kennt diesen Kasten nicht. Ohne
     Blende endet die Zeile am rechten Rand mitten im Wort («ZÄHLT JE …») —
     genau die Sorte angeschnittener Kopf, die B-2 abschafft. Die Blende ist
     keine Vermutung: der Inhalt misst rund 1'250 px (am Handy) bis 1'370 px
     (am Tisch, mit «Legt an») und überläuft damit auf JEDER hier gemessenen
     Breite. Wo er es einmal nicht täte, blendet sie Grund auf Grund und ist
     unsichtbar. */
  -webkit-mask-image: linear-gradient(90deg, #000 calc(100% - 26px), transparent);
  mask-image: linear-gradient(90deg, #000 calc(100% - 26px), transparent);
}
.kf-wo__zeug::-webkit-scrollbar { display: none; }
.kf-wo__zeug > * { flex: 0 0 auto; }
/* KEIN GRIFF BRICHT AUF ZWEI ZEILEN.
   Im Band über allem hatte jeder Knopf die halbe Seitenbreite zur Verfügung;
   in der Szene sind es rund 1250 px, und dort brachen «Ganzes Netz» und
   «max. 1» mitten durch — ein zweizeiliger Knopf macht die ganze Zeile
   doppelt hoch, und diese Höhe fehlt der Karte darunter (im Bild gemessen:
   110 px statt 44). Ein Knopf, der nicht ganz in eine Zeile passt, wird
   schmaler beschriftet, nie umgebrochen. */
.kf-wo__zeug .kf-segment > button { white-space: nowrap; }
.kf-wo__zeug .kf-leiste__wort { letter-spacing: .03em; white-space: nowrap; }
.kf-wo__flaeche {
  display: flex; gap: 1px;
  flex: 1 1 auto; min-height: 0; min-width: 0;
  background: var(--border);

  /* ===================================================================
     DIESE FLÄCHE FÄLLT NIE MEHR AUF NULL (25.08.2026)
     ===================================================================
     `flex: 1 1 auto; min-height: 0` heisst wörtlich: «nimm den Rest — und
     wenn kein Rest da ist, verschwinde». Genau das ist am 25.08. gemessen
     worden: 504 × 0, 561 × 0, 606 × 0 px. Ein Kasten, der Karte UND
     Standortliste trägt, darf das nie. Der Boden ist kein geratenes Mass: die
     Karte zeichnet nach viewBox 1000 × 640 und füllt ihren Kasten mit
     `aspect-ratio` — die Höhe bestimmt die Breite, und weil der Kasten dem
     Bild folgt, ist die Karte bei JEDER Höhe GANZ zu sehen (keine Balken, kein
     abgeschnittenes Tessin).

     DER BODEN IST EIN NETZ, KEIN MASS. Er ist bewusst KLEIN gewählt: sobald
     die Werkzeugzeile nicht mehr umbricht (oben), bekommt diese Fläche im
     normalen Lauf den ganzen Rest der Szene und steht weit über dem Boden
     (gemessen 25.08. nach der Behebung: 118 px auf 1280×700, 175 px auf
     1920×970 — Karte 184 × 118 bzw. 273 × 175). Der Boden greift nur dort, wo
     sonst wieder eine Null stünde. Ein GROSSER Boden wäre der falsche Griff:
     er würde die Szene zum Rollen zwingen und die Karte mitten in der Schweiz
     abschneiden — am Bild geprüft (1440×790, Boden 160 px: 42 px Rollweg, das
     halbe Wallis unter der Kante). Lieber eine kleinere Karte, die GANZ da
     ist, als eine grössere, von der ein Stück fehlt.

     Die Karte bleibt auf Laptops kleiner, als die Referenz sie zeigt. Die
     Ursache liegt NICHT hier: über der Schale stehen 176 px Kopfzone
     (`--cp-oben`) plus 40 px Luft plus 32 px unten — 248 px von 790. Das ist
     die Schale, nicht der Rechner; es steht als Befund im Rapport zum
     Breiten-Wächter. */
  min-height: 96px;
}
/* DAS LETZTE NETZ: reicht die Höhe trotz allem nicht, wird GEROLLT statt
   gequetscht. Ohne diese Zeile schnitte `.cp__werk` (`overflow: hidden`, mit
   Grund) den Rest einfach ab — und genau ein solcher Schnitt hat die Karte am
   25.08. unsichtbar gemacht, ohne dass irgendetwas es meldete. */
.kf-wo { overflow-y: auto; scrollbar-width: thin; overscroll-behavior-y: contain; }
@media (max-width: 1080px), (pointer: coarse) {
  /* AM HANDY EINE ZEILE, NICHT VIER.
     Gemessen: umbrechend belegt das Werkzeug auf 390 px vier Zeilen à ~44 px
     — die Karte stünde damit erst bei y≈230 und ihre Mitte unter der Kante
     (der Wisch-Beweis der Ketten-Probe griff prompt ins Leere). Es wird
     deshalb gewischt, nie umgebrochen: dieselbe Mechanik, die die Schale für
     ihre Bereichsleiste und ihre Leiste seit jeher fährt, mit derselben
     «da liegt noch was»-Fahne. 44 px statt 176.

     ⚠️ 25.08.2026: DIE MECHANIK STEHT NICHT MEHR HIER, sondern in der
     Grundregel von `.kf-wo__zeug` weiter oben — sie gilt seither auf JEDER
     Breite, weil die Zeile auch in einer 504-px-Laptopspalte auf vier Zeilen
     umbrach und die Karte dort auf 9 × 0 px drückte. Zwei Fassungen derselben
     Regel wären die nächste Drift; hier bleibt nur, was am Handy WIRKLICH
     anders ist: der engere Innenabstand und die Reihenfolge der Teile. */
  /* DAS SCHNAPPEN JE GRUPPE — nur hier, weil es dem Wisch gilt: ohne es endet
     die Zeile nach jedem Wisch an einer zufaelligen Pixelkante, mitten in
     «Zaehlt je Stan…». «Nie mitten im Wort enden» ist das Hausgesetz dieser
     Zeile (Owner-Befund 4); es galt bisher nur fuer ihren rechten Rand (die
     Blende), nicht fuer ihren Ruhepunkt. `proximity`, nicht `mandatory`: ein
     erzwungenes Einrasten machte kurze Korrekturwischer unmoeglich. */
  .kf-wo__zeug {
    padding: 7px 12px;
    scroll-padding-left: 12px;
    scroll-snap-type: x proximity;
  }
  .kf-wo__zeug > * { scroll-snap-align: start; }
  /* Am Handy trägt die Fläche keine Karte mehr (`kf-wo--galerie`), und die
     Teile ordnen sich in EINER Spalte — dort ist ein Boden für den
     Zwischenkasten sinnlos, weil es ihn gar nicht gibt (`display: contents`
     weiter unten). */
  .kf-wo__flaeche { min-height: 0; }

  /* UND ES STEHT UNTER DER KARTE, NICHT ÜBER IHR.
     Im Bild geprüft, 390×620: über der Karte kostete das Werkzeug 64 px an der
     teuersten Stelle der Fläche — die Karte begann erst bei y≈220, das
     Suchfeld war halb angeschnitten, und von der Standortliste stand keine
     Zeile mehr im Bild. Am Rechner ist «zuerst das Werkzeug, dann die Fläche»
     richtig (beides steht ohnehin gleichzeitig da); am Handy wird gerollt,
     und dann gilt die Reihenfolge des Blicks: erst das Bild, auf das man
     tippt, dann die Regler dazu, dann die Liste.
     `display: contents` löst den Zwischen-Kasten auf, damit sich Karte,
     Legende, Werkzeug und Liste in EINER Spalte ordnen lassen; alle
     bestehenden Regeln zu `.kf-wo__karte` und `.kf-wo__liste` sind
     Nachfahren-Regeln und gelten unverändert weiter. */
  .kf-wo__flaeche { display: contents; }
  .kf-wo__karte { order: 1; }
  .kf-karte__legende { order: 2; }
  .kf-wo__zeug { order: 3; }
  .kf-wo__liste { order: 4; }

  /* OHNE KARTE KEHRT SICH DIE REIHENFOLGE UM (Owner 25.08.2026).
     Die Regel darüber lautet: «erst das Bild, auf das man tippt, dann die
     Regler dazu, dann die Liste». Seit die Karte am Handy abtritt, IST die
     Galerie das, worauf man tippt — und sie steht in der Liste. Bliebe das
     Werkzeug auf `order: 3`, wäre das Erste auf dem Schirm eine Reihe Regler
     («Zählt je Standort · Nur …») über einer Fläche, auf der noch gar nichts
     gewählt ist: 44 px an der teuersten Stelle, für eine Verfeinerung, die
     ohne Auswahl nichts verfeinert. Am Bild gesehen, 25.08. — der erste
     Eindruck der Fläche war die abgeschnittene Zeile «ZÄHLT JE STANDORT».
     Jetzt gilt dieselbe Regel mit dem neuen Bild: Galerie, dann Regler. */
  .kf-wo--galerie .kf-wo__zeug { order: 5; }
}

/* ===========================================================================
   RUNDE 3 · B-2 — KEIN KOPF OHNE INHALT
   ===========================================================================
   BEFUND (Prüfblick 10.08.): in der Ausgabe stand der Positions-Tabellenkopf
   ohne eine einzige Zeile im Bild, und auf 1280 px zeigten die
   Zusammenfassungs-Chips nur ihre Köpfe. Beides ist derselbe Fehler: die
   Ausgabe ist ein Rollkasten mit fester Höhe, und sie schneidet dort, wo die
   Kante zufällig fällt.

   Zwei Regeln, die das mechanisch beenden:
   (1) Der Kasten rastet auf Blockanfänge ein. Nach jedem Rollen beginnt oben
       ein ganzer Block — nie sein Rest, nie sein Kopf allein. `proximity`
       statt `mandatory`: ein erzwungenes Einrasten würde langes Rollen in
       der Positionsliste gegen den Finger arbeiten.
   (2) Der Tabellenkopf der Positionen klebt an seiner Tabelle. Er ist die
       Beschriftung von sechs Spalten; ohne eine Zeile darunter beschriftet
       er nichts. `sticky` im Rollkasten hält ihn bei seinen Zeilen, egal wo
       gerollt wird.
   Die dritte Ursache — der Alarmkasten frass ein Viertel der Ausgabe — ist
   im Markup behoben (`leitplankenKopfHtml`: zwei Zeilen wurden eine). */
/* Seit 02.09.2026 ist die Ausgabe das Blatt «Prüfen» — dieselben zwei Regeln
   am Blatt statt an einem Rollkasten unter dem Werk. */
.cp__blatt:has(> .kf-ausgabe) { scroll-snap-type: y proximity; }
.cp__blatt > .kf-ausgabe .kf-block { scroll-snap-align: start; }
/* Der Blatt-Kopf ist selbst ein Fangpunkt — sonst zieht der Fang beim Öffnen
   des Blatts den ersten Block nach oben und der Kopf steht ausserhalb (gesehen
   02.09. am 1440-Bild: «Zusammenfassung» oben, die Frage weg). */
.cp__blatt > .kf-ausgabe .kf-blattkopf { scroll-snap-align: start; scroll-margin-top: 18px; }
/* `scroll-margin-top` = Blatt-Rand oben: der Fangpunkt liegt bei scrollTop 0,
   nicht 18 px tiefer — sonst klebt der Kopf ohne Luft unter dem Band. */
.kf-pos-kopf {
  position: sticky; top: 0; z-index: 2;
  background: var(--surface);
}
/* Der Nachsatz des Alarms steht in derselben Zeile hinter der Zahl, nicht
   darunter: dieselbe Aussage, ein Drittel der Höhe. Auf sehr schmalen
   Schirmen bricht er um — dort ist Höhe billiger als eine abgeschnittene
   Zeile. */
.kf-warn__nach {
  margin-left: 8px;
  font-size: 11.5px; font-weight: 500;
  color: var(--text-tertiary);
}

/* ===========================================================================
   RUNDE 3 · B-3 — DIE MELDUNG LEGT SICH NICHT AUF DIE LEISTEN
   ===========================================================================
   BEFUND (Prüfblick 10.08., 390 px): der Toast «Preise aktualisiert …» lag
   über dem Statusband UND über der Bereichsleiste. Beide waren weder zu lesen
   noch zu treffen.

   `.toast-stack` rechnet seinen Boden aus `20 + Bodenabstand + Fusshöhe` —
   richtig für jede Fläche des Hauses. Nur trägt DIESE unter dem Werk noch
   zwei feste Zeilen, die es sonst nirgends gibt. Ihre Höhe misst der
   Konfigurator selbst und schreibt sie als `--kf-unterbau` an den Body
   (`meldeUnterbau()`, in `destroy()` wieder abgeräumt) — gemessen statt
   geraten, und `toast.js` bleibt unberührt: es ist die Meldung des ganzen
   Hauses, nicht die dieser Fläche. */
body:has(.cp .kf-wo) .toast-stack {
  bottom: calc(20px + var(--boden-abstand) + var(--fuss-h)
    + var(--vv-unten, 0px) + var(--kf-unterbau, 0px));
}

/* ---- W10-4 · Suchfeld über der Kundenliste ------------------------------ */
.kf-kundewahl > input[type="search"] { margin-bottom: 5px; }

@media (max-width: 1080px), (pointer: coarse) {
  /* Trefffläche: derselbe Boden wie für jeden anderen Griff dieser Fläche. */
  .kf-tiefe-auf, .kf-sammeln, .kf-pfad__weg > button { min-height: 44px; }
  .kf-tiefe-auf { min-width: 44px; }
}

/* ---- Seitenzonen: nur noch das Kundenportal trägt sie (02.09.2026) -------
   Der Offerten-Weg hat seit 02.09. keine Zonen «links/rechts» mehr — fünf
   Blätter statt drei Spalten. Diese drei Regeln standen bis dahin für seine
   Seitenspalten und wirkten ungescopt auch im Kundenportal (`links: Deine
   Auswahl`, `rechts: Zeitraum & Plätze`, kunde-portal.js:3603/3624). Sie
   bleiben wortgleich, damit das Portal Pixel für Pixel steht («Kundenportal
   bleibt, wie es ist»). Wer sie hier entfernt, ändert das Portal. */
.cp__zone--links .cp__zoneleib,
.cp__zone--rechts .cp__zoneleib { padding: 9px 13px; }
.cp__zone--links .cp__zoneleib { padding: 9px 13px; display: flex; flex-direction: column; }
.cp__zone--links .cp__zoneleib > * { flex: 0 0 auto; }

/* ===========================================================================
   EARLY BIRD — SICHTBAR FÜR JEDEN, SCHALTBAR NUR FÜR EINEN (Owner 26.08.2026)
   ===========================================================================
   «der muss bei jedem sichtbar sein damit man dem kunden zeigen kann es sind
   50% bei der berechnung aber nur ich kann ihn ein und aus schalten».

   Der gesperrte Schalter darf nicht wie ein Fehler aussehen: die ZAHL bleibt
   voll lesbar (sie ist das Verkaufsargument), nur der Kasten selbst ist matt.
   Ein durchgängig ausgegrautes Element hätte genau das versteckt, worum der
   Owner gebeten hat. Diese Regeln gelten auf JEDER Breite — der Satz gilt am
   Telefon wie am Rechner. */
.kf-schalter--eb .kf-schalter__wert {
  font-weight: 650; color: var(--accent-strong); white-space: nowrap;
}
.kf-schalter--eb:has(input:disabled) { opacity: 1; cursor: default; }
.kf-schalter--eb:has(input:disabled) > span { color: var(--text-secondary); }
.kf-schalter--eb input:disabled { cursor: not-allowed; }
.kf-hint--eb { margin: 2px 0 0; font-size: 11.5px; line-height: 1.35; }

/* ===========================================================================
   Patch-Integration — Namensraum kf-; Quelle: docs/design/patch-konfigurator-blaetter.css
   Steht direkt nach patch-konfigurator-w10.css: dieselbe Kaskade wie bis 02.09., als der Block dort stand.
   =========================================================================== */
/* ===========================================================================
   FÜNF BLÄTTER — Band · Auftrag · Standorte (Karte + Galerie + Korb-Streifen)
   · Ausspielung · Spot · Prüfen (Owner 02.09.2026)
   ===========================================================================
   Eigenes Blatt, direkt nach patch-konfigurator-w10.css in der Kaskade —
   dieselbe Reihenfolge wie am 02.09., als dieser Block noch in w10 stand.
   Warum ein eigenes Blatt: der Stil-Wächter (`_stil_einmalig_test.mjs`,
   Prüfung 3) zählt in den Blättern seiner Erhebung jede Grundregel samt
   ihrer Handy-Fassung als Doppelung; 23 solche Paare kamen mit den fünf
   Blättern — die richtige Bauweise (§10a.3), aber im falschen Blatt. Das Tor
   hielt an (Anlauf 2 für v391), zu Recht. Ein neues Blatt bewachen Prüfung
   1 und 2 (kein Selektor in zwei Blättern).

   Bildreferenz: `docs/design/referenzen/konfigurator-greenfield-2026-08-10/`
   — der Massstab für Luft, Ordnung und erkennbare Unterschiede, NIE die
   Vorlage zum Abpausen (Owner 02.09.: «wir haben viel mehr Logik, Tiefe,
   Verknüpfung»). Farbwelt: `docs/design/EINHEIT.md §1.3`.
   =========================================================================== */

/* ---- Das Band: fünf Blätter, klickbar (Owner 02.09.2026) ------------------
   Es steht im `schritte`-Schlitz der Schale zwischen Kopf und Werk, unter der
   Weg-Leiste. Bis 02.09. war es ein reines Zustandsband («kein Knopfband»,
   Runde 3): auf einer Fläche mit vier Zonen nebeneinander hatte ein Klick
   nichts zu tun. Seit die Fläche fünf Blätter trägt, IST es die Navigation —
   `data-cp-ansicht`, delegiert von cockpit.js, `aria-selected` von der Schale
   nachgeführt. Die eigene Reiterzeile der Schale ist dafür verborgen (Block
   «FÜNF BLÄTTER» weiter unten).

   EINHEIT §5.3: nummerierte Kreise MIT Namen, waagerecht, dünne Trennung.
   Keine Balkensegmente, keine Chevron-Trenner.

   `flex: 0 0 auto` ist Pflicht: `.cp` ist eine Flex-Spalte, und ohne diese
   Zeile würde das Band vom Werk zusammengedrückt. */
.kf-schritte {
  flex: 0 0 auto;
  /* `.cp` ist eine Flex-Spalte mit `align-items: center` — ohne diese zwei
     Zeilen bekäme das Band die Breite seines INHALTS statt der Fläche. */
  align-self: stretch;
  width: 100%;
  border-bottom: 1px solid var(--border);
  background: var(--surface-1);
}
.kf-schritte > ol {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 1px;
  margin: 0; padding: 0;
  list-style: none;
  background: var(--border);          /* die Haarlinien zwischen den Schritten */
}
.kf-schritte > ol > li { display: grid; min-width: 0; }

.kf-schritt {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: center;
  gap: 10px;
  width: 100%;
  min-height: 54px;
  padding: 8px 18px;
  border: 0;
  border-bottom: 2px solid transparent;
  text-align: left;
  font: inherit;
  color: var(--text-secondary);
  background: var(--surface-1);
  cursor: pointer;
  transition: background var(--dur-fast, 120ms), border-color var(--dur-fast, 120ms);
}
.kf-schritt:hover { background: var(--surface); }
.kf-schritt:hover .kf-schritt__wer strong { color: var(--accent-strong); }
.kf-schritt:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

/* Drei Formen, drei Zustände (EINHEIT §4.5) — nie eine Doppelbelegung:
   Umriss-Kreis mit Nummer = kommt noch · gefüllter Kreis mit Nummer = hier
   bist du · gefüllter Kreis mit Häkchen = erledigt. */
.kf-schritt__nr {
  display: grid; place-items: center;
  width: 28px; height: 28px;
  border: 1px solid var(--border);
  border-radius: 50%;
  font-size: 12px; font-weight: 650;
  font-variant-numeric: tabular-nums;
  color: var(--text-tertiary);
  background: transparent;
}
.kf-schritt__nr svg { width: 13px; height: 13px; }
.kf-schritt__wer { display: grid; gap: 1px; min-width: 0; }
.kf-schritt__wer strong {
  font-size: 13px; font-weight: 650; letter-spacing: .01em;
  color: var(--text-secondary);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.kf-schritt__wer small {
  font-size: 11px; line-height: 1.3;
  color: var(--text-tertiary);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.kf-schritt.is-fertig .kf-schritt__nr {
  border-color: transparent;
  color: var(--on-accent);
  background: var(--accent);
}
.kf-schritt.is-fertig .kf-schritt__wer strong { color: var(--text-primary); }
/* «Hier bist du»: die Zelle blau getönt (gemessen #0c151e, Bild 02) und
   unter ihr ein heller Lichtstreif statt einer harten Linie. */
.kf-schritt[aria-selected="true"] {
  border-bottom-color: transparent;
  background: linear-gradient(180deg, rgba(var(--accent-tint-rgb), .10), rgba(var(--accent-tint-rgb), .16));
  box-shadow: inset 0 -2px 0 0 rgba(var(--accent-rgb), .55);
}
.kf-schritt[aria-selected="true"] .kf-schritt__nr {
  border-color: transparent;
  color: var(--on-accent);
  background: var(--accent);
}
.kf-schritt[aria-selected="true"] .kf-schritt__wer strong { color: var(--accent-strong); }

/* Was fehlt, wird beim Namen genannt — und sieht auch danach aus. Dieselbe
   Warnstufe wie `.kf-warn`. */
.kf-schritt.has-luecke .kf-schritt__wer small { color: var(--warn-strong); }
.kf-schritt.has-luecke[aria-selected="true"] { border-bottom-color: var(--warn-strong); }

/* AM HANDY GEHT DAS BAND AN DEN DAUMEN, NICHT AN DEN KOPF.
   Über dem ersten Inhalt stehen höchstens 72 px (Anatomie dieser Fläche,
   08.08.); das Band zieht deshalb ans untere Ende, direkt über den Sockel
   (`order: 7` vor dem Fuss `order: 9`) — wo die Hand ohnehin liegt. Es ist
   dort die EINE Navigation: der offene Schritt steht ausgeschrieben da (Name
   + Lücke), die vier anderen sind ihre Ziffer — Häkchen für erledigt, Nummer
   für kommt noch; der Name bleibt als `aria-label` am Knopf. */
@media (max-width: 1080px), (pointer: coarse) {
  .kf-schritte {
    order: 7;
    border-top: 1px solid var(--border);
    border-bottom: 0;
  }
  .kf-schritte > ol {
    display: flex;
    gap: 0;
    background: transparent;
  }
  .kf-schritte > ol > li { flex: 0 0 auto; }
  .kf-schritte > ol > li:has(> [aria-selected="true"]) { flex: 1 1 auto; min-width: 0; }
  .kf-schritt {
    min-height: 48px;
    padding: 4px 10px;
    border-bottom: 0;
    border-left: 1px solid var(--border);
    background: transparent;
  }
  .kf-schritte > ol > li:first-child .kf-schritt { border-left: 0; }
  .kf-schritt:not([aria-selected="true"]) { grid-template-columns: auto; padding: 4px 9px; }
  .kf-schritt:not([aria-selected="true"]) .kf-schritt__wer { display: none; }
  .kf-schritt[aria-selected="true"] { background: var(--accent-soft); }
}

/* ===========================================================================
   FÜNF BLÄTTER (Owner 02.09.2026) — Auftrag · Standorte · Ausspielung · Spot · Prüfen
   ===========================================================================
   Bis 02.09. standen drei Zonen und eine Ausgabe gleichzeitig da; auf 1440 px
   mass die Karte 204×130 px, die Werkzeugzeile brach ab, und die Ausgabe war
   grösser als die Arbeit, auf der sie beruht. Jetzt trägt jedes Blatt die
   ganze Breite. Die Reiterzeile der Schale ist verborgen — das Band oben ist
   die Navigation (`.kf-schritte`: Nummer, Häkchen, Lücke). Die Blätter selbst
   scrollen innen (`.cp__blatt`, patch-konfigurator.css). Die Regeln zu
   `.cp__zone--links/--rechts`, die hier standen, sind mit den Zonen gefallen. */
.cp:has(.kf-schritte) .cp__buehnekopf { display: none; }
.cp:has(.kf-schritte) .cp__blatt { padding: 18px 24px 24px; }
/* Das Standort-Blatt trägt die Karte randnah: Luft nur oben und seitlich. */
.cp:has(.kf-schritte) .cp__blatt:has(> .kf-wo) { padding: 12px 18px 0; }

/* Der Blatt-Kopf (Owner 02.09. nachts): «01 · Auftrag», die eine Frage des
   Blatts, rechts der Stand — Erledigt, Startklar oder «Offen: …». Er ist ein
   Kopf über der Arbeit, kein Panel: keine Kante, nur Luft darunter. In der
   Ausgabe (Grid) nimmt er die ganze Breite (`grid-column`). */
.kf-blattkopf {
  display: grid; grid-template-columns: minmax(0, 1fr) auto;
  grid-column: 1 / -1;
  align-items: center; gap: 4px 16px;
  margin: 0 0 20px; padding: 18px 22px;
  border: 1px solid var(--border); border-radius: var(--radius-card);
  background: var(--work-heading-background);   /* gemessen Bild 02 */
}
.kf-blattkopf > .kf-kopf { grid-column: 1; margin: 0; letter-spacing: .16em; color: #7691aa; }
/* Die Frage ist gross und dünn (Referenz 40 px / 400) — kein fetter Titel. */
.kf-blattkopf__frage {
  grid-column: 1; margin: 0;
  font-size: 30px; font-weight: 400; letter-spacing: -.01em; line-height: 1.2;
  color: var(--text-primary); text-wrap: balance;
}
.kf-blattkopf__stand {
  grid-column: 2; grid-row: 1 / span 2; align-self: center;
  max-width: 44vw; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Über der Karte ist der Kopf EINE Zeile: Nummer · Wort, Frage, Stand — die
   Karte bezieht ihre Breite aus der Höhe des Blatts, jede Zeile mehr macht
   sie schmaler (Ratsche 640 px auf 1440, `_offerte_handy_test` G). */
/* ENG HEISST FLACH: die Szene (Karte, Positionen) bekommt die Hoehe. A/B gegen
   v393 auf der Probe-Seite (03.09., `ab-probe.mjs`): der gerahmte Kopf kostete
   14–18 px und schob alles darunter — die Karte auf 1440 verlor 28 px Breite
   (Ratsche G), der Positionskopf stand auf 1280×800 ohne Zeile im Bild (B-2:
   460 → 482 px), am Handy rueckte die Summe ueber 1,4 Fensterhoehen (D2).
   Der Rahmen gehoert den grossen Koepfen (Auftrag, Ausspielung, Spot); hier
   traegt die Zeile nur Etikett, Frage und Stand — dieselbe Hoehe wie v393. */
.kf-blattkopf--eng {
  display: flex; align-items: baseline; flex-wrap: wrap; gap: 0 14px;
  margin: 0; padding: 0; border: 0; border-radius: 0; background: transparent;
}
.kf-blattkopf--eng .kf-blattkopf__frage { font-size: 18px; }
.kf-blattkopf--eng .kf-blattkopf__stand { align-self: center; }

/* Auftrag (Kunde | Wozu | Im Korb) und Ausspielung (Umfang | Zeitraum |
   Werbeplätze): drei ruhige Flächen nebeneinander — je eine Frage, Luft
   darin, kein Rahmen (DESIGN.md: Panels borderlos, Fläche trennt, nicht
   Linie). Bis 02.09. waren es Haarlinien-Spalten mit 80 % Leere darunter. */
.kf-auftrag, .kf-ausspielung {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 20px; align-items: stretch;
}
.kf-auftrag__spalte, .kf-ausspielung__spalte {
  min-width: 0; padding: 18px 20px 20px;
  border: 1px solid var(--border); border-radius: var(--radius-card); background: var(--surface-1);
}
.kf-auftrag .kf-kopf, .kf-ausspielung .kf-kopf, .kf-spot > .kf-kopf { margin: 0 0 10px; }
/* Das Korb-Fach rollt in seinem eigenen Kasten, wie die Standortliste — ab
   dem ersten Stück ganz im Bild, ab dem zwölften rollt es. */
.kf-auftrag__spalte--korb .kf-korbfach { max-height: 48vh; overflow-y: auto; }
/* Der Leerzustand des Korbs zeigt seine zwei Wege auf jeder Breite — sie
   öffnen das Blatt «Standorte». Linksbündig wie die Spalte. */
/* Der leere Korb trägt den Haus-Leerzustand, wie er ist — keine linksbündige
   Sonderfassung (Muster-Wächter «Kein Blatt kleidet den Haus-Leerzustand neu
   ein», Tor-Halt 02.09.). */
/* Die Zählregel («Zählt je Standort») in der Umfang-Spalte: Wort über Wahl,
   nicht mehr in einer Zeile mit dem Kartenwerkzeug. */
.kf-ausspielung .kf-leiste__gruppe { display: grid; gap: 6px; margin-bottom: 12px; }
.kf-ausspielung .kf-leiste__wort {
  font-size: 11.5px; font-weight: 600; letter-spacing: .02em; color: var(--text-secondary);
}
.kf-ausspielung .kf-schalter.kf-leiste__gruppe { display: flex; align-items: center; gap: 8px; }

/* Spot: drei Karten, eine Wahl (Referenz Szene 4). Eine Wahlkarte ist ein
   Bedienelement, kein Panel — deshalb trägt sie die eine begründete Kante.
   Der Knopf trägt keine eigene Klasse: er ist dieselbe Haus-Form wie der
   Wozu-Knopf («BUTTON ohne Klasse», Muster-Grundlinie) — der Muster-Wächter
   hielt das Tor am 02.09. an, weil `kf-wahlkarte` eine 110. Form gewesen
   wäre. Das Aussehen hängt am Behälter. */
.kf-spot__wege { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 16px; }
.kf-spot__wege > button {
  position: relative;
  display: grid; gap: 6px; align-content: start;
  min-height: 112px; padding: 18px 44px 18px 20px;
  border: 1px solid var(--border); border-radius: var(--radius-card);
  background: var(--surface); color: inherit;
  text-align: left; font: inherit; cursor: pointer;
  transition: border-color var(--dur-fast, 120ms), background var(--dur-fast, 120ms);
}
.kf-spot__wege > button:hover { border-color: var(--accent-line); }
.kf-spot__wege > button:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.kf-spot__wege > button strong { font-size: 15px; font-weight: 650; color: var(--text-primary); }
.kf-spot__wege > button small { font-size: 12.5px; line-height: 1.45; color: var(--text-secondary); }
.kf-spot__wege > button[aria-pressed="true"] {
  border-color: var(--accent); background: var(--accent-soft);
  box-shadow: inset 0 0 0 1px var(--accent);
}
.kf-spot__wege > button[aria-pressed="true"] strong { color: var(--accent-strong); }
/* Das Häkchen der gewählten Karte, aus zwei Kanten gezeichnet — kein Bild,
   kein Zeichen aus der Schrift (Referenz Szene 4: Häkchen oben rechts). */
.kf-spot__wege > button[aria-pressed="true"]::before {
  content: ''; position: absolute; top: 14px; right: 14px;
  width: 20px; height: 20px; border-radius: 50%; background: var(--accent);
}
.kf-spot__wege > button[aria-pressed="true"]::after {
  content: ''; position: absolute; top: 18px; right: 21px;
  width: 5px; height: 9px;
  border: solid var(--on-accent); border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}
.kf-spot__wege > button:disabled { opacity: .55; cursor: default; }

/* Standorte: Kopf mit dem Umschalter der Sichten (KARTE | GEBIETE | AUSWAHL N
   | GROSS, Referenz Szene 2). Karte links, Tafel rechts; «Gross» ist die
   Karte allein. Die Breiten sind Deckel — die Höhe des Blatts bestimmt über
   `aspect-ratio` die Karte (patch-konfigurator.css `.kf-wo__karte`). */
.kf-wo__kopf {
  flex: 0 0 auto;
  display: flex; align-items: center; justify-content: space-between;
  flex-wrap: wrap; gap: 8px 20px;
  padding: 0 0 4px;
}
.kf-wo__titel { display: flex; align-items: baseline; flex-wrap: wrap; gap: 4px 12px; min-width: 0; }
.kf-wo__titel .kf-kopf, .kf-wo__titel .kf-hint { margin: 0; }
.kf-wo__sicht { flex: 0 0 auto; }
.kf-wo__sicht > button { white-space: nowrap; padding: 0 14px; }
.kf-wo--gebiete .kf-wo__karte, .kf-wo--auswahl .kf-wo__karte { max-width: 52%; }
.kf-wo--gross .kf-wo__karte { max-width: none; flex: 1 1 auto; }

/* Der Korb-Streifen auf jeder Breite (bis 02.09. nur am Handy): was gewählt
   ist, mit ✕ je Stück und «Alles zurücksetzen». Die Handy-Fassung darunter
   (klebend, 44-px-Griffe) bleibt und überschreibt nur, was dort anders ist. */
.kf-strf { flex: 0 0 auto; margin: 0 0 6px; padding: 2px 0 7px; border-bottom: 1px solid var(--border-subtle); }
.kf-strf__kopf {
  display: flex; align-items: center; justify-content: space-between;
  gap: 8px; min-height: 24px;
}
.kf-strf__zahl {
  min-width: 0; font-size: 12.5px; font-weight: 650; color: var(--text-secondary);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.kf-strf__alles {
  flex: 0 0 auto; min-height: 28px; padding: 0 10px;
  border: 1px solid var(--border); border-radius: var(--radius-pill);
  background: var(--surface); color: var(--text-secondary);
  font: inherit; font-size: 12px; font-weight: 650; cursor: pointer;
}
.kf-strf__alles:hover { color: var(--text-primary); border-color: var(--text-tertiary); }
.kf-strf__alles:disabled { opacity: .5; cursor: default; }
.kf-strf__reihe { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }
.kf-strf__stueck {
  display: inline-grid; grid-template-columns: minmax(0, 1fr) auto;
  align-items: center; gap: 2px;
  max-width: 320px; min-height: 32px; padding: 2px 2px 2px 10px;
  border: 1px solid var(--border); border-radius: var(--radius-pill);
  background: var(--surface-2);
}
/* Ausgeschlossen: gestrichelt und ohne Fläche — sichtbar «nicht dabei». */
.kf-strf__stueck--ab { border-style: dashed; background: transparent; }
.kf-strf__wer { min-width: 0; }
.kf-strf__wer b {
  display: block; font-size: 12.5px; font-weight: 650; color: var(--text-primary);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.kf-strf__wer small {
  display: block; font-size: 11px; color: var(--text-tertiary);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.kf-strf__stueck button {
  flex: 0 0 auto; width: 28px; height: 28px; min-width: 28px;
  display: grid; place-items: center;
  border: 0; border-radius: 50%;
  background: transparent; color: var(--text-secondary);
  font-size: 14px; line-height: 1; cursor: pointer;
}
.kf-strf__stueck button:hover { background: var(--surface); color: var(--text-primary); }
.kf-strf__stueck button:disabled { opacity: .45; cursor: default; }

@media (max-width: 1080px), (pointer: coarse) {
  .cp:has(.kf-schritte) .cp__blatt { padding: 12px 14px 20px; }
  .cp:has(.kf-schritte) .cp__blatt:has(> .kf-wo) { padding: 8px 12px 0; }
  .kf-auftrag, .kf-ausspielung { grid-template-columns: 1fr; gap: 12px; }
  .kf-auftrag__spalte, .kf-ausspielung__spalte { padding: 16px; }
  /* Am Handy nennt das Band am Daumen Nummer und Wort — der Kopf trägt nur
     die Frage und den Stand, untereinander, in einer Zeile je. Sonst frisst
     er den Rollweg zum Preis (`_offerte_handy_test` D2: < 1,4 Fensterhöhen). */
  .cp__blatt .kf-blattkopf { grid-template-columns: minmax(0, 1fr); gap: 4px; margin: 0 0 12px; }
  .cp__blatt .kf-blattkopf > .kf-kopf { display: none; }
  /* Am Handy sagt das Band unter dem Blatt schon «Offen: Kunde», und «Prüfen»
     hat den Block «Was gilt, was offen ist». Ein dritter Ort für denselben
     Stand kostete 22 px je Kopf (A/B gegen v393: 51 → 73 px) und schob die
     Summe über 1,4 Fensterhöhen hinaus (Probe D2). Der Kopf trägt hier nur
     die Frage. */
  .cp__blatt .kf-blattkopf__stand { display: none; }
  .cp__blatt .kf-blattkopf__frage { font-size: 18px; }
  .cp__blatt .kf-blattkopf__stand { grid-column: 1; grid-row: auto; justify-self: start; max-width: 100%; }
  /* Auch der enge Kopf (Standorte, Prüfen) stapelt am Handy: Frage und Stand
     in EINER Zeile sprengen 366 px um ein paar Pixel, das Blatt bekommt einen
     Querscroll, und der Wisch der Werkzeugzeile landet dort statt im Deck
     (`_offerte_handy_test` E4, 02.09.). */
  .cp__blatt .kf-blattkopf--eng { display: grid; }
  .kf-auftrag__spalte--korb .kf-korbfach { max-height: none; overflow: visible; }
  .kf-spot__wege { grid-template-columns: 1fr; }
  .kf-spot__wege > button { min-height: 64px; }
  .kf-wo__kopf { padding-bottom: 6px; }
  .kf-wo__sicht { width: 100%; }
  .kf-wo__sicht > button { flex: 1 1 0; min-height: 44px; }
}

/* W10-2 («der Briefkastenschlitz», 10.08.) IST MIT DER AUSGABE GEFALLEN
   (02.09.2026). Hier stand die Höhen-Buchführung zwischen Werk und Ausgabe
   (`min-height: min(260px, calc(100% - 226px))`, Deckel 34svh, der
   zurückgenommene Versuch vom 25.08.). Es gibt keine Ausgabe mehr, die mit dem
   Werk um die Höhe streitet: das Ergebnis ist das Blatt «Prüfen», und das
   offene Blatt bekommt den ganzen Rest der Schale. Rückweg: git, Commit vor
   dem 02.09. */

/* ===========================================================================
   DIE GALERIE — Ganze Schweiz · Kantone · Regionen (Owner 25.08. / 02.09.2026)
   ===========================================================================
   OWNER-WORTLAUT am eigenen Gerät (25.08.): «auf dem Handy müsste die Karte
   entfernt werden und eine Galerie, die ganze Schweiz» — und am 02.09. für
   den Rechner: «entweder eine Karte auswählen oder man kann eine Galerie
   öffnen. Dann kommt die Galerie mit Kanton, ganzen Netzwerken und so weiter,
   oder Ort oder einzelne». Seither zeichnet die Sicht «Gebiete» sie auf jeder
   Breite; am Handy ist sie die erste Sicht (die Karte gibt es dort nicht:
   Basel-Stadt misst im SVG 12 × 10 px, der Haus-Boden ist 44).

   Die Bauform ist die der Ortsliste (Name · Zahl · «›» · «+»), damit Kanton,
   Ort und Standort dieselbe Zeile sind — eine Bauart, drei Stufen.
   =========================================================================== */
.kf-gal { display: block; padding: 2px 0 4px; }

/* DIE GANZE SCHWEIZ IST EIN GRIFF — die grösste Trefffläche der Stufe, weil
   sie die häufigste Antwort ist («ganzes Netz»). */
.kf-gal__netz {
  display: grid; grid-template-columns: minmax(0, 1fr) auto;
  align-items: center; gap: 10px; width: 100%;
  min-height: 52px; padding: 8px 12px; margin: 0 0 8px;
  border: 1px solid var(--accent-line); border-radius: var(--radius-card);
  background: var(--accent-soft); color: inherit;
  font: inherit; text-align: left; cursor: pointer;
}
.kf-gal__netz.is-voll { border-color: var(--border); background: var(--surface); }
.kf-gal__netz:disabled { opacity: .5; cursor: default; }
.kf-gal__netzwer { min-width: 0; }
.kf-gal__netzwer strong {
  display: block; font-size: 14px; font-weight: 650; color: var(--text-primary);
}
.kf-gal__netzwer small {
  display: block; margin-top: 2px; font-size: 12px; color: var(--text-tertiary);
}
.kf-gal__tun {
  flex: 0 0 auto; white-space: nowrap;
  font-size: 12.5px; font-weight: 650; color: var(--accent-strong);
}
.kf-gal__netz.is-voll .kf-gal__tun { color: var(--text-secondary); }

/* Kantone ODER Regionen. Zwei Knöpfe, EINE Zeile — kein Aufklappmenü. */
.kf-gal__ebene { display: flex; margin: 0 0 8px; }
.kf-gal__ebene button { flex: 1 1 0; }

/* DIE ZEILEN. Drei Spalten: öffnen (nimmt die ganze Breite) · der Zeiger ·
   der eine Griff, der das ganze Gebiet dazunimmt. Links öffnet, rechts wählt
   — dieselbe Trennung wie in der Ortsliste. */
.kf-gal__gitter {
  display: block;
  border: 1px solid var(--border); border-radius: var(--radius-card);
  background: var(--surface);
  overflow: hidden;
}
.kf-gal__zeile {
  display: grid; grid-template-columns: minmax(0, 1fr) auto auto;
  align-items: center; gap: 8px;
  padding: 5px 10px 5px 12px;
  border-bottom: 1px solid var(--border-subtle);
}
.kf-gal__zeile:last-child { border-bottom: 0; }
.kf-gal__zeile.is-voll { background: var(--accent-soft); }
.kf-gal__zeile.is-teil { background: rgba(var(--accent-rgb), .06); }
.kf-gal__auf {
  display: block; min-width: 0; min-height: 40px; padding: 4px 0;
  border: 0; background: transparent; color: inherit;
  font: inherit; text-align: left; cursor: pointer;
}
.kf-gal__auf strong {
  display: block; font-size: 13.5px; font-weight: 650; color: var(--text-primary);
}
.kf-gal__auf small {
  display: block; margin-top: 2px; font-size: 11.5px; color: var(--text-tertiary);
}
.kf-gal__auf:hover strong { color: var(--accent-strong); }
.kf-gal__pfeil { font-size: 17px; line-height: 1; color: var(--text-tertiary); }
.kf-gal__dazu { min-width: 78px; font-size: 12.5px; }

/* Am Handy gilt der Griff-Boden von 44 px (Anlass dieser Galerie). */
@media (max-width: 1080px), (pointer: coarse) {
  .kf-gal__netz { min-height: 56px; padding: 9px 12px; }
  .kf-gal__netzwer strong { font-size: 15px; }
  .kf-gal__ebene button { min-height: 44px; }
  .kf-gal__zeile { padding: 7px 10px 7px 12px; }
  .kf-gal__auf { min-height: 48px; }
  .kf-gal__auf strong { font-size: 15px; }
  .kf-gal__dazu { min-height: 44px; }
}

/* ===========================================================================
   DER KORB-STREIFEN AM HANDY — klebend, 44-px-Griffe (Owner 26.08.2026)
   ===========================================================================
   OWNER-WORTLAUT am eigenen Telefon: «… kann man nicht entfernen und neu
   wählen sehr unständlich viel zu lange». Die Grundform des Streifens steht
   seit 02.09. bei den Blättern (oben, auf jeder Breite); hier nur, was am
   Finger anders ist: er KLEBT (`sticky`, nicht `fixed` — er gehört zum Blatt,
   nicht zum Schirm), rollt in EINER Zeile, und das ✕ ist 44 × 44 statt 28. */
@media (max-width: 1080px), (pointer: coarse) {
  .kf-strf {
    position: sticky; top: 0; z-index: 3;
    margin: 0 0 8px; padding: 6px 0 7px;
    background: var(--surface);
    border-bottom: 1px solid var(--border);
  }
  .kf-strf__alles { min-height: 44px; font-size: 12.5px; }
  .kf-strf__reihe {
    flex-wrap: nowrap; margin-top: 5px;
    overflow-x: auto; overflow-y: hidden;
    scrollbar-width: none; -webkit-overflow-scrolling: touch;
    overscroll-behavior-x: contain;
  }
  .kf-strf__reihe::-webkit-scrollbar { display: none; }
  .kf-strf__stueck {
    flex: 0 0 auto; max-width: 74vw; min-height: 44px; padding: 3px 3px 3px 10px;
  }
  .kf-strf__wer b { font-size: 13px; }
  .kf-strf__stueck button { width: 44px; height: 44px; min-width: 44px; font-size: 15px; }
}

/* ===========================================================================
   DER BERATUNGSRECHNER AUF BLATT 1 (06.09.2026)
   ---------------------------------------------------------------------------
   Owner woertlich (06.09.): «wenn jemand sagt ja ich 3000 Fr. investiere ich
   lieber in Social Media dann habe ich viel mehr Anfragen — aber viel mehr ist
   ja nicht immer gleich besser.» Dieser Satz faellt am Offertentisch. Der
   Rechner dazu war gebaut und stand nur in der Lead-Akte; hier stand ein
   Kommentar, der auf ihn zeigte.

   ER STEHT UNTER DEN DREI SPALTEN, nicht als vierte daneben. Drei Gruende:
   Kunde/Wozu/Korb sind je ein Drittel des Blatts breit (210–280 px) und
   tragen keinen Rechner mit zwei Saeulen; er beantwortet die Frage des Blatts
   WEITER, statt eine vierte zu stellen; und auf 390 px stuenden vier Spalten
   untereinander — der Rechner waere unter drei Bildschirmhoehen begraben.

   KEINE EIGENE GESTALT. Der Kasten kommt fertig aus
   components/wegvergleich.js und traegt das Kleid der Referenz (Ueberzeile,
   grosser duenner Frage-Titel, Haarlinien, blaue Toenung fuer «unser Weg»).
   Hier steht nur, WO er sitzt und dass er dem Blatt gehoert — kein Rahmen um
   einen Rahmen, keine zweite Farbe.
   =========================================================================== */
.kf-rechner { margin-top: 14px; }
/* Der Bereichsname dieser Flaeche statt `la-abschnitt` (Lead-Akte): derselbe
   Innenabstand, aber unter dem Namen des Bereichs, dem die Flaeche gehoert.
   Ein Blatt, das die Klasse eines fremden Bereichs traegt, ist der Anfang
   davon, dass beide zusammenwachsen. */
.kf-rechner__rahmen { padding: 14px 16px; }
.kf-rechner__rahmen > .panel__title { margin-top: 0; }
/* Am Handy hat das Blatt seinen eigenen Rand — der Kasten liegt buendig zu
   den Spalten darueber, nicht enger. */
@media (max-width: 720px), (pointer: coarse) {
  .kf-rechner { margin-top: 12px; }
  .kf-rechner__rahmen { padding: 12px 12px 14px; }
}

.kf-order-work__title { display:flex; align-items:baseline; gap:16px; padding:24px 28px 18px; }
.kf-order-work__title h2 { margin:0; font-size:22px; letter-spacing:-.025em; }
.kf-order-work__title > span { font-size:12px; color:var(--text-secondary); }
.kf-order-work__grid { display:grid; grid-template-columns:minmax(0,1.45fr) minmax(280px,.55fr); gap:28px; padding:0 28px 28px; align-items:start; }
.kf-order-work__configuration,.kf-order-work__advice { min-width:0; }
.kf-order-work__configuration .kf-auftrag { grid-template-columns:repeat(auto-fit,minmax(min(100%,240px),1fr)); padding:0; gap:16px; }
.kf-order-work__configuration .kf-auftrag__spalte--korb { grid-column:1/-1; }
.kf-order-work__advice { border-left:1px solid var(--border); padding-left:24px; }
.kf-order-work__advice .ad-editor { padding:4px 0 18px; }
.kf-order-work__advice .ad-editor__head { flex-wrap:wrap; gap:8px; }
.kf-order-work__advice .ad-editor__drafttools { padding-top:14px; }
.kf-order-work--guided .kf-order-work__grid { grid-template-columns:minmax(0,1.35fr) minmax(300px,.65fr); }
.kf-order-work--guided .kf-order-work__advice { order:-1; border-left:0; padding-left:0; }
.kf-order-work--guided .kf-order-work__configuration { border-left:1px solid var(--line); padding-left:24px; }
.kf-order-work--guided .kf-auftrag { grid-template-columns:minmax(0,1fr); }
.kf-order-work--guided .ad-editor__head h2 { font-size:23px; }
@media(max-width:980px) {
  .kf-order-work__grid,.kf-order-work--guided .kf-order-work__grid { grid-template-columns:minmax(0,1fr); padding:0 16px 20px; gap:20px; }
  .kf-order-work__advice { order:-1; border-left:0; padding-left:0; }
  .kf-order-work--guided .kf-order-work__configuration { border-left:0; border-top:1px solid var(--line); padding:20px 0 0; }
  .kf-order-work__advice .ad-editor__drafttools { border-bottom:0; }
}
@media(max-width:620px) {
  .kf-order-work__configuration .kf-auftrag { grid-template-columns:minmax(0,1fr); }
}

/* Compact, persistent offer summary; details stay in the selected work sheet. */
.kf-consultation { display:grid; grid-template-columns:auto minmax(0,1fr) minmax(0,1fr) minmax(0,1.2fr); gap:0; flex-shrink:0; background:var(--surface-inset); border-bottom:1px solid var(--border); }
.kf-consultation > button { display:grid; align-content:center; gap:3px; text-align:left; min-width:0; padding:8px 14px; background:transparent; color:var(--text-primary); border:0; border-right:1px solid var(--border); cursor:pointer; font:inherit; }
.kf-consultation > button:last-child { border-right:0; }
.kf-consultation > button:hover { background:var(--accent-soft); }
.kf-consultation > button:focus-visible { outline:2px solid var(--accent); outline-offset:-2px; }
.kf-consultation span,.kf-consultation small { font-size:11px; line-height:1.4; color:var(--text-secondary); }
.kf-consultation strong { font-size:16px; line-height:1.3; font-variant-numeric:tabular-nums; overflow-wrap:anywhere; }
.kf-known-lead { display:grid; gap:10px; }
.kf-known-lead p { margin:0; color:var(--text-secondary); line-height:1.5; }
@media (max-width:1080px), (pointer:coarse) {
  .kf-order-work:not(.kf-order-work--guided) .kf-order-work__advice { order:0; }
  .kf-schritte > ol { display:grid; grid-template-columns:repeat(5,minmax(0,1fr)); }
  .kf-schritte > ol > li { min-width:0; }
  .kf-schritt,.kf-schritt:not([aria-selected="true"]) { display:flex; flex-direction:column; justify-content:center; width:100%; min-height:48px; gap:2px; padding:6px 2px; }
  .kf-schritt .kf-schritt__nr { display:none; }
  .kf-schritt:not([aria-selected="true"]) .kf-schritt__wer { display:grid; }
  .kf-schritt .kf-schritt__wer strong { font-size:11px; white-space:normal; overflow:visible; overflow-wrap:anywhere; }
  .kf-schritt .kf-schritt__wer small { display:none; }
}
/* 15.09.: economic work needs the whole work surface; the quote stays reachable. */
.kf-order-work--guided .kf-order-work__grid{grid-template-columns:minmax(0,1fr)}
.kf-order-work--guided .kf-order-work__configuration{border-left:0;border-top:1px solid var(--line);padding:20px 0 0}
.kf-order-work--guided .kf-order-work__configuration>summary{cursor:pointer;min-height:44px;font-weight:650}
.kf-order-work--guided .kf-order-work__advice{order:-1;width:100%;max-width:none}
.kf-work-modes { display:flex; align-items:center; gap:4px; padding:6px 10px; border-right:1px solid var(--border); }
.kf-work-modes > button { border:1px solid transparent; background:transparent; color:var(--text-secondary); border-radius:var(--radius-button); min-height:40px; padding:8px 12px; cursor:pointer; font:inherit; font-size:13px; font-weight:600; }
.kf-work-modes > button[aria-pressed="true"] { background:var(--accent); color:var(--on-accent); }
.kf-work-modes > button:focus-visible { outline:2px solid var(--accent); outline-offset:2px; }
.kf-work-context{border-bottom:1px solid var(--line);margin:0;background:var(--surface)}.kf-work-context>summary{cursor:pointer;font-size:12px;padding:8px 18px;color:var(--muted)}
@media(max-width:760px) {
  .kf-consultation { grid-template-columns:minmax(0,1fr) minmax(0,1.15fr) minmax(0,1fr); }
  .kf-consultation > button { padding:6px 10px; min-height:56px; }
  .kf-consultation > button small { display:none; }
  .kf-consultation strong { font-size:13px; }
  .kf-work-modes { grid-column:1/-1; padding:2px 8px; border-right:0; border-bottom:1px solid var(--border); }
  .kf-work-modes > button { flex:1; min-width:0; min-height:40px; padding:6px 10px; font-size:12px; }
  .kf-work-context > summary { padding:6px 10px; }
  .kf-order-work__title { padding:18px 16px; display:block; }
  .kf-order-work__title h2 { font-size:20px; margin-bottom:5px; }
}

.ew-studio-toolbar { display:flex; flex-wrap:wrap; gap:16px; align-items:flex-end; justify-content:space-between; }
.ew-studio-toolbar>label { display:grid; gap:7px; font-size:12px; color:var(--text-secondary); }
.ew-studio-toolbar select { min-height:44px; padding:9px 34px 9px 12px; min-width:140px; border:1px solid var(--border); border-radius:8px; background:var(--surface); color:var(--text-primary); font-size:14px; }
.ew-journey-canvas { display:grid; grid-template-columns:minmax(250px,1.1fr) minmax(280px,1fr); gap:28px; align-items:start; }
.ew-funnel { display:grid; gap:7px; }
.ew-funnel-stage { display:grid; grid-template-columns:minmax(0,1fr) auto; align-items:center; gap:8px 18px; padding:12px 16px; border:1px solid transparent; border-radius:9px; color:var(--text-primary); text-align:left; background:var(--surface); cursor:pointer; }
.ew-funnel-stage:hover { background:var(--surface-hover); border-color:var(--border); }
.ew-funnel-stage[aria-pressed=true] { border-color:var(--accent); background:var(--accent-soft); }
.ew-funnel-stage b { font-size:14px; font-weight:550; }
.ew-funnel-stage small { display:block; color:var(--text-secondary); font-size:12px; margin-top:3px; }
.ew-funnel-stage strong { font-size:22px; font-weight:600; font-variant-numeric:tabular-nums; }
.ew-funnel-track { grid-column:1/-1; width:100%; height:4px; display:block; background:var(--border); border-radius:3px; overflow:hidden; }
.ew-funnel-track>span { display:block; height:100%; background:var(--accent); border-radius:3px; transition:width 170ms ease-out; }
.ew-stage-settings { position:sticky; top:16px; padding:20px; border:1px solid var(--border); border-radius:12px; background:var(--surface-1); min-width:0; }
.ew-stage-settings>h4 { font-size:18px; line-height:1.4; margin:0 0 18px; }
.ew-stage-settings>details { margin:20px 0; border-top:1px solid var(--border); border-bottom:1px solid var(--border); padding:12px 0; }
.ew-stage-settings summary { cursor:pointer; min-height:32px; font-size:14px; font-weight:550; }
.ew-stage-settings .ew-output { position:static; border:0; padding:16px 0 0; background:transparent; }
.ew-stage-settings .ew-input { margin-bottom:14px; }
.ew-result-title { padding:0 0 16px; margin:12px 0; border-bottom:1px solid var(--border); }
.ew-result-title>span { display:block; font-size:13px; color:var(--text-secondary); margin-bottom:8px; }
.ew-result-title>strong { display:block; font-size:30px; line-height:1.2; font-weight:600; font-variant-numeric:tabular-nums; }
.ew-result-title small { font-size:12px; font-weight:400; color:var(--text-secondary); }
.ew-warning { background:var(--warn-soft,var(--surface-2)); color:var(--text-primary); padding:12px; border:1px solid var(--warn); border-radius:8px; font-size:13px; line-height:1.55; }
.ew-waterfall { display:block; width:100%; height:auto; overflow:visible; margin-bottom:12px; }
.ew-waterfall text { fill:var(--text-primary); font-size:16px; font-weight:550; font-variant-numeric:tabular-nums; }
.ew-waterfall .ew-bridge-label { font-size:13px; fill:var(--text-secondary); font-weight:400; }
.ew-chart-axis { stroke:var(--border); stroke-width:1; }
.ew-bridge-total { fill:var(--accent-deep); }.ew-bridge-gain { fill:var(--good); }.ew-bridge-cost { fill:var(--warn); }
.ew-sensitivity { width:100%; border-collapse:collapse; margin:16px 0; font-size:13px; }
.ew-sensitivity :is(th,td) { border-bottom:1px solid var(--border); padding:12px 0; text-align:left; }
.ew-sensitivity :is(th,td):last-child { text-align:right; font-variant-numeric:tabular-nums; }
.ew-studio .ew-inputs>[data-advisory-action=workbench-example] { margin-bottom:18px; padding:10px 12px; border:1px solid var(--border); background:var(--surface); color:var(--text-primary); border-radius:8px; text-align:left; cursor:pointer; }
.ew-studio :is(button,select,input):focus-visible { outline:2px solid var(--accent); outline-offset:3px; }
@media(max-width:800px) { .ew-journey-canvas { grid-template-columns:minmax(0,1fr); gap:20px; } .ew-stage-settings { position:static; } .ew-funnel { grid-template-columns:repeat(3,minmax(0,1fr)); gap:6px; } .ew-funnel-stage { display:flex; flex-direction:column; align-items:flex-start; padding:10px; } .ew-funnel-stage strong { font-size:19px; } .ew-funnel-stage b { font-size:12px; } .ew-funnel-stage small { font-size:11px; } .ew-studio>h3 { font-size:20px; } }
@media(max-width:430px) { .ew-funnel { grid-template-columns:repeat(2,minmax(0,1fr)); } .ew-studio-toolbar>label { flex:1; } .ew-studio-toolbar select { max-width:100%; min-width:0; } .ew-stage-settings { padding:15px; } }
@media(prefers-reduced-motion:reduce) { .ew-funnel-track>span { transition:none; } }
.ew-input-intro,.ew-inputs>.ew-hint { grid-column:1/-1; }
.ew-sections { display:flex; flex-wrap:wrap; gap:5px; margin-bottom:14px; }
.ew-sections button { flex:1; min-height:42px; padding:7px 9px; border:1px solid var(--border); border-radius:7px; background:transparent; color:var(--text-secondary); font-size:12px; cursor:pointer; }
.ew-sections button[aria-pressed=true] { color:var(--accent-strong); border-color:var(--accent); background:var(--accent-soft); }
.ew-example { margin-top:22px; font-size:13px; color:var(--text-secondary); }
.ew-example summary { cursor:pointer; padding:8px 0; }
.ew-example button { padding:9px 14px; background:var(--surface); border:1px solid var(--border); color:var(--text-primary); border-radius:7px; cursor:pointer; }

/* Use the available work surface inside the ERP navigation. */
.ew-studio { container-type:inline-size; }
@container(max-width:760px) { .ew-journey-canvas { grid-template-columns:minmax(0,1fr); gap:18px; }.ew-funnel { grid-template-columns:repeat(3,minmax(0,1fr)); gap:7px; }.ew-funnel-stage { display:flex; flex-direction:column; align-items:flex-start; gap:6px; padding:11px; }.ew-funnel-stage strong { font-size:21px; }.ew-funnel-stage b { font-size:12px; }.ew-funnel-stage small { font-size:11px; }.ew-funnel-track { height:3px; margin-top:auto; }.ew-stage-settings { position:static; padding:18px; }.ew-studio>h3 { font-size:18px; margin:16px 0; } }
@container(max-width:340px) { .ew-funnel { grid-template-columns:repeat(2,minmax(0,1fr)); } }


/* ============================================================
   Patch-Integration — Namensraum vk-karte__; Quelle: docs/design/patch-kundenkarte-griff.css
   ============================================================ */
/* ===========================================================================
   NAHT A-1 · DIE KUNDENKARTE BEKOMMT IHREN GRIFF (11.08.2026)
   ===========================================================================
   Eigener Block, zeichengleich gespiegelt am Ende von `public/style.css`.
   Er ergänzt den Karten-Abschnitt (style.css §4 «Karten-Raster») um genau
   zwei Dinge und ändert dort keine bestehende Regel.

   ANLASS (Owner-Durchlauf «Generali», 10.08.): Die Kundenkarte war ein `<a>`
   ohne Innenleben — ein Suchschritt ohne Ziel. Der Weg zur Offerte lief über
   das Dossier und dort über einen Reiter. Der Griff gehört an die Karte.

   WARUM DIE KARTE DAFÜR KEIN LINK MEHR IST: ein Knopf im Link ist ungültiges
   Markup — dieselbe Begründung, die style.css bereits für die Offertenkarte
   festhält («Die Karte IST die Tür — auch dort, wo sie kein <a> ist»). Der
   NAME bleibt ein echter Link, damit Mittelklick, Vorschau und Tastatur
   erhalten bleiben; die Karte ist die bequeme Fläche darüber. Beides braucht
   je eine Regel, sonst sähe der Name aus wie ein Link (Unterstrich, blau)
   und die Karte hätte keinen sichtbaren Fokus mehr.

   Das Winkelzeichen ist dasselbe Mittel wie in der Kundenwelt
   (`.ko-zeile__weg`, docs/design/patch-meine-offerten.css) und in den Listen der Innenwelt: es
   sagt IM RUHEZUSTAND, dass hier eine Tür ist. Hover und Fokus helfen nur
   dem, der schon weiss, dass da etwas ist.
   =========================================================================== */

/* Der Name ist die Tür — er soll aussehen wie der Titel, den er ersetzt,
   nicht wie ein Link. Farbe und Schnitt bleiben in `.vk-karte__titel`. */
.vk-karte__tuer {
  color: inherit;
  text-decoration: none;
}
/* Dafür trägt er den Fokusring, den vorher die ganze Karte trug
   (`.vk-karte:focus-visible`, style.css:13650) — sonst verlöre die Tastatur
   ihre sichtbare Spur. Der Radius hält den Ring am Wort statt am Rechteck. */
.vk-karte__tuer:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--radius-card);
}

/* Das Winkelzeichen sitzt am rechten Ende der FUSSZEILE — und das ist eine
   gemessene Entscheidung, kein Geschmack.

   ZUERST STAND ES IM KARTENKOPF, neben dem Zustands-Chip. Dort kostet es roh
   28px (Kopf-Lücke 10 + Kasten 18), und die hat der Kopf nicht: auf der 330px
   breiten Karte (1400px-Fläche, vier Spalten) bleiben dem Namen 174px, und
   «Barbershop Zentral GmbH» braucht 165. Gemessen am 11.08. war der
   Firmenname danach abgeschnitten — genau das Billige, gegen das der
   Karten-Abschnitt gebaut ist, und `_verkauf_ui_test.mjs` sagt es laut («kein
   Firmenname wird abgeschnitten»). Auch mit negativen Rändern blieben nur
   1–2px Luft; eine Lösung, die auf zwei Pixel steht, ist keine.

   Die Fusszeile hat rechts NICHTS stehen (höchstens drei kurze Angaben, links
   ausgerichtet). Dort kostet das Zeichen den Namen nichts und steht trotzdem
   im Ruhezustand da. `margin-left: auto` schiebt es ans Ende der Zeile.

   Es ist ein `<i>`, kein `<span>`: die Fusszeile trägt höchstens DREI
   Angaben, und genau die zählt `_verkauf_ui_test.mjs` als `span`. Ein
   Winkelzeichen als vierter `span` hätte den Wächter rot gemacht — und die
   ehrliche Antwort darauf ist, das Zeichen aus der Zählung zu nehmen, nicht
   die Zählung aus dem Wächter. Nebenwirkung, die dazu passt: der Trennpunkt
   der Fusszeile (`span + span::before`) greift auf ein `<i>` gar nicht erst
   zu — es steht ja auch kein «·» vor einer Tür. */
.vk-karte__weg {
  display: inline-flex;
  align-items: center;
  margin-left: auto;
  color: var(--text-tertiary);
}
.vk-karte__weg svg { width: 18px; height: 18px; }
.vk-karte:hover .vk-karte__weg { color: var(--accent); }

/* ===========================================================================
   § 3 · DIE TUER IST SO GROSS WIE DIE KARTE (04.09.2026)
   ===========================================================================
   GEMESSEN, NICHT GEMEINT: `a.vk-karte__tuer` mass auf ALLEN NEUN Breiten
   118.9 x 16 px — der Name ist der einzige echte Link in die Kundenakte, und
   er war 16 px hoch. Der Griff-Boden dieses Hauses ist 44 px.

   WARUM ES NIEMAND SAH: Die Kundenliste stand zwar in SCHIRME, aber die
   Attrappe der Fundament-Buehne kannte `sales_customers_overview` nicht — die
   Flaeche zeigte ihren Leerzustand, und ein Leerzustand hat keine Karten.
   Seit dem 04.09. traegt die Attrappe drei Kunden (scripts/lib/fundament-
   buehne.mjs), und im selben Lauf fiel dieser Befund 27-mal (3 Karten x 9
   Breiten). Ein Waechter ueber einer leeren Flaeche misst nichts.

   DIE ANTWORT IST NICHT «MACH DEN NAMEN 44 PX HOCH». Das risse den
   Kartenkopf auseinander und aendert eine Liste, die der Owner taeglich
   ansieht, ohne Not. Die Wahrheit steht schon im Kopf dieser Datei: DIE KARTE
   IST DIE TUER, der Name traegt sie nur sichtbar (und wegen Mittelklick,
   Vorschau und Tastatur ist er ein echtes `<a>`). Also bekommt der Anker die
   Fangflaeche der Karte — dasselbe Mittel, das dieses Haus schon fuehrt
   (`.firm-card__weg::after`, patch-leadakte.css:39; «DIE TAPFLAECHE OHNE DIE
   HOEHE», patch-pool.css) und das die Messung ausdruecklich kennt
   (scripts/lib/breiten-mass.mjs:249).

   WAS SICH DABEI VERHAELT: nichts Sichtbares. Der Klick auf die Karte landete
   vorher beim Horcher (`sales-customers.js:797`), jetzt beim Anker — und der
   Horcher tritt bei jedem `<a>` von selbst zurueck (`e.target.closest('a,
   button')`). Das Ziel ist beide Male `#/v/customer/<id>`. Gewonnen ist der
   Mittelklick auf der ganzen Karte statt nur auf dem Wort.

   NUR IN DER KUNDENLISTE: die Offertenliste benutzt dieselbe Klasse fuer
   einen ANDEREN Satz («Kunde zuordnen», sales-offers.js:1500). Dort ist der
   Anker keine Tuer zur Karte, sondern eine Nachbesserung — er darf die Karte
   nicht schlucken.
   =========================================================================== */
body.lx-kundenliste .vk-karte__tuer::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: var(--radius-card);
}

/* ============================================================
   Patch-Integration — Namensraum anruf-/jetzt__reihe (Anruf-Moment); Quelle: docs/design/patch-anrufmoment.css
   ============================================================ */
/* ============================================================
   W11.3 / W11.5 — Der Anruf-MOMENT
   Quelle: components/anruf-kontext.js · components/anruf-reihe.js
   Beweis: scripts/_anrufweg_ui_test.mjs
   ============================================================

   WARUM ES DIESEN BLOCK GIBT. Der verzweigende Katalog-Baum stand seit dem
   31.07. im Anruf-Fenster — nur stand darüber nichts als ein Firmenname.
   Wen genau rufe ich an, unter welcher Nummer, was war beim letzten Mal, wo
   im Ablauf bin ich, und was löst mein Antippen aus? Vier Fragen, vier neue
   Bausteine, alle INNERHALB des bestehenden `.mini-modal` — kein zweites
   Fenster, keine zweite Bauart.

   Bewusst NICHT dupliziert und darum hier nicht noch einmal beschrieben:
   `.assessment-q`/`.tap-group`/`.tap-btn` (1649-1684, das Tap-Vokabular samt
   44px-Touch), `.so2-chips`/`.so2-chip`, `.call-when`, `.mini-modal`
   (1568-1605) und `.firm-link` — der Anruf-Kopf leiht sich davon die Optik
   der Nummer.
   ============================================================ */

/* Der Kopf: wen rufe ich an. Er sitzt als ruhige Fläche über dem Baum, damit
   der Blick zuerst die Firma trifft und dann die erste Frage. */
.anruf-kopf {
  display: grid;
  gap: 6px;
  padding: 12px 14px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
}
.anruf-kopf__firma {
  margin: 0;
  display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap;
}
.anruf-kopf__firma b { font-size: 15px; color: var(--text); }
.anruf-kopf__ort { font-size: 12px; color: var(--text-secondary); }

/* Die Nummer ist ein ANGEBOT, kein Zwang: ein grosser Tap-Bereich mit dem
   Hörer-Zeichen, der `tel:` öffnet — gewählt wird nie automatisch. 44px, weil
   das der Griff ist, den ein Berater am Handy als erstes trifft. */
.anruf-kopf__nummer {
  display: inline-flex; align-items: center; gap: 8px;
  min-height: 44px; padding: 8px 12px;
  border: 1px solid var(--accent-line); border-radius: var(--radius-button);
  background: var(--accent-soft); color: var(--accent-strong);
  font-size: 14.5px; font-weight: 650; text-decoration: none;
  justify-self: start;
  font-variant-numeric: tabular-nums;
}
.anruf-kopf__nummer svg { width: 16px; height: 16px; }
.anruf-kopf__nummer:hover { border-color: var(--accent); }
/* Ohne Nummer tut nichts so, als könnte man wählen. */
.anruf-kopf__nummer--leer {
  background: transparent; border-color: var(--border);
  color: var(--text-tertiary); font-weight: 500;
}

/* Die Vorgeschichte — «3× angerufen · zuletzt 05.08.2026 · 2. Runde».
   Steht nur da, wenn es sie gibt (OWNER-WUENSCHE 16). */
.anruf-kopf__her {
  margin: 0; font-size: 12px; color: var(--text-secondary);
  font-variant-numeric: tabular-nums;
}
/* Was damals gesagt wurde. Das Wort davor ist die Etikette, nicht der Inhalt. */
.anruf-kopf__damals {
  margin: 0; font-size: 12.5px; color: var(--text-secondary);
  line-height: 1.45;
  border-left: 2px solid var(--accent-line); padding-left: 10px;
}
.anruf-kopf__damals span {
  display: block; font-size: 11px; letter-spacing: .08em;
  text-transform: uppercase; color: var(--text-tertiary); margin-bottom: 2px;
}

/* Leerer Kopf = keine Lücke im Raster (der Aufrufer gibt nicht immer eine
   Firma mit; dann verhält sich das Fenster exakt wie vorher). */
[data-slot="kopf"]:empty { display: none; }

/* Wo stehe ich. Ein Wort und ein Balken — mehr braucht es nicht, und weniger
   wäre der starre Frage-Roboter, den der Owner am 19.07. abgelehnt hat.
   Die Leiste steht zwischen Kopfzeile und Körper, also AUSSERHALB des
   mitscrollenden Bereichs — auf einem langen Ast wächst der Baum über die
   Fensterhöhe hinaus, und genau dann zählt «wie weit bin ich» am meisten. */
.anruf-standleiste {
  padding: 8px 18px;
  border-bottom: 1px solid var(--border);
  background: var(--surface);
  flex: 0 0 auto;
}
.anruf-standleiste:empty { display: none; }
.anruf-stand {
  margin: 0; display: flex; align-items: center; gap: 10px;
}
.anruf-stand__wort {
  font-size: 11.5px; letter-spacing: .04em; color: var(--text-secondary);
  white-space: nowrap; font-variant-numeric: tabular-nums;
}
.anruf-stand__bar {
  flex: 1 1 auto; height: 4px; border-radius: 999px;
  background: var(--surface-3); overflow: hidden;
}
.anruf-stand__bar i {
  display: block; height: 100%; border-radius: 999px;
  background: var(--accent); transition: width var(--transition);
}
.anruf-stand.is-fertig .anruf-stand__wort { color: var(--accent-strong); }

/* Die Folge. Sie sitzt zwischen Baum und Knopf, weil sie GENAU den Knopf
   beschreibt, der darunter steht (Grundgesetz 2). */
.anruf-folge {
  margin: 0; padding: 10px 18px;
  border-top: 1px solid var(--border);
  background: var(--accent-soft); color: var(--accent-strong);
  font-size: 13px; font-weight: 600; line-height: 1.4;
}

/* W11.5: der Reihen-Knopf im JETZT-Streifen. Er steht NEBEN «Anrufen», nie
   davor — ein Anruf ist der Normalfall, die Reihe die Absicht. */
.jetzt__reihe {
  display: inline-flex; align-items: center; gap: 8px;
  min-height: 44px; white-space: nowrap;
}
.jetzt__reihe-zahl {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 22px; height: 20px; padding: 0 6px;
  border-radius: var(--radius-badge); background: var(--accent-soft); color: var(--accent-strong);
  font-size: 11.5px; font-weight: 700; font-variant-numeric: tabular-nums;
}

@media (max-width: 720px) {
  /* Handy zuerst (Grundgesetz 6): der Kopf bleibt kompakt, die Nummer wird
     zur vollen Zeile — sie ist der Griff, den der Daumen sucht. */
  .anruf-kopf { padding: 10px 12px; }
  .anruf-standleiste { padding: 8px 14px; }
  .anruf-kopf__nummer { justify-self: stretch; width: 100%; justify-content: center; }
  .anruf-folge { padding: 10px 14px; }
  /* Der Reihen-Knopf teilt sich die Zeile mit «Anrufen» statt zu überlaufen. */
  .jetzt__reihe { flex: 1 1 100%; justify-content: center; }
}

/* ============================================================
   Patch-Integration — Namensraum li- (Leads hochladen); Quelle: docs/design/patch-leadimport.css
   ============================================================ */
/* ===========================================================================
   W11.2 · «Leads hochladen» — der geführte Weg (views/lead-import.js)
   ===========================================================================
   Es gibt hier bewusst KEINE eigene Schrittleisten-Bauart: das Band benutzt
   `.kf-schritte` / `.kf-schritt` des Offerten-Wegs (EINHEIT §5.3, nummerierte
   Kreise mit Namen). Eine zweite Bauart wäre genau die Uneinheitlichkeit, die
   EINHEIT.md schlichtet. Ergänzt wird nur, was diese Fläche zusätzlich
   braucht: das Band steht hier in der Seite statt in der Konfigurator-Schale,
   also bekommt es Rand und Abstand.

   Handy zuerst (Grundgesetz 6): jede Reihe bricht auf EINE Spalte um, und die
   beiden Tabellen scrollen in ihrem eigenen Kasten — die Seite selbst läuft
   auf 390 px nie waagerecht über. */
/* Der Kopf ist eine REIHE, nicht zwei Zeilen. `.admin-page__head` ist ein
   blosser Block; jede Fläche mit einem Griff daneben macht ihn selbst zur
   Reihe (dasselbe tut `.pool-kopf`). Ohne diese drei Zeilen rutscht «Zum
   Pool» unter die Überschrift. */
.li-seite .admin-page__head {
  display: flex; flex-wrap: wrap; align-items: center;
  justify-content: space-between; gap: 10px;
}
.li-band { border: 1px solid var(--border); border-radius: var(--radius-card); margin-bottom: 14px; overflow: hidden; }
/* Drei Schritte, drei Spalten. `.kf-schritte` ist auf fünf gesetzt (der
   Offerten-Weg hat fünf) — ohne diese Zeile stünden hier zwei leere Spalten. */
.li-band > ol { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.li-panel { margin-top: 0; }
.li-panel + .li-panel { margin-top: 16px; }

.li-datei input[type="file"] { padding: 10px 0; font: inherit; color: var(--text-secondary); max-width: 100%; }
.li-gewaehlt { margin: 2px 0 12px; color: var(--text-secondary); font-size: 13px; }

.li-beispiel {
  margin: 14px 0 4px; padding: 12px 14px;
  border: 1px dashed var(--border); border-radius: var(--radius-card); background: var(--surface-2);
}
.li-beispiel strong { display: block; margin-bottom: 6px; font-size: 13px; }
.li-beispiel pre {
  margin: 0 0 8px; padding: 8px 10px; overflow-x: auto;
  border-radius: var(--radius-card); background: var(--surface-1);
  font-size: 12px; line-height: 1.6; white-space: pre;
}
.li-beispiel small { display: block; color: var(--text-secondary); line-height: 1.55; }

.li-zuordnung { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 12px; }
.li-zuordnung--fest { margin-top: 14px; padding-top: 14px; border-top: 1px solid var(--border); }
.li-fussnote { display: block; margin-top: 4px; color: var(--text-tertiary); font-size: 11.5px; line-height: 1.45; }

.li-probe { margin-top: 16px; }
.li-probe > strong { display: block; margin-bottom: 6px; font-size: 13px; }
/* Der eigene Kasten scrollt — nie die Seite (Grundgesetz 6). */
/* ENTFERNT am 21.08.2026, nicht ersetzt: `.li-tabelle` als eigene BAUART
   (eigener Wirt mit Rahmen, eigene Kopfzeile, eigene Zellenmasse) — und mit ihr
   der Umstand, dass diese Tabelle GAR KEINE Handy-Fassung hatte: acht Spalten
   auf 390 px, nur quer zu schieben. Die Flaeche traegt jetzt
   `class="team-table li-tabelle"` im Haus-Gehaeuse `.table-wrap`
   (BEREICHE §10, EINHEIT 4.9). Was hier BLEIBT, bleibt mit Grund und ist keine
   Bauart, sondern eine oertliche Notwendigkeit. */
/* Der lange Rapport scrollt senkrecht — dann muss seine Kopfzeile stehen
   bleiben, sonst weiss man nach zwanzig Zeilen nicht mehr, was «Stand» war. */
.li-tabelle-wirt--lang { max-height: 380px; overflow-y: auto; }
.li-tabelle-wirt--lang .li-tabelle thead th { position: sticky; top: 0; z-index: 1; background: var(--surface-2); }
/* Der Rapport hat ZWEI Spalten. Die 640px Mindestbreite des Hauses sind fuer
   acht gedacht; bei zweien schoeben sie die Liste grundlos seitwaerts.
   (`components/tabelle-beschriften.js` beschriftet erst ab drei Spalten — die
   Kartenform greift hier also bewusst nicht, zwei Spalten sind schon eine.) */
.li-tabelle-wirt--lang .team-table { min-width: 0; }
/* UMBENANNT 22.08.2026: `.li-leer` -> `.li-ohne-wert`. Der Name log. Das hier
   ist keine leere FLAECHE, sondern ein leerer WERT: der Gedankenstrich in
   einer Zelle der Importvorschau, wenn eine Spalte nichts enthaelt. Solange
   er `-leer` hiess, stand er in jeder Zaehlung der Leer-Bauarten mit drin
   und brauchte dort eine begruendete Ausnahme — fuer ein Ding, das mit dem
   Leerzustand einer Flaeche nichts zu tun hat. Ein Name, der eine Ausnahme
   noetig macht, ist der falsche Name. */
.li-ohne-wert { color: var(--text-tertiary); }

.li-zahlen { display: flex; flex-wrap: wrap; gap: 8px; margin: 4px 0 12px; }
.li-zahl {
  display: inline-flex; align-items: baseline; gap: 5px;
  padding: 7px 12px; border-radius: var(--radius-badge);
  background: var(--surface-2); color: var(--text-secondary); font-size: 13px;
}
.li-zahl b { font-size: 15px; font-weight: 700; color: var(--text-primary); font-variant-numeric: tabular-nums; }
.li-zahl--neu { background: var(--accent-soft); color: var(--accent-strong); }
.li-zahl--neu b { color: var(--accent-strong); }

.li-erklaerung { margin: 0 0 12px; padding-left: 18px; color: var(--text-secondary); font-size: 13px; line-height: 1.6; }
.li-erklaerung li + li { margin-top: 4px; }

.li-marke {
  display: inline-block; padding: 2px 9px; border-radius: var(--radius-badge);
  font-size: 11.5px; font-weight: 620; white-space: nowrap;
  background: var(--surface-2); color: var(--text-secondary);
}
.li-marke--neu { background: var(--accent-soft); color: var(--accent-strong); }

.li-rapport { margin: 2px 0 10px; font-size: 17px; font-weight: 650; line-height: 1.5; }
.li-warnung { margin: 0 0 10px; color: var(--danger); font-size: 13px; line-height: 1.55; }
.li-fortschritt { margin: 8px 0 0; color: var(--text-secondary); font-size: 13px; font-variant-numeric: tabular-nums; }
.li-tasten { margin-top: 16px; }

@media (max-width: 720px) {
  /* Eine Spalte, ganze Knöpfe. Auf 390 px steht jedes Auswahlfeld allein und
     jeder Griff ist über die volle Breite mit dem Daumen erreichbar. */
  .li-zuordnung { grid-template-columns: 1fr; }
  /* Ghost oben, Primärgriff unten — unten ist der Daumen. `.modal-actions`
     klebt am Handy ohnehin als Leiste am Fuss (style.css:1225); hier wird nur
     aus der Reihe eine Spalte. */
  .li-tasten { flex-direction: column; align-items: stretch; }
  .li-tasten > .primary-btn, .li-tasten > .ghost-btn { width: 100%; justify-content: center; }
  .li-rapport { font-size: 15.5px; }
  /* Nur der aktive Schritt trägt sein Wort — die übrigen bleiben Ziffer
     (EINHEIT §5.3, Schlichtung 11.08.: eine Zeile, kein Wischen). */
  .li-band .is-nebenan .kf-schritt__wer { display: none; }
  .li-band .kf-schritt { justify-content: center; padding: 6px 8px; }
}

/* ============================================================
   Patch-Integration — Namensraum lx-eskal-/lx-eskoffen- (Eskalationen); Quelle: docs/design/patch-eskalationen.css
   ============================================================ */
/* ── W11.6 · Eskalationen ────────────────────────────────────────────────────
   Zwei Flächen, ein Bild: der Katalog im Regel-Zentrum («Wenn etwas liegen
   bleibt») und die offenen Forderungen auf der Zentrale («Das liegt bei dir»).
   Beide leihen sich Farben, Radien und Abstände aus den Tokens — kein eigener
   Look, nur eine eigene Form. */
.lx-eskal { display: flex; flex-direction: column; gap: 10px; }
.lx-eskal__row {
  border: 1px solid var(--border); border-radius: var(--radius-card); padding: 12px 14px;
  background: var(--surface-2); display: flex; flex-direction: column; gap: 10px;
}
.lx-eskal__row.is-on { border-color: var(--accent-soft); }
.lx-eskal__kopf { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.lx-eskal__titel { font-size: 13.5px; font-weight: 620; }
.lx-eskal__anlass { font-size: 12px; color: var(--muted); }
.lx-eskal__felder { display: flex; flex-wrap: wrap; gap: 10px 14px; }
.lx-eskal__feld { display: flex; flex-direction: column; gap: 3px; min-width: 0; flex: 1 1 190px; }
.lx-eskal__feld > span { font-size: 11.5px; color: var(--muted); }
.lx-eskal__feld > select {
  min-height: 36px; border: 1px solid var(--border); border-radius: var(--radius-card);
  background: var(--surface); color: var(--text-primary); padding: 0 8px; font-size: 13px;
  max-width: 100%;
}
.lx-eskal__fuss { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.lx-eskal__stand { font-size: 12px; color: var(--muted); margin-right: auto; }
.lx-eskal__wartet { font-size: 11.5px; color: var(--warning, var(--muted)); }
.lx-eskal__save {
  min-height: 36px; padding: 0 12px; border-radius: var(--radius-card); font-size: 12.5px;
  border: 1px solid var(--border); background: var(--surface); color: var(--text-primary);
  cursor: pointer;
}
.lx-eskal__save:disabled { opacity: 0.5; cursor: wait; }

.lx-eskoffen__panel { margin-bottom: 16px; }
.lx-eskoffen__mark { display: inline-flex; vertical-align: -3px; margin-right: 6px; color: var(--danger); }
.lx-eskoffen__zahl { font-size: 12.5px; color: var(--muted); font-variant-numeric: tabular-nums; }
.lx-eskoffen__row {
  display: flex; align-items: center; gap: 10px; padding: 9px 0;
  border-top: 1px solid var(--border); min-width: 0;
}
.lx-eskoffen__row.is-gesehen { opacity: 0.62; }
.lx-eskoffen__body { display: flex; flex-direction: column; gap: 1px; min-width: 0; flex: 1 1 auto; }
.lx-eskoffen__titel { font-size: 13.5px; font-weight: 600; }
.lx-eskoffen__meta { font-size: 12px; color: var(--muted); }
.lx-eskoffen__tage {
  font-size: 12px; font-variant-numeric: tabular-nums; white-space: nowrap;
  color: var(--danger); flex: 0 0 auto;
}
.lx-eskoffen__ok {
  min-height: 36px; padding: 0 11px; border-radius: var(--radius-card); font-size: 12.5px;
  border: 1px solid var(--border); background: var(--surface); color: var(--text-primary);
  cursor: pointer; flex: 0 0 auto;
}
/* 03.09.: zwei Formen aus einer Quelle. Das Widget trägt das Frage-Kopf-Kleid
   (grund.css); die eigene Fläche ordnet nach Bereich mit gesperrten Versalien
   als Überschrift — dieselbe Schrift wie das Etikett des Frage-Kopfs. */
.lx-eskoffen__was { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.lx-eskoffen__bereich {
  margin: 18px 0 4px; font-size: 12px; font-weight: 650; letter-spacing: .16em;
  text-transform: uppercase; color: var(--text-secondary);
}
.lx-eskoffen__bereich:first-child { margin-top: 0; }
/* 24.08. — die Wand wird eine Karte: gleiche Anlässe gebündelt (ab drei),
   Einzelzeilen aufklappbar. Dieselbe Zeilen-Bauart, nur als <summary>. */
.lx-eskoffen__buendel { border-top: 1px solid var(--border); }
.lx-eskoffen__buendel > summary { list-style: none; cursor: pointer; }
.lx-eskoffen__buendel > summary::-webkit-details-marker { display: none; }
.lx-eskoffen__row--buendel { border-top: 0; }
.lx-eskoffen__row--buendel .lx-eskoffen__titel::before {
  content: '▸ '; color: var(--muted); font-size: 11px;
}
.lx-eskoffen__buendel[open] .lx-eskoffen__row--buendel .lx-eskoffen__titel::before {
  content: '▾ ';
}
.lx-eskoffen__row--innen { padding-left: 18px; }

@media (max-width: 720px), (pointer: coarse) {
  /* 390 px: jedes Auswahlfeld steht allein, jeder Griff ist über die volle
     Breite mit dem Daumen erreichbar (44 px wie im ganzen Haus), und nichts
     läuft seitlich hinaus. */
  .lx-eskal__feld { flex: 1 1 100%; }
  /* Der Haus-Riegel `select { min-height: 44px }` (Zeile ~630) verliert gegen
     die genauere Auswahl `.lx-eskal__feld > select` — darum steht die 44 hier
     noch einmal ausdrücklich, statt sich auf eine Kaskade zu verlassen. */
  .lx-eskal__feld > select { min-height: 44px; }
  .lx-eskal__save, .lx-eskoffen__ok { min-height: 44px; }
  .lx-eskal__fuss > .lx-eskal__save,
  .lx-eskal__fuss > .lx-policy__switch { flex: 1 1 auto; justify-content: center; }
  .lx-eskoffen__row { flex-wrap: wrap; }
  .lx-eskoffen__body { flex: 1 1 100%; }
}
/* ============================================================
   Patch-Integration — Namensraum gb (Gebiete); Quelle: docs/design/patch-gebiete.css
   Der Block wird bei Integration als GANZES ersetzt, nie editiert.
   W11.1 «Gebiets-Zuteilung» (Gesetz 16): die Flaeche #/a/gebiete und der
   Klartext-Streifen «Dein Gebiet» im Vertriebsportal und im Vertriebs-Dossier.
   ============================================================ */
/* W11.1 «Gebiete» — Namensraum .gb-*

   Die Flaeche #/a/gebiete (views/admin-gebiete.js) und der Klartext-Streifen
   «Dein Gebiet» im Vertriebsportal und im Vertriebs-Dossier.

   KEINE NEUE FARBE, KEIN NEUER ABSTAND. Alles kommt aus den Tokens:
   --surface-inset, --surface-2, --border, --text-primary/-secondary/-tertiary.
   Zustaende sind gerahmte Chips der bestehenden Bauart (.sl-badge, EINHEIT
   4.7), Knoepfe sind .primary-btn/.ghost-btn (1.4), der Seitentitel kommt aus
   .page-head und wird hier NICHT angefasst (1.5, 26 px).

   HANDY ZUERST GEDACHT. Jede Reihe darf umbrechen, jede Zelle traegt
   min-width: 0, jeder lange Ortsname bricht im Wort statt die Seite zu
   verbreitern. Auf 390 px steht die Weiten-Zeile unter dem Namen statt daneben
   und jeder Griff nimmt die volle Breite — ein Knopf, den man mit dem Daumen
   verfehlt, ist keiner. */

/* --- Die Liste der Gebiete ------------------------------------------------ */
.gb-liste { list-style: none; margin: 0; padding: 0; display: grid; gap: 14px; }

.gb-karte { padding: 16px; min-width: 0; }
.gb-karte.is-zu { opacity: .72; }

.gb-karte__kopf {
  display: flex; flex-wrap: wrap; align-items: baseline;
  justify-content: space-between; gap: 6px 14px; min-width: 0;
}
.gb-karte__wer { display: flex; flex-wrap: wrap; align-items: baseline; gap: 8px; min-width: 0; }
.gb-name { font-size: 16px; font-weight: 650; color: var(--text-primary); overflow-wrap: anywhere; }
.gb-art { font-size: 12.5px; color: var(--text-tertiary); }
.gb-stand {
  margin: 0; font-size: 13px; color: var(--text-secondary);
  font-variant-numeric: tabular-nums;
}

/* Die Weiten eines Gebiets. Ein Chip, ein Rueckweg — nie ein Kreuz ohne Wort:
   «Entfernen» sagt, was passiert, ein x muss man erraten. */
.gb-weiten {
  list-style: none; margin: 12px 0 0; padding: 0;
  display: flex; flex-wrap: wrap; gap: 8px;
}
.gb-weite {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 4px 6px 4px 4px;
  border: 1px solid var(--border); border-radius: var(--radius-badge);
  background: var(--surface-inset); min-width: 0;
}
.gb-weite .sl-badge { border: 0; background: transparent; }
.gb-weg { padding: 2px 8px; font-size: 12px; min-height: 26px; }

.gb-karte__akt {
  display: flex; flex-wrap: wrap; gap: 8px; margin-top: 14px;
}

/* ENTFERNT, nicht ersetzt: .gb-leer — GEFALLEN 21.08.2026 — die Leer-Zeile des Hauses ist EINE Form:
   `.empty-state.empty-state--zeile` + `.empty-state__weg` in docs/design/grund.css.
   Zwei ihrer fuenf Vorkommen trugen ueberdies gar keinen Leerzustand, sondern
   ein «wird geladen …»; die tragen jetzt `ladeZeile()`. */
.gb-hinweis { margin: 0 0 12px; font-size: 13px; color: var(--text-secondary); line-height: 1.55; }

/* --- Die Firmen eines Gebiets (die Nachpruefung) -------------------------- */
.gb-firmen {
  margin-top: 14px; padding: 12px;
  border: 1px solid var(--border); border-radius: var(--radius-card);
  background: var(--surface-inset);
}
.gb-firmen__satz {
  margin: 0 0 10px; font-size: 12.5px; color: var(--text-secondary); line-height: 1.55;
}
.gb-firmen__liste { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.gb-firmen__liste > li {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 10px; min-width: 0;
  font-size: 13.5px;
}
.gb-firmen__liste b { overflow-wrap: anywhere; }
.gb-ort { color: var(--text-tertiary); font-size: 12.5px; }

/* --- Der Verlauf ---------------------------------------------------------- */
.gb-verlauf { list-style: none; margin: 14px 0 0; padding: 0; display: grid; gap: 8px; }
.gb-verlauf > li {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 10px;
  font-size: 13px; color: var(--text-secondary); min-width: 0;
}
.gb-verlauf__wann { font-variant-numeric: tabular-nums; color: var(--text-tertiary); }
.gb-verlauf__wer { color: var(--text-primary); }
.gb-verlauf__wort { overflow-wrap: anywhere; }

/* --- Das Formular --------------------------------------------------------- */
.gb-form { padding: 16px; margin-bottom: 18px; }
.gb-form__felder {
  display: grid; gap: 12px;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
}
.gb-form__felder .field { min-width: 0; }
.gb-form__akt { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 16px; }

/* Die Ort-Weite als TREFFERLISTE, nicht als Vorrat (Gesetz 13). Sie ist
   bewusst gedeckelt hoch: wer scrollen muss, hat nicht gesucht. */
.gb-treffer {
  list-style: none; margin: 14px 0 0; padding: 0;
  display: flex; flex-wrap: wrap; gap: 8px;
  max-height: 168px; overflow-y: auto;
}
.gb-treffer .ghost-btn {
  display: inline-flex; align-items: baseline; gap: 8px;
  font-size: 13.5px;
}
.gb-treffer .ghost-btn.is-gewaehlt {
  border-color: var(--accent); color: var(--accent-strong);
}
.gb-treffer__zahl { font-size: 12px; color: var(--text-tertiary); font-variant-numeric: tabular-nums; }

/* --- Die benannten Gruppen (Entscheid W6) --------------------------------- */
.gb-gruppen { margin-top: 18px; padding: 16px; }
.gb-gruppen > summary { cursor: pointer; list-style: none; }
.gb-gruppen > summary::-webkit-details-marker { display: none; }
.gb-gruppen > summary h3 { display: inline; font-size: 15px; }
.gb-gruppen__liste { list-style: none; margin: 0 0 16px; padding: 0; display: grid; gap: 14px; }
.gb-gruppen__liste > li {
  padding-top: 12px; border-top: 1px solid var(--border); min-width: 0;
}
.gb-gruppen__liste > li:first-child { padding-top: 0; border-top: 0; }
.gb-gruppen__kopf { display: flex; flex-wrap: wrap; align-items: baseline; gap: 8px; }
.gb-gruppen__akt { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; align-items: center; }
.gb-gruppen__akt select { min-width: 0; max-width: 100%; }
.gb-gruppen__neu {
  display: flex; flex-wrap: wrap; gap: 10px; align-items: flex-end;
  padding-top: 14px; border-top: 1px solid var(--border);
}
.gb-gruppen__neu .field { flex: 1 1 220px; min-width: 0; }

/* --- «Dein Gebiet» — der Klartext-Streifen -------------------------------- */
/* Er steht im Vertriebsportal (#/vp) und im Vertriebs-Dossier. Eine Zeile,
   kein Kasten mit Ueberschrift: der Vertrieb soll seine Zusage LESEN, nicht
   eine Kachel deuten. */
.gb-zusage {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px 10px;
  margin: 0 0 16px; padding: 10px 14px;
  border: 1px solid var(--border); border-radius: var(--radius-card);
  background: var(--surface-inset); min-width: 0;
}
.gb-zusage__wort { font-size: 13px; color: var(--text-secondary); }
.gb-zusage__weiten {
  font-size: 14px; font-weight: 620; color: var(--text-primary); overflow-wrap: anywhere;
}
.gb-zusage--zu .gb-zusage__weiten { color: var(--text-tertiary); }

@media (max-width: 640px) {
  /* Eine Spalte, ganze Knoepfe. Auf 390 px steht jedes Auswahlfeld allein und
     jeder Griff ist ueber die volle Breite mit dem Daumen erreichbar. */
  .gb-karte { padding: 14px; }
  .gb-karte__kopf { flex-direction: column; align-items: flex-start; }
  .gb-form__felder { grid-template-columns: 1fr; }
  .gb-karte__akt > .ghost-btn,
  .gb-form__akt > .primary-btn,
  .gb-form__akt > .ghost-btn { flex: 1 1 100%; justify-content: center; }
  .gb-gruppen__akt > select,
  .gb-gruppen__akt > .ghost-btn,
  .gb-gruppen__neu > .ghost-btn { flex: 1 1 100%; }
  .gb-treffer { max-height: 208px; }
  .gb-treffer > li { flex: 1 1 100%; }
  .gb-treffer .ghost-btn { width: 100%; justify-content: space-between; }
}
/* ============================================================
   Patch-Integration — Namensraum zz (Zwei-Zahlen-Prinzip); Quelle: docs/design/patch-zweizahlen.css
   Der Block wird bei Integration als GANZES ersetzt, nie editiert.
   W12.1 «Das Zwei-Zahlen-Prinzip bei Impressionen» (Verlust 5): die
   Herkunfts-Unterzeile an jeder gezaehlten und jeder geschaetzten Zahl —
   Kundenbericht (#/k/berichte), Partner-Dossier, Kunden-Dossier.
   ============================================================ */
/* ============================================================
   W12.1 · Das Zwei-Zahlen-Prinzip — die Herkunft an der Zahl
   Namensraum: zz-
   Owner-Befund (Verlust 5): «Die Beschriftung ist die Grenze zwischen seriös
             und rechtlich angreifbar.»
   Gesetz:   docs/design/EINHEIT.md — 1.3 EIN Akzent, 1.6 kein Erklärtext unter
             dem Titel (die Herkunft steht unter der ZAHL, nicht unter der
             Überschrift), 4.3 jede Karte trägt ihr Element, 5.5 eine Kennzahl,
             ein Name, eine Einheit.
   Die EINE Sache, die dieser Block leistet: eine Zahl, die geschätzt ist,
             sieht anders aus als eine, die gezählt ist — und beide tragen
             sichtbar, woher sie kommen. Die Unterzeile ist Nebentext, kein
             zweites Etikett: die Marke oben sagt WAS, diese Zeile sagt WOHER.
   Warum kein eigener Farbakzent: die Marke («Gezählt»/«Geschätzt») trägt
             die Farbe schon. Zwei farbige Elemente an derselben Zahl wären
             ein zweiter Akzent (EINHEIT 1.3). Die Unterzeile bleibt Tertiärton;
             unterschieden wird über die Kante links, nicht über Farbe.
   Genutzt aus dem Bestand (NICHT neu definiert): --text-tertiary, --hairline,
             --warn-rgb, --accent-rgb.
   Integration: als Block ans Ende von public/style.css hängen.
   ============================================================ */

/* Die Herkunfts-Unterzeile. Sie steht IMMER da, wo die Zahl steht — nie in
   einer Fussnote, nie in einem Tooltip. Ein Kunde, der die Zahl abschreibt,
   soll die Herkunft mit abschreiben. */
.zz-herkunft {
  display: block;
  margin-top: 4px;
  padding-left: 8px;
  border-left: 2px solid rgba(var(--accent-rgb), .45);
  font-size: 11.5px;
  line-height: 1.45;
  color: var(--text-tertiary);
  /* Lange Herkunftssätze brechen um, statt die Karte zu sprengen. Auf 390 px
     ist das der Unterschied zwischen «steht da» und «läuft raus». */
  overflow-wrap: anywhere;
  text-wrap: pretty;
}

/* Geschätzt sieht nicht aus wie gezählt. Die Kante wechselt auf Bernstein und
   wird gestrichelt — dieselbe Sprache, die das Etikett am Partner-Dossier
   schon spricht (`.pd2-etikett--modell`). Nicht kräftiger, nur anders: eine
   Schätzung soll nicht auffälliger wirken als eine gezählte Zahl. */
.zz-herkunft--geschaetzt {
  border-left-style: dashed;
  border-left-color: rgba(var(--warn-rgb), .5);
}

/* In der Zwei-Zellen-Zeile des Dossiers sitzt die Unterzeile in einer Zelle
   mit knappem Raum — dort trägt sie keinen eigenen Einzug, sonst rückt sie
   gegen die Zellkante. */
.pd2-zwei__zelle > .zz-herkunft {
  margin-top: 6px;
  padding-left: 7px;
}

/* In der Berichtskarte folgt unter der Unterzeile noch die Formel (`.kb-fuss`).
   Ohne diesen Abstand kleben beide aneinander und lesen sich als ein Satz. */
.kb-karte > .zz-herkunft + .kb-fuss {
  margin-top: 8px;
  padding-top: 8px;
  border-top: 1px solid var(--hairline);
}

@media (max-width: 640px) {
  /* Auf dem Handy steht die Herkunft unter einer schon schmalen Zahl. Etwas
     kleiner, aber nie unter 11 px — sie ist Teil der Aussage, kein Kleingedrucktes. */
  .zz-herkunft { font-size: 11px; }
}

/* ============================================================
   Patch-Integration — Namensraum sig-pausen/sp-/mk-kachel__qr (Screens-Ordnung); Quelle: docs/design/patch-screens-ordnung.css
   ============================================================ */
/* W12.3/W12.5 «Screens-Ordnung» — Namensraeume .sig-pausen / .sp-* / .mk-kachel__qr

   Drei Dinge tragen diesen Block:
     1. «Screens pausieren» an der Signage-Flaeche — die Ortswahl nach
        Gesetz 13 (ganzer Kanton · ganzer Ort · einzelner Standort, mit Suche).
     2. Die zwei Griffe, die aus dem Versteck kommen: Bildschirm-Status und
        «Bildschirm hinzufuegen» an der Standort-Zeile, der Belegungskalender
        EINEN Tipp darunter.
     3. Die Zaehladresse an der Mediathek-Kachel — sie haengt seit W12.3 am
        Spot statt am Vergleichs-Kaestchen.
     Dazu die eine leise Zeile, ueber die der Owner noch an das versteckte
     Inventar kommt (Gesetz 19).

   KEINE NEUE FARBE, KEIN NEUER ABSTAND, KEIN LEUCHT-HOF. Alles kommt aus den
   Tokens (--surface-inset, --border, --text-primary/-secondary/-tertiary,
   --accent), Zustaende sind die bestehenden Chips, Knoepfe die bestehenden
   .primary-btn/.ghost-btn, die Trefferliste erbt die Proportionen von
   .gb-treffer (dieselbe Bauform, anderer Namensraum — components/orts-weite.js).

   HANDY ZUERST. Jede Reihe bricht um, jede Zelle traegt min-width: 0, jeder
   lange Ortsname bricht im Wort. Auf 390 px nimmt jeder Treffer die volle
   Breite: ein Knopf, den der Daumen verfehlt, ist keiner. */

/* --- 1) Screens pausieren -------------------------------------------------- */

/* Zugeklappt ist es EINE Zeile, kein Kasten: die Flaeche gehoert der Tafel,
   nicht der Pause (Grundgesetz 5, nicht ueberladen). */
.sig-pausen--zu {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px;
  margin-bottom: 16px; padding: 10px 14px;
  border: 1px solid var(--border); border-radius: var(--radius-card);
  background: var(--surface-inset); min-width: 0;
}
.sig-pausen--zu > span { font-size: 13px; color: var(--text-secondary); min-width: 0; }
.sig-pausen--zu > strong {
  margin-left: auto; font-size: 12.5px; font-weight: 620;
  color: var(--warn, var(--text-primary)); font-variant-numeric: tabular-nums;
}

.panel.sig-pausen { padding: 16px 20px; margin-bottom: 16px; }
.sig-pausen .panel__header { align-items: flex-start; gap: 10px; }

.sp-weiten { margin: 12px 0 0; flex-wrap: wrap; }

.sp-felder {
  display: grid; gap: 10px 14px; margin-top: 12px;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}
.sp-felder .field { min-width: 0; margin: 0; }

/* Die Trefferliste — gedeckelt hoch: wer scrollen muss, hat nicht gesucht. */
.sp-treffer {
  list-style: none; margin: 14px 0 0; padding: 0;
  display: flex; flex-wrap: wrap; gap: 8px;
  max-height: 168px; overflow-y: auto;
}
.sp-treffer .ghost-btn {
  display: inline-flex; align-items: baseline; gap: 8px; font-size: 13.5px;
  text-align: left; overflow-wrap: anywhere;
}
.sp-treffer .ghost-btn.is-gewaehlt {
  border-color: var(--accent); color: var(--accent-strong);
}
.sp-treffer__zahl { font-size: 12px; color: var(--text-tertiary); font-variant-numeric: tabular-nums; }

/* ENTFERNT, nicht ersetzt: .sp-leer — GEFALLEN 21.08.2026 — die Leer-Zeile des Hauses ist EINE Form:
   `.empty-state.empty-state--zeile` + `.empty-state__weg` in docs/design/grund.css.
   Sie war mit .gb-leer in patch-gebiete.css zeichengleich: zwei Blaetter,
   dieselbe Regel, zwei Namen. */

/* Nach der Wahl: was getroffen wird, wann, warum, und was das Geld macht. */
.sp-wahl {
  margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--border);
  min-width: 0;
}
.sp-wahl__satz {
  margin: 0; font-size: 14px; color: var(--text-secondary);
  overflow-wrap: anywhere;
}
.sp-wahl__satz strong { color: var(--text-primary); font-weight: 650; }
.sp-wahl > .field { margin-top: 12px; min-width: 0; }
.sp-gruende, .sp-modi { flex-wrap: wrap; }
.sp-akt { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 16px; }

/* Die Quittung. Sie sagt auch, was NICHT ging — und dann mit Namen. */
.sp-quittung {
  margin-top: 14px; padding: 12px 14px;
  border: 1px solid var(--border); border-radius: var(--radius-card);
  background: var(--surface-inset);
}
.sp-quittung.is-teil { border-color: var(--warn, var(--border)); }
.sp-quittung p { margin: 0 0 4px; font-size: 13px; color: var(--text-secondary); }
.sp-quittung p strong { color: var(--text-primary); }
.sp-quittung ul { margin: 0; padding-left: 18px; font-size: 13px; color: var(--text-secondary); }
.sp-quittung li { overflow-wrap: anywhere; }

/* Was gerade pausiert ist — und der Rueckweg daneben (W9.6: kein Zustand
   ohne Rueckweg). */
.panel.sp-laufen { padding: 16px 20px; margin-bottom: 16px; }
.sp-laufen h3 { margin: 0 0 10px; font-size: 15px; }
.sp-laufen ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.sp-laufen li {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: 6px 12px; padding-top: 8px; border-top: 1px solid var(--border); min-width: 0;
}
.sp-laufen li:first-child { padding-top: 0; border-top: 0; }
.sp-laufen li > span { font-size: 13px; color: var(--text-secondary); min-width: 0; overflow-wrap: anywhere; }
.sp-laufen li strong { color: var(--text-primary); font-weight: 620; }
.sp-laufen li em { font-style: normal; font-variant-numeric: tabular-nums; }

/* --- 2) Die Griffe an der Standort-Zeile ---------------------------------- */

.sig-loc__griffe {
  display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px;
}
.sig-loc__kalender:not(:empty) { margin-top: 10px; }

/* Der Status-Griff steht AM Bildschirm, nicht zwei Ebenen darunter. Er bleibt
   klein: er ist ein Griff in einer Zeile, keine Ueberschrift. */
.sig-screen__status { display: inline-flex; margin: 0; min-width: 0; }
.sig-screen__status select {
  height: 28px; padding: 2px 24px 2px 8px; font-size: 12.5px;
  min-width: 0; max-width: 148px;
}

/* --- 3) Die Owner-Ebene (Gesetz 19) --------------------------------------- */
/* Eine Zeile, leise, am Fuss. Sie ist der einzige benannte Weg zum
   versteckten Rechenwerk — und sie sieht aus wie eine Fussnote, weil sie
   eine ist. */
.sig-rechnung {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 10px;
  margin: 24px 0 0; padding-top: 14px; border-top: 1px solid var(--border);
  font-size: 12.5px; color: var(--text-tertiary); min-width: 0;
}
.sig-rechnung > a { font-weight: 620; color: var(--text-secondary); }
.sig-rechnung > a:hover { color: var(--text-primary); }
.sig-rechnung > span { min-width: 0; line-height: 1.55; }

/* --- 4) Die Zaehladresse an der Mediathek-Kachel -------------------------- */
/* Sie gehoert zu GENAU diesem Spot — darum steht sie in seiner Kachel und
   nicht am Kopf der Flaeche. */
.mk-kachel__qr {
  margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--border);
  display: grid; gap: 8px; min-width: 0;
}
.mk-kachel.is-qr-offen { border-color: var(--accent); }
.mk-kachel__qr .mk-stand__zeile {
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; min-width: 0;
}
.mk-kachel__qr .mk-stand__label {
  font-size: 12px; color: var(--text-tertiary); flex: 0 0 auto;
}
.mk-kachel__qr .mk-stand__code {
  font-size: 11.5px; overflow-wrap: anywhere; min-width: 0;
  color: var(--text-secondary);
}
.mk-kachel__qr .mk-stand__satz {
  margin: 0; font-size: 12px; color: var(--text-tertiary); line-height: 1.55;
}

/* --- 5) Der Vorrat des gemeinsamen Bausteins ------------------------------ */
/* components/orts-weite.js zeichnet ohne `klasse` in den Namensraum `ow-`.
   Er wird heute nirgends benutzt — steht aber da, damit eine kuenftige
   Flaeche nicht ungestylt startet und dafuer eine eigene Bauform erfindet.
   ENTFERNT, nicht ersetzt: `.ow-leer` — GEFALLEN 22.08.2026. Sie war die
   FUENFZEHNTE Leer-Bauart und die einzige, die nie ein Mensch geschrieben
   hat: orts-weite.js hat den Namen aus dem Namensraum des Aufrufers ERZEUGT
   (`gb-treffer` -> `.gb-leer`, `sp-treffer` -> `.sp-leer`, Vorgabe
   `ow-treffer` -> `.ow-leer`). Das Bauteil zieht jetzt die Leer-Zeile des
   Hauses (`.empty-state.empty-state--zeile`, grund.css); der Vorrat hier
   braucht darum keine eigene Leer-Regel mehr. */
.ow-treffer {
  list-style: none; margin: 14px 0 0; padding: 0;
  display: flex; flex-wrap: wrap; gap: 8px; max-height: 168px; overflow-y: auto;
}
.ow-treffer .ghost-btn { display: inline-flex; align-items: baseline; gap: 8px; font-size: 13.5px; }
.ow-treffer .ghost-btn.is-gewaehlt { border-color: var(--accent); color: var(--accent-strong); }
.ow-treffer__zahl { font-size: 12px; color: var(--text-tertiary); font-variant-numeric: tabular-nums; }

@media (max-width: 640px) {
  /* Eine Spalte, ganze Knoepfe. */
  .panel.sig-pausen, .panel.sp-laufen { padding: 14px; }
  .sig-pausen--zu { flex-direction: column; align-items: stretch; }
  .sig-pausen--zu > .ghost-btn { width: 100%; justify-content: center; }
  .sig-pausen--zu > strong { margin-left: 0; }
  .sp-felder { grid-template-columns: 1fr; }
  .sp-treffer { max-height: 208px; }
  .sp-treffer > li { flex: 1 1 100%; }
  .sp-treffer .ghost-btn { width: 100%; justify-content: space-between; }
  .sp-akt > .primary-btn { flex: 1 1 100%; justify-content: center; }
  .sig-loc__griffe > .ghost-btn { flex: 1 1 100%; justify-content: center; }
  .sig-screen__status { width: 100%; }
  .sig-screen__status select { max-width: none; width: 100%; }
  .sp-laufen li { flex-direction: column; align-items: flex-start; }
  .sp-laufen li > .ghost-btn { width: 100%; justify-content: center; }
  .ow-treffer > li { flex: 1 1 100%; }
  .ow-treffer .ghost-btn { width: 100%; justify-content: space-between; }
}

/* ============================================================
   Patch-Integration — Namensraum mk-pruef/material-file__pruef (Content-Moderation); Quelle: docs/design/patch-moderation.css
   ============================================================ */
/* W12.4 «Content-Moderation» — Namensraeume .mk-pruef / .mk-kachel__pruef /
   .material-file__pruef

   WAS DIESER BLOCK KLEIDET. Ein Spot in einem Coiffeursalon ist Aussenwirkung
   im Laden eines Dritten. Seit W12.4 traegt darum jede Spot-Version ihren
   Pruef-Zustand — «Wird geprueft» / «Freigegeben» / «Zurueckgewiesen: <Grund>»
   — und wer freigeben darf, hat den Griff dazu an der Kachel:
     1. Die Zustandszeile unter dem Dateinamen (Mediathek) und die zwei Zeichen
        an der Versionszeile (Werbematerial-Panel).
     2. Die aufklappbare Pruef-Karte AN der Kachel: angetippte Gruende, ein
        freiwilliges Feld, zwei Knoepfe, der Verlauf darunter.

   KEINE NEUE FARBE, KEIN NEUER ABSTAND, KEIN LEUCHT-HOF. Alles kommt aus den
   Tokens (--surface-2/-3, --border, --hairline, --text-primary/-secondary/
   -tertiary, --accent); die Zustaende sind die BESTEHENDEN Chips
   (.sl-badge--aktiv / --pipeline / --storniert), die Knoepfe die bestehenden
   .primary-btn / .ghost-btn. Die Pruef-Karte erbt die Proportionen von
   .mk-kachel__qr (dieselbe Bauform an derselben Kachel, anderer Inhalt) —
   damit stehen zwei aufgeklappte Griffe nie in zwei Formensprachen
   uebereinander.

   HANDY ZUERST. Auf 390 px stapelt sich jede Reihe, jede Zelle traegt
   min-width: 0, jede Tippflaeche misst mindestens 44 px. Die Gruende sind
   Chips, die umbrechen — kein waagerechtes Scrollfeld, in dem der letzte
   Grund unsichtbar bleibt. */

/* --- 1) Der Zustand als Wort, direkt unter dem Dateinamen ----------------- */
/* Sie steht ZWISCHEN Kopf und Kunde: was mit dem Spot ist, liest man vor dem
   Kunden und vor dem Format. Bei einer Zurueckweisung steht der Grund gleich
   daneben — eine Absage, die man erst aufklappen muss, ist ein Ausgang ohne
   Folge (Grundgesetz 2). */
.mk-kachel__pruef {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 8px;
  margin: 6px 0 0; min-width: 0;
}
.mk-pruef__grund {
  font-size: 12px; color: var(--text-secondary); line-height: 1.5;
  min-width: 0; overflow-wrap: anywhere;
}
.mk-pruef__seit {
  font-size: 12px; color: var(--text-tertiary);
  font-variant-numeric: tabular-nums;
}

/* --- 2) Die Pruef-Karte an der Kachel ------------------------------------- */
.mk-pruef {
  margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--border);
  display: grid; gap: 10px; min-width: 0;
}
.mk-kachel.is-pruef-offen { border-color: var(--accent); }
.mk-pruef__frage {
  margin: 0; font-size: 13px; font-weight: 620; color: var(--text-primary);
  line-height: 1.45;
}
.mk-pruef__bisher {
  margin: 0; font-size: 12px; color: var(--text-tertiary); line-height: 1.55;
  overflow-wrap: anywhere;
}

/* Antippen statt tippen (Grundgesetz 7). Die Chips brechen um; der gewaehlte
   traegt die Akzentkante, nicht eine Fuellfarbe — dieselbe Sprache wie
   .ow-treffer .ghost-btn.is-gewaehlt. */
.mk-pruef__gruende {
  display: flex; flex-wrap: wrap; gap: 6px; min-width: 0;
}
.mk-pruef__chip {
  appearance: none; cursor: pointer; text-align: left;
  background: var(--surface-3); color: var(--text-secondary);
  border: 1px solid var(--border); border-radius: var(--radius-badge);
  padding: 8px 12px; min-height: 44px; font-size: 12.5px; line-height: 1.35;
  min-width: 0; overflow-wrap: anywhere;
}
.mk-pruef__chip:hover { color: var(--text-primary); border-color: var(--hairline); }
.mk-pruef__chip.is-an,
.mk-pruef__chip[aria-pressed="true"] {
  border-color: var(--accent); color: var(--accent-strong);
  background: var(--surface-2);
}

.mk-pruef__frei { margin: 0; }
.mk-pruef__frei input { min-height: 44px; }

.mk-pruef__knoepfe {
  display: flex; flex-wrap: wrap; gap: 8px; min-width: 0;
}
.mk-pruef__knoepfe > button { min-height: 44px; }

.mk-pruef__satz {
  margin: 0; font-size: 12px; color: var(--text-tertiary); line-height: 1.55;
}

/* --- 3) Der Verlauf ------------------------------------------------------- */
/* Append-only im Server, hier eine schlichte Liste: was, wann, von wem, warum.
   Er ist der Nachweis, den eine Frage von aussen verlangt — darum steht er in
   der Karte und nicht in einem zweiten Fenster. */
.mk-pruef__verlauf {
  display: grid; gap: 6px; padding-top: 8px;
  border-top: 1px solid var(--border); min-width: 0;
}
.mk-pruef__liste {
  list-style: none; margin: 0; padding: 0; display: grid; gap: 8px;
  max-height: 168px; overflow-y: auto; min-width: 0;
}
.mk-pruef__liste li {
  display: grid; gap: 2px; font-size: 12px; line-height: 1.5; min-width: 0;
}
.mk-pruef__liste b { font-weight: 620; color: var(--text-secondary); font-size: 12.5px; }
.mk-pruef__liste span { color: var(--text-tertiary); font-variant-numeric: tabular-nums; }
.mk-pruef__liste i {
  font-style: normal; color: var(--text-secondary); overflow-wrap: anywhere;
}

/* --- 4) Dieselbe Wahrheit im Werbematerial-Panel -------------------------- */
/* Das Panel steht an der Buchung (#/v/material und Kunden-Detail). Es zeigt
   dieselben Woerter wie die Mediathek — eine Version, ein Zustand, ein Satz. */
.material-file__pruef { justify-self: start; }
.material-file__pruefgrund {
  grid-column: 1 / -1;
  margin: 2px 0 0; font-size: 12px; color: var(--text-secondary);
  line-height: 1.5; overflow-wrap: anywhere; min-width: 0;
}
.material-file__weisenbox { grid-column: 1 / -1; min-width: 0; }
.material-file__weisenbox .field { margin: 8px 0 0; }
.material-file__weisenbox input { min-height: 44px; }
.material-file__weisenzeile {
  display: flex; flex-wrap: wrap; gap: 8px; margin-top: 6px;
}
.material-file__weisenzeile > button { min-height: 44px; }
.material-file__freigeben,
.material-file__weisen { min-height: 44px; }

@media (max-width: 640px) {
  /* Eine Spalte, ganze Knoepfe — ein halber Knopf am Rand ist auf dem Handy
     kein Knopf. */
  .mk-pruef__knoepfe > button,
  .material-file__weisenzeile > button { flex: 1 1 100%; justify-content: center; }
  .mk-pruef__chip { flex: 1 1 100%; text-align: center; }
  .mk-pruef__liste { max-height: none; }
}

/* ============================================================
   Patch-Integration — Namensraum lx-demo (Demo-Bereich); Quelle: docs/design/patch-demo.css
   ============================================================ */
/* W13.1 «Der Demo-Bereich als Mandant» — Namensraum .lx-demo

   WAS DIESER BLOCK KLEIDET. Ein Band ueber der ganzen App, solange jemand im
   Demo-Bereich arbeitet. Gesetz 15.1 verlangt es woertlich: «Wer dort
   arbeitet, sieht jederzeit, dass er in der Demo ist.» Es haengt an
   document.body, nicht in einer Ansicht — ein Flaechenwechsel darf es nie
   wegnehmen.

   WARUM ES AUSSIEHT WIE DAS VORSCHAU-BAND — UND WARUM NICHT GANZ. Bauform,
   Hoehe, Rhythmus und der Weg hinaus rechts sind dieselben (style.css:13268,
   EINHEIT §3.1: eine Form fuer eine Sache). Die Farbe ist eine andere, weil es
   eine andere Aussage ist: das Vorschau-Band warnt («du siehst eine fremde
   Rolle, deine Rechte gelten weiter»), dieses Band stellt fest («nichts hier
   ist echt»). Es nimmt darum die Signalfarbe des Systems statt der Warnfarbe —
   ruhig, aber nicht zu uebersehen.

   NICHT KLEBEND. Zwei Elemente mit `position: sticky; top: 0` liegen beim
   Scrollen uebereinander (derselbe Befund wie beim Installations-Streifen,
   style.css:13294 ff.). Vorschau und Demo koennen gleichzeitig stehen — der
   Owner sieht die Kundenflaeche des Demo-Bereichs an. Das Demo-Band scrollt
   deshalb mit; sichtbar bleibt es trotzdem, weil jede Flaeche oben beginnt
   und `hat-demo` unten Platz schafft.

   KEIN LEUCHT-HOF. Owner-Befund 03.08.: die App hat kein «Glueh». Die Trennung
   nach unten ist eine 1px-Kante, kein weicher farbiger Schatten. */

.lx-demo {
  display: flex; align-items: center; justify-content: center; gap: 14px;
  flex-wrap: wrap;
  padding: 8px 16px;
  background: var(--accent-soft, rgba(18, 217, 211, .12));
  border-bottom: 1px solid var(--accent, #12d9d3);
  color: var(--text-primary);
  font-size: 12.5px; line-height: 1.3;
  letter-spacing: .01em;
}
.lx-demo__wort { font-weight: 650; }
.lx-demo__raus {
  padding: 6px 12px; min-height: 32px;
  border: 1px solid var(--accent, #12d9d3); border-radius: var(--radius-button);
  background: transparent; color: var(--text-primary);
  font: inherit; font-size: 12px; cursor: pointer;
}
.lx-demo__raus:hover { background: rgba(18, 217, 211, .12); }
.lx-demo__raus:disabled { opacity: .55; cursor: default; }

/* Am Handy: dieselbe Zeile, kleiner gesetzt — und der Weg hinaus behaelt seine
   44px, weil ein Knopf unter 44px am Daumen kein Knopf ist. */
@media (max-width: 900px) {
  .lx-demo { padding: 7px 12px; font-size: 12px; gap: 8px; }
  .lx-demo__raus { min-height: 44px; }
}
/* Der schmalste Fall (390px): das Wort darf umbrechen, der Knopf nimmt die
   ganze Breite. Nichts laeuft quer aus dem Bild. */
@media (max-width: 420px) {
  .lx-demo { flex-direction: column; align-items: stretch; text-align: center; }
  .lx-demo__raus { width: 100%; }
}

/* ============================================================
   Patch-Integration — Namensraum lx-recht (Personendaten löschen); Quelle: docs/design/patch-recht.css
   ============================================================ */
/* ── W13.3 · Personendaten löschen ───────────────────────────────────────────
   Eine Fläche, drei Ruhepunkte: suchen, vorschauen, vollziehen. Farben, Radien
   und Abstände kommen aus den Tokens — kein eigener Look, nur eine eigene
   Form. Der einzige Farbakzent liegt dort, wo er hingehört: auf der Liste
   dessen, was fällt, und auf dem Knopf, der es auslöst. */
.lx-recht__panel { margin-bottom: 16px; }

.lx-recht__suchfeld { display: flex; flex-direction: column; gap: 4px; margin-bottom: 10px; }
.lx-recht__suchfeld > span { font-size: 11.5px; color: var(--muted); }
.lx-recht__suchfeld > input {
  min-height: 44px; border: 1px solid var(--border); border-radius: var(--radius-card);
  background: var(--surface); color: var(--text-primary); padding: 0 10px;
  font-size: 14px; max-width: 100%;
}

.lx-recht__treffer { list-style: none; margin: 0 0 10px; padding: 0; }
.lx-recht__treffer > li + li { border-top: 1px solid var(--border); }
.lx-recht__treffer button {
  width: 100%; min-height: 44px; display: flex; align-items: center; gap: 10px;
  background: none; border: 0; cursor: pointer; padding: 8px 2px;
  color: var(--text-primary); text-align: left;
}
.lx-recht__name { font-size: 13.5px; font-weight: 600; min-width: 0; }
.lx-recht__ort { font-size: 12px; color: var(--muted); margin-left: auto; }

.lx-recht__vorschau {
  border: 1px solid var(--border); border-radius: var(--radius-card); padding: 12px 14px;
  background: var(--surface-2); display: flex; flex-direction: column; gap: 12px;
}
.lx-recht__wen { margin: 0; font-size: 13px; color: var(--muted); }

.lx-recht__liste > h3 { margin: 0 0 6px; font-size: 12px; color: var(--muted); font-weight: 620; }
.lx-recht__liste ul { list-style: none; margin: 0; padding: 0; }
.lx-recht__liste li {
  display: grid; grid-template-columns: 1fr auto; gap: 2px 10px;
  padding: 7px 0; border-top: 1px solid var(--border); min-width: 0;
}
.lx-recht__was { font-size: 13.5px; min-width: 0; overflow-wrap: anywhere; }
.lx-recht__zahl {
  font-size: 12.5px; color: var(--muted); font-variant-numeric: tabular-nums;
  white-space: nowrap; text-align: right;
}
.lx-recht__grund {
  grid-column: 1 / -1; font-size: 12px; color: var(--muted); overflow-wrap: anywhere;
}
.lx-recht__liste--faellt .lx-recht__was { color: var(--danger); }

.lx-recht__wiederkehr { margin: 0; font-size: 12px; color: var(--muted); }
.lx-recht__vollziehen { min-height: 44px; align-self: flex-start; }
.lx-recht__unwiderruflich { margin: 0; font-size: 12px; color: var(--muted); }
.lx-recht__vollzogen { margin: 0; font-size: 13px; }

.lx-recht__frist { align-items: flex-start; }
.lx-recht__fristwort { font-size: 13.5px; font-weight: 600; }
.lx-recht__gesetz { font-size: 12px; color: var(--muted); white-space: nowrap; }
.lx-recht__schalter {
  display: inline-flex; align-items: center; gap: 7px; min-height: 44px;
  font-size: 12.5px; color: var(--muted); cursor: pointer; white-space: nowrap;
}
.lx-recht__schalter input { width: 18px; height: 18px; }

.lx-recht__vollzuege { list-style: none; margin: 0; padding: 0; }
.lx-recht__vollzuege li {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 10px;
  padding: 7px 0; border-top: 1px solid var(--border);
}
.lx-recht__tag { font-size: 12.5px; font-variant-numeric: tabular-nums; }
.lx-recht__anlass { font-size: 12.5px; color: var(--muted); }
.lx-recht__vollzuege .lx-recht__zahl { margin-left: auto; }

/* 390 px: die Zahl rutscht unter den Text, statt die Zeile zu sprengen. */
@media (max-width: 430px) {
  .lx-recht__liste li { grid-template-columns: 1fr; }
  .lx-recht__zahl { text-align: left; }
  .lx-recht__vollziehen { align-self: stretch; }
}
/* ============================================================
   Patch-Integration — Namensraum vko (Verkaufs-Ordnung); Quelle: docs/design/patch-verkaufsordnung.css
   Der Block wird bei Integration als GANZES ersetzt, nie editiert.
   W14.0 · Geld-Zustand-Abzeichen (bezahlt/teilzahlung) + Sicht-Leiste
   (meine · alle · je Mitarbeiter · externer Vertrieb), Gesetze 21/22.
   ============================================================ */
/* ============================================================
   W14.0 · Die Verkaufs-Ordnung — Geld-Zustand + Sicht-Leiste
   Namensraum: vko-
   Owner-Diktat 11.08.2026 (Gesetze 21/22): die Offerte sagt ihren
   Geld-Zustand (bezahlt/teilzahlung/verrechnet als Abzeichen), und der
   Sehende filtert nach Person/Welt (meine · alle · je Mitarbeiter ·
   externer Vertrieb).
   Gesetz: docs/design/EINHEIT.md — 4.7 (kein farbiges Wort ohne Rahmen),
           1.3 (EIN Akzent), keine Leucht-Höfe (Owner 03.08.).
   Genutzt aus dem Bestand (NICHT neu definiert): --good-rgb/--good-strong,
           --warn-rgb/--warn-strong, --border, --line-strong, --accent-soft,
           --accent-line, --accent-strong, --text-primary/-secondary,
           --transition. Die Abzeichen erben .sl-badge, die Chips die
           Bauform von .vk-filter — kein zweiter Knopfstil.
   ============================================================ */

/* --- Gesetz 22: die zwei neuen Geld-Abzeichen. «Verrechnet» erbt das
       bestehende .so-badge--gesendet (Info), hier stehen nur die zwei neuen. --- */
.sl-badge.vko-badge--bezahlt {
  background: rgba(var(--good-rgb), .20);
  color: var(--good-strong);
  border-color: rgba(var(--good-rgb), .50);
  font-weight: 700;
}
.sl-badge.vko-badge--teil {
  background: rgba(var(--warn-rgb), .14);
  color: var(--warn-strong);
  border-color: rgba(var(--warn-rgb), .38);
}

/* Der offene Restbetrag als ruhiger Chip (die Zahl, die den nächsten Schritt
   trägt) — erbt .vk-chip, nur die Warnfarbe kommt dazu. */
.vk-chip.vko-chip--offen {
  color: var(--warn-strong);
  border-color: rgba(var(--warn-rgb), .35);
}

/* --- Gesetz 21.4: die Sicht-Leiste. Dieselbe Chip-Bauform wie .vk-filter,
       damit an Offerten und Kunden dieselbe Ordnung sichtbar ist. --- */
.vko-sicht {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  margin: 0 0 12px;
}
.vko-sicht__chip {
  display: inline-flex; align-items: center; height: 32px;
  padding: 0 12px; border-radius: var(--radius-badge); cursor: pointer;
  background: transparent; border: 1px solid var(--border);
  color: var(--text-secondary); font-family: inherit; font-size: 12px;
  font-weight: 600; white-space: nowrap;
  transition: background var(--transition), border-color var(--transition), color var(--transition);
}
/* DER GRIFF-BODEN GEHOERT DEM BAUTEIL, NICHT ZWEI FLAECHEN (07.09.2026).
   Er stand bis heute in patch-handy-verkauf.css und galt nur, wenn der Koerper
   `lx-offertenliste` oder `lx-kundenliste` hiess. Die dritte Flaeche, die
   dieses Bauteil benutzt — die Statistik (#/m/goals) — erbte damit 32-px-
   Chips: gemessen mit `node scripts/_jede_breite_test.mjs --nur=statistik`,
   «griff button.vko-sicht__chip — 61.8x32 px» auf 390, 430, 768 UND 1024.
   Eine Flaechen-Bindung ist hier falsch: `.vko-sicht__chip` ist kein geteiltes
   Grundbauteil wie `.stat`, es gehoert AUSSCHLIESSLICH dieser Leiste — und wo
   sie steht, muss der Daumen sie treffen. Der Block in patch-handy-verkauf.css
   ist damit entfallen (ersetzt, nicht danebengestellt). */
@media (max-width: 1080px), (pointer: coarse) {
  /* EINE Regel, und sie nennt die Griffe als Kinder der Leiste — nicht die
     drei Klassen ein zweites Mal. `.vko-sicht__chip`, `__mit` und `__select`
     stehen oben genau einmal; ein zweites Vorkommen derselben Klasse in
     diesem Blatt zaehlte `_stil_einmalig_test.mjs` als neue Doppelung
     (1034 -> 1036, der Auslieferer hielt am 07.09. 19:44 in 1y2 daran).
     Der Boden gilt dem Knopf, dem Etikett und der Auswahl darin. */
  .vko-sicht > button,
  .vko-sicht > label,
  .vko-sicht > label > select { min-height: 44px; }
}
.vko-sicht__chip:hover { color: var(--text-primary); border-color: var(--line-strong); }
.vko-sicht__chip.is-active {
  background: var(--accent-soft); border-color: var(--accent-line); color: var(--accent-strong);
}
.vko-sicht__mit {
  display: inline-flex; align-items: center; gap: 6px; height: 32px;
  padding: 0 8px 0 12px; border-radius: var(--radius-badge);
  border: 1px solid var(--border); color: var(--text-secondary);
}
.vko-sicht__mit.is-active { border-color: var(--accent-line); color: var(--accent-strong); }
.vko-sicht__mit-wort { font-size: 12px; font-weight: 600; white-space: nowrap; }
.vko-sicht__select {
  height: 30px; max-width: 170px; border: 0; background: transparent;
  color: inherit; font-family: inherit; font-size: 12px; cursor: pointer;
}
.vko-sicht__select:focus { outline: none; }

/* --- Am Handy: die Sicht-Leiste bleibt kompakt und die LETZTE Kachel füllt
       ihre Reihe, wenn sie sonst halb allein stünde. Dieselbe Abfrage, an der
       auch die Offerten-Fläche hängt (style.css).

       ZUERST STAND HIER `:nth-child(5)` — gezählt für genau fünf Kacheln.
       Seit dem 17.08. hat die Offertenliste eine SECHSTE, die nur erscheint,
       wenn wirklich etwas abgelaufen ist (`views/sales-offers.js`, «Abgelaufen»).
       Dann traf die Regel die fünfte von sechs, und die sechste stand halb
       allein in einer vierten Reihe — genau das Bild, gegen das die Regel
       geschrieben wurde. Am Handy (390 px) wuchs die Leiste dadurch beim
       Eintreffen der Daten von 155 auf 207 px und schob die ganze Liste um
       52 px nach unten: der Sprung, den das Skelett verhindern soll
       (`_ladezustand_test.mjs`, B2).
       `:last-child:nth-child(odd)` zählt nicht mehr mit — es fragt, ob die
       letzte Kachel allein bliebe. Fünf Kacheln: die fünfte füllt die Reihe
       (drei Reihen, wie bisher). Sechs Kacheln: keine muss (auch drei Reihen).
       Die Höhe hängt damit nicht mehr an der Zahl der Kacheln. --- */
/* DIE EINE ZEILE, Bauform Flex (04.09.2026): die Sicht-Chips brachen am
   Telefon in zwei Reihen um (102 px vor der ersten Offerte). Dieselbe Antwort
   wie beim Kennzahlen-Streifen (grund.css) — nur heisst der Rollweg hier
   `flex-wrap: nowrap`. `flex: 0 0 auto` ist tragend: ohne sie schrumpfen die
   Chips auf ihre Mindestbreite, statt zu rollen. */
@media (max-width: 640px) {
  .vko-sicht {
    flex-wrap: nowrap; overflow-x: auto;
    overscroll-behavior-x: contain; scrollbar-width: none;
  }
  .vko-sicht::-webkit-scrollbar { width: 0; height: 0; }
  .vko-sicht > * { flex: 0 0 auto; }
}
@media (max-width: 1080px), (pointer: coarse) {
  .vko-sicht { gap: 6px; margin-bottom: 8px; }
  .vko-sicht__select { max-width: 130px; }
  /* ENTFERNT 04.09.2026: `…:last-child:nth-child(odd) { grid-column: 1/-1 }`.
     Sie fragte, ob die letzte Kachel in einer ZWEISPALTIGEN Anordnung allein
     bliebe. Seit «DIE EINE ZEILE» (patch-handy-verkauf.css) gibt es am Handy
     keine zweite Reihe mehr, in der etwas allein stehen koennte. */
}
/* ============================================================
   Patch-Integration — Namensraum kalk (Kalkulator/Führung); Quelle: docs/design/patch-kalkulator.css
   Der Block wird bei Integration als GANZES ersetzt, nie editiert.
   W14.0 V3 · Vollkosten je Bildschirm gegen die Einnahmen (Gesetz 17).
   ============================================================ */
/* ============================================================
   W14.0 V3 · Der Kalkulator als Führungs-Instrument
   Namensraum: kalk-
   Owner-Diktat 11.08.2026 (Gesetz 17, Präzisierung 2026-08-11b):
   Vollkosten je Bildschirm gegen die Einnahmen — kein Widget, am
   Handy vollwertig bedienbar. Nur Layout; die Zahlen kommen aus
   sales_pnl_month / netz_stand (kein zweiter Finanzbereich).
   ============================================================ */
.kalk .admin-page__hint { max-width: 62ch; }

/* Vollkosten-Aufschlüsselung: eine Zeile = Wort links, Betrag rechts,
   Herkunft als Beisatz (gezählt aus Belegen · gleichmässig verteilt). */
.kalk-aufschluss { margin-top: 16px; }
.kalk-aufschluss > .panel__title { margin: 0 0 4px; }
.kalk-zeile {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 12px; padding: 7px 0; border-bottom: 1px solid var(--border);
}
.kalk-zeile:last-child { border-bottom: 0; }
.kalk-zeile__wort {
  display: inline-flex; align-items: baseline; flex-wrap: wrap; gap: 6px;
  min-width: 0; color: var(--text-secondary); font-size: 14px;
}
.kalk-zeile__wert {
  color: var(--text); font-weight: 600; white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.kalk-zeile--summe {
  border-top: 2px solid var(--line-strong); border-bottom: 0;
  margin-top: 2px; padding-top: 10px;
}
.kalk-zeile--summe .kalk-zeile__wort { color: var(--text); font-weight: 600; }
.kalk-zeile--summe .kalk-zeile__wert { font-size: 17px; }

/* Die Herkunft jeder Zahl — gezählt aus Belegen oder geschätzt (gleichmässig
   verteilt). Die Haftung hängt daran (Zwei-Zahlen-Kanon). */
.kalk-herkunft {
  font-size: 11px; font-weight: 600; line-height: 1.6; white-space: nowrap;
  padding: 0 8px; border-radius: var(--radius-badge);
  border: 1px solid var(--border); color: var(--text-tertiary);
}
.kalk-herkunft--geschaetzt {
  color: var(--warn-strong); border-color: rgba(var(--warn-rgb), .4);
  background: rgba(var(--warn-rgb), .12);
}

/* Die Grenze (Owner-Gate) — drei Sachverhalte (Bauteil `.sachverhalt`, grund.css),
   nicht mehr ein Absatz: gemessen · verteilt · nicht in den Daten. */
.kalk-grenze { margin-top: 16px; }

/* Standort-Tabelle: der Ort gedämpft neben dem Namen. */
.kalk-ort { color: var(--text-tertiary); font-size: 12px; }

/* Am Handy vollwertig: nichts läuft über die Kante, die Zeilen brechen sauber. */
@media (max-width: 720px), (pointer: coarse) {
  .kalk-zeile { gap: 4px 10px; }
}

/* ============================================================
   Patch-Integration — Namensraum lx-handy-verkauf; Quelle: docs/design/patch-handy-verkauf.css
   Der Block wird bei Integration als GANZES ersetzt, nie editiert.
   ============================================================ */
/* `.vk-kopf__akt` ist am 19.08.2026 gefallen: mit `sales-offers.js` trug die
   LETZTE Fläche ihren eigenen Kopf. Die Zeilen sind nicht gelöscht, sondern
   umgehängt — auf den Handgriff-Bereich des EINEN Seitenkopfs innerhalb der
   Marke `.vk-kopf`. So bleibt das Handy-Bild genau, wie es war, und es gibt
   trotzdem nur noch eine Hülle. */
/* ============================================================
   W14.0 V4 · Handy-Pass Verkauf
   Namensraum: lx-kundenliste / lx-rechnungen (+ geteilt mit lx-offertenliste)
   Owner-Diktat 11.08.2026 (OWNER-WUENSCHE Punkt 23, dritte Erwähnung):
   «Auf dem Smartphone funktioniert das sowieso null. Ganz schlimmes
   Verhalten. Nicht nur das, sondern ALLES: Offerten, Kunden. Alles sieht
   wieder overengineered aus auf dem Smartphone.»

   Die Offerten hatten ihren Handy-Pass schon (patch-offertenliste.css,
   body.lx-offertenliste): kein Titel im Kopf, Kacheln flach 2×2, Werkzeug-
   leiste weg, eigene Suchzeile. Kunden und Rechnungen trugen weiter die
   gestapelte Desktop-Seite: bei den Kunden stand die erste Karte erst bei
   650 px (gemessen 390×620), weil Kacheln (262 px) und eine 179-px-Filter-
   leiste den ganzen Bildschirm füllten; bei den Rechnungen war die Werk-
   zeugleiste ein vierzeiliger Stapel (228 px) und die erste Rechnung stand
   bei 588 px. Dazu drei Tapflächen unter 44 px (die Sicht-Chips 32 px, die
   Sortierauswahl 40 px). Nur Handy-Darstellung — was am Desktop steht,
   bleibt am Desktop; keine Fähigkeit wird entfernt, nur verdichtet.

   Die BREITE ist dieselbe, an der auch die Offerten-Fläche hängt
   (HANDY_ABFRAGE, sales-offers.js). Der Arm `(pointer: coarse)` steht hier
   weiter, weil ein Griff-Boden an jedem groben Zeigegerät gilt, auch auf
   1920 px, während ein Raster nach Breite gilt — «wie gross ist der Finger»
   gegen «wie breit ist der Bildschirm».

   WAS HIER STEHT UND WAS NICHT (nachgezogen 07.09.2026): Der Umbau der
   Fläche hängt an den Körper-Klassen, nie am geteilten `.vk`/`.vk-karte`/
   `.stat` — sonst träfe er die Kundenakte oder eine fremde Fläche ungeprüft
   mit. Ein Griff-BODEN dagegen gehört dem Bauteil und wohnt bei ihm: der
   Boden der Sicht-Leiste stand bis 07.09. hier (Block A, an zwei Körper-
   Klassen) und liess damit die dritte Fläche mit derselben Leiste — die
   Statistik — auf 32-px-Chips stehen. Er ist nach patch-verkaufsordnung.css
   an `.vko-sicht__chip` selbst gewandert; die Wirkung auf Offerten und
   Kunden ist unverändert, die Bedingung dieselbe.
   ============================================================ */
@media (max-width: 1080px), (pointer: coarse) {

  /* --- B) Kunden-Karten enger stellen --------------------------------------
     Am Telefon zählt jeder Millimeter: dieselbe Karte, weniger Rahmen um sie
     herum, damit mehr Arbeit in einen Bildschirm passt. Der Inhalt bleibt.
     NUR die Kundenkarte — die Offertenkarte hat ihre eigene, engere Handy-
     Fassung (style.css, `body.lx-offertenliste .vk-karte { padding: 9px 12px }`,
     Zeichen ausgeblendet); ein zweiter Padding-Wert hier hätte ihren
     Firmennamen beschnitten (verkauf:ui «nichts wird abgeschnitten»). */
  body.lx-kundenliste .vk-raster { gap: 8px; }
  body.lx-kundenliste .vk-karte { padding: 11px 13px; gap: 7px; }
  body.lx-kundenliste .vk-karte__akt .ghost-btn { min-height: 44px; }

  /* --- C) Kunden: die eigene kompakte Handy-Fassung ------------------------- */
  /* Reihenfolge wie bei den Offerten (03.09., Owner: «ich will ja OBEN
     einstellen, was will ich als erstes»): die Sicht-Leiste («wessen Vorgänge»)
     steht gleich unter dem Kopf, vor den Zahlen. `.vk` wird dazu eine Spalte;
     nur am Handy, nur an dieser Fläche. */
  body.lx-kundenliste .vk { display: flex; flex-direction: column; }
  body.lx-kundenliste .vk > .vk-kopf            { order: 1; }
  body.lx-kundenliste .vk > [data-slot="sicht"] { order: 2; margin-bottom: 6px; }
  body.lx-kundenliste .vk > [data-slot="kpis"]  { order: 3; }
  body.lx-kundenliste .vk > .vk-leiste          { order: 4; }
  body.lx-kundenliste .vk > [data-slot="table"] { order: 5; }

  /* Kopf: kein Titel (die Daumenleiste sagt «Kunden»), «Neu» kompakt rechts. */
  body.lx-kundenliste .vk-kopf {
    display: flex; align-items: center; margin-bottom: 8px; min-height: 0;
  }
  body.lx-kundenliste .vk-kopf h1 { display: none; }
  body.lx-kundenliste .vk-kopf .lx-seitenkopf__akt { width: auto; margin: 0 0 0 auto; }
  body.lx-kundenliste .vk-kopf .lx-seitenkopf__akt .primary-btn { min-height: 44px; white-space: nowrap; }

  /* ENTFERNT 04.09.2026 — ERSETZT durch «DIE EINE ZEILE» (unten). Hier stand
     die 2×2-Fassung der Kundenliste samt flacher Kachel. Dieselbe Falle wie
     bei der Offertenliste: `repeat(2, …)` wiegt schwerer als die Systemregel,
     die zwei ausdruecklichen Spalten wurden gequetscht, und die Probe meldete
     «schmalste 71px». Die Kachel ist jetzt an EINER Stelle flach. */

  /* Filterleiste kompakt: die Suche nimmt die volle Breite (Zeile 1), Filter
     und Sortierung fallen als flache 44-px-Chips darunter — statt eines
     179-px-Stapels. Das Wort «Sortieren:» fällt weg; Zeichen und Auswahl
     sagen dasselbe und sparen die Breite, die die Chips in eine Zeile bringt. */
  body.lx-kundenliste .vk-leiste { gap: 6px; margin-bottom: 10px; }
  body.lx-kundenliste .vk-suche { flex: 1 1 100%; max-width: none; min-height: 44px; }
  body.lx-kundenliste .vk-filter { min-height: 44px; padding: 0 11px; }
  /* Die Sortierung dehnt sich in der Flex-Leiste sonst auf volle Breite und
     bekäme eine eigene Zeile — schmal und gedeckelt teilt sie sich Zeile 2 mit
     den Filter-Chips (die Ränder brachten die drei sonst 2 px über die Kante). */
  body.lx-kundenliste .lst-ordnung { min-height: 44px; flex: 0 0 auto; max-width: 200px; }
  body.lx-kundenliste .lst-ordnung select { min-height: 44px; }
  body.lx-kundenliste .lst-ordnung__wort { display: none; }
  /* Der Zähler «5 von 5» fällt am Handy weg — die Karten stehen ja gleich
     darunter (gleiche Entscheidung wie bei den Offerten, deren Zähler in der
     am Handy ausgeblendeten Werkzeugleiste sitzt). So teilen sich Filter und
     Sortierung EINE Zeile: die Leiste ist zwei Zeilen statt drei. */
  body.lx-kundenliste .vk-zaehler { display: none; }

  /* --- D) Rechnungen: die eigene kompakte Handy-Fassung --------------------- */
  /* Ein Werkzeug erklärt sich nicht (EINHEIT.md 1.6) — der SCOR-Hinweis
     kostet am Telefon zwei Zeilen und sagt dem, der die Fläche kennt, nichts. */
  body.lx-rechnungen .admin-page__hint { display: none; }

  /* ENTFERNT 04.09.2026 — ERSETZT durch «DIE EINE ZEILE» (unten): Polsterung,
     Zahlgroesse und Fuge des KPI-Streifens stehen dort fuer JEDE Flaeche. */
  /* Der Zähler «5 von 5» fällt am Handy weg — die Rechnungen stehen darunter. */
  body.lx-rechnungen .sl-count { display: none; }

  /* Die Werkzeugleiste verdichten (war ein 228-px-Stapel aus vier Zeilen):
     flache Griffe, jeder ≥ 44 px, das Sortier-Wort weg. Und die REIHENFOLGE
     packt: Liste/Kanban und die Sortierung teilen sich Zeile 1, der
     Status-Filter steht darunter, die zwei Anlege-Knöpfe teilen die letzte
     Zeile. Liste/Kanban und der Status-Filter bleiben — nichts fällt weg. */
  body.lx-rechnungen .so-toolbar { gap: 6px; margin: 8px 0; }
  /* `min-width: 0` ist hier die tragende Zeile, nicht Kosmetik: die innere
     Reihe ist selbst ein Flex-KIND von `.so-toolbar` und traegt darum die
     Vorgabe `min-width: auto` — sie kann nicht unter ihre Inhaltsbreite
     schrumpfen. Gemessen am 18.08.: 477px in einem 342px breiten Kasten, und
     alles darin richtete sich nach den 477. Erst mit dieser Zeile gilt wieder
     die Breite des Bildschirms. */
  body.lx-rechnungen .so-toolbar__reihe { row-gap: 6px; min-width: 0; }
  /* `width: auto` und der 44-px-Boden gehoeren zu denselben Waehlern wie die
     Reihenfolge — EINE Regel je Waehler und Block (Doppel-Waechter). Die
     Begruendung fuer beides steht unten bei «DIE EINE ZEILE». */
  body.lx-rechnungen .so-toolbar [data-slot="view"]   { order: 1; width: auto; }
  body.lx-rechnungen .so-toolbar .lst-ordnung         { order: 2; min-height: 44px; }
  /* ENTFERNT 04.09.2026 — ERSETZT durch «DIE EINE ZEILE» (unten, Abschnitt 3).
     Hier zwang `flex: 1 0 100%` den Status-Filter in eine EIGENE Zeile. Das
     war am 18.08. die richtige Antwort auf ein anderes Problem (die Leiste
     wuchs auf 477 px und zog den Flex-Kasten mit, die Sortierung endete bei
     405 px auf einem 390er-Schirm). Der Rollweg loest beides zugleich: die
     Reihe rollt, statt zu wachsen ODER umzubrechen.
     GEMESSEN: mit dieser Regel blieb die Werkzeugleiste bei 224 px und die
     Probe «bleibt kompakt (<= 170px)» rot — die Systemregel kam nicht durch,
     weil `body.lx-rechnungen .so-toolbar [data-slot=…]` staerker wiegt. */
  /* DIE ZUSTAENDE STEHEN HINTER DEM GRIFF «FILTER» (05.09.2026, Runde 2).
     ------------------------------------------------------------------------
     WAS HIER STAND UND WARUM ES FAELLT — die Geschichte in drei Schritten:
       18.08.  Der Status-Filter bekam mit `flex: 1 0 100%` eine EIGENE Zeile,
               weil die Leiste sonst auf 477 px wuchs und die Sortierung bei
               405 px auf einem 390er Schirm endete.
       05.09.  Die eigene Zeile wurde ein ROLLWEG: sechs Zustaende messen
               nebeneinander 526 px in einem 362 px breiten Ausschnitt;
               umbrechend kosteten sie 94 px Hoehe und schoben die erste
               Rechnung auf 533 px hinunter, rollend nur 44 px. Der Kommentar
               nannte das einen «Owner-Entscheid: eine Zeile, die rollt».
       05.09.  DAS WAR EINE DEUTUNG, KEIN WORT DES EIGENTUEMERS. Sein Wort an
               diesem Tag lautet: «alles ueberlappend, kein Rendering … keine
               Einheitlichkeit, keine Symmetrie.» Gemessen an genau dieser
               Stelle: «Storniert» endete bei 435 px, «Ueberfaellig» bei 540 px
               — beide ausserhalb eines 390 px breiten Bildes, ohne Balken, der
               sagt, dass es weitergeht. Ein Rollweg ohne Balken sieht aus wie
               ein Fehler, und «Heute/Leads» beantwortet dieselbe Frage seit
               demselben Tag anders: die Regler wohnen hinter einem Griff
               «Filter». Zwei Antworten auf dieselbe Frage sind die fehlende
               Einheitlichkeit, die er meint.
     DER ENTSCHEID: Rechnungen bekommen am Telefon dieselbe Behandlung wie
     «Heute/Leads» — die Zustaende ziehen ins Blatt (views/sales-invoices.js,
     `filterBlatt`), und in der Werkzeugzeile steht ein Griff, der den
     geltenden Zustand traegt. Die Rechnung «44 px statt 94 px Hoehe» bleibt
     wahr: der Griff kostet gar keine Zeile, er teilt sie mit «Ansicht».
     Am Schreibtisch aendert sich nichts — dort steht die Reihe offen in der
     Leiste, wie seit dem 20.08. abgenommen.
     ------------------------------------------------------------------------
     EINE ZEILE, DREI DINGE: Ansichtswechsel · Ansicht · Filter. Gemessen auf
     390 px vor dem Umbau: Reihe 204 px (Liste/Kanban 160 + Sortierung 32) +
     Griff «Ansicht» 152 px = 356 von 362 px — voll, bevor der Filter da war.
     Darum wird der Ansichtswechsel enger gestellt, genau wie auf
     «Heute/Leads» (patch-telefon-griffe.css, `.ll-leiste .view-toggle__btn`):
     dieselbe Schrift, dasselbe Polster, dieselbe gesperrte Versalie. */
  /* ⚠️ DIESE ZEILEN STEHEN NICHT HIER, SONDERN IN EINEM EIGENEN 720er-BLOCK
     am Ende dieses Blattes («DIE TELEFON-ZEILE DER RECHNUNGEN»). Grund,
     gemessen am 05.09.2026: der Block, in dem dieser Kommentar steht, gilt
     `(max-width: 1080px), (pointer: coarse)` — also auch fuer die Tafel
     hochkant (768) und quer (1024). Dort gibt es den Griff «Filter» gar
     nicht (das Bauteil entscheidet bei 720 px, views/sales-invoices.js), und
     `flex: 1 1 0` an der Reihe zusammen mit `margin-left: auto` an den
     Ansichten liess die Reihe auf 8 px (768) bzw. 28 px (1024)
     zusammenfallen — ihre drei Kinder standen einzeln irgendwo in der Zeile
     und die Ansichten-Leiste lag darueber. Der Fehler war AELTER als dieser
     Umbau (auf dem unberuehrten Stand 2c5f3565 mit denselben Zahlen
     gemessen); er faellt mit dem Umzug in den 720er-Block. */
  /* `.view-toggle` steht am Handy sonst auf voller Breite (docs/design/grund.css,
     Scroll-Umschalter) — jedes Steuerelement bekäme damit eine eigene Zeile.
     Der Liste/Kanban-Umschalter darf hier schmal bleiben.
     05.09.2026, Runde 2: die Sortierung teilt diese Zeile NICHT mehr — sie
     liegt im Blatt hinter dem Griff «Filter» (unten). Die Waehler tragen
     darum `.so-toolbar__reihe` statt `.so-toolbar`: das Blatt haengt selbst in
     der Werkzeugleiste (der Griff muss beim Neuzeichnen stehen bleiben), und
     ein Waehler auf `.so-toolbar ` traefe die Auswahl IM Blatt gleich mit —
     dort ist sie breit, traegt ihr Wort «Sortieren:» und soll es behalten. */
  body.lx-rechnungen .so-toolbar__reihe .lst-ordnung { width: auto; flex: 0 0 auto; }
  body.lx-rechnungen .so-toolbar .view-toggle__btn { min-height: 44px; }
  body.lx-rechnungen .so-toolbar .lst-ordnung select { min-height: 44px; }
  body.lx-rechnungen .so-toolbar__reihe .lst-ordnung__wort { display: none; }
  /* Im Blatt nimmt die Auswahl die ganze Breite und steht unter den
     Zustaenden — dieselbe Anordnung wie die Felder im Blatt von
     «Heute/Leads» (patch-telefon-griffe.css, `.ll-blatt-filter`). */
  body.lx-rechnungen .lx-blatt__fach .lst-ordnung {
    display: flex; width: 100%; margin-top: 10px; min-height: 44px;
  }
  body.lx-rechnungen .lx-blatt__fach .lst-ordnung select { flex: 1 1 auto; min-width: 0; max-width: none; }
  /* ZWEI GRIFFE, EINE HOEHE (05.09.2026). «Rechnung aus Offerte» bricht auf
     390 px zweizeilig um und stand darum 10 px hoeher als «+ Freie Rechnung»
     daneben — zwei Kaesten, zwei Hoehen, genau das «keine Symmetrie» des
     Eigentuemers (Live-Bild 05.09.). `align-items: stretch` gibt beiden die
     Hoehe der hoeheren; das Wort wird nicht gekuerzt, keiner faellt weg. */
  body.lx-rechnungen .si-toolbar-actions { width: 100%; align-items: stretch; }
  body.lx-rechnungen .si-toolbar-actions .primary-btn,
  body.lx-rechnungen .si-toolbar-actions .ghost-btn { min-height: 44px; flex: 1 1 0; }
  /* DAS SUCHFELD NIMMT DIE VOLLE BREITE (05.09.2026) — wie auf der Kundenliste
     (Abschnitt C) und der Offertenliste. Es steht hier als einziges Kind
     ausserhalb einer Flex-Leiste (sales-invoices.js: `label.vk-suche` direkt in
     `.admin-page`), und `display: inline-flex` machte es so breit wie sein
     Inhalt: gemessen 272 px auf 390 px, mit 86 px Leere daneben. Die
     Flex-Regeln der Nachbarflaechen konnten es nicht erreichen — ein Kind ohne
     Flex-Eltern hat kein `flex`. */
  body.lx-rechnungen .admin-page > .vk-suche { display: flex; width: 100%; max-width: none; }
}


/* ============================================================
   DIE EINE ZEILE steht seit dem 04.09.2026 NICHT MEHR HIER
   ============================================================
   Sie stand einen halben Tag lang in diesem Blatt und wirkte — aber am
   falschen Ort: `.vk-kacheln`, `.panel.stat-strip`, `.vko-sicht` und
   `.so-toolbar__reihe` hatten damit je ZWEI Blaetter, und
   `npm run test:stil:einmalig` meldete «85 von 77» (acht Selektoren neu in
   einem zweiten Blatt). Der Waechter hatte recht: ein Bauteil hat EIN Blatt.

   Wo sie jetzt steht — je beim Bauteil, dem sie gehoert:
     docs/design/grund.css              «DIE EINE ZEILE» (`.stat-strip`)
                                        und `.so-toolbar__reihe` (ohne
                                        Geraeteblock, sie rollt immer)
     docs/design/patch-verkauf.css      `.vk-kacheln` im 640er-Block
     docs/design/patch-verkaufsordnung.css `.vko-sicht` im 640er-Block
   Damit gilt sie fuer JEDE Flaeche mit einem Kennzahlen-Streifen, nicht nur
   fuer die drei des Verkaufs — das war der Auftrag («System-Bauteil, nicht je
   Flaeche»). Was in diesem Blatt oben noch steht, sind echte Eigenheiten der
   drei Verkaufs-Flaechen (Filterleiste, Zaehler, Reihenfolge der Werkzeuge).
   ============================================================ */


/* ============================================================
   NUR AM TELEFON: DIE ORDNUNG GIBT NACH (05.09.2026)
   ============================================================
   Gemessen auf 390 px: Ansicht 160 px + Fuge 12 px + Ordnung 195 px = 367 px
   in einem 358 px breiten Kasten — die Sortierung stand 9 px draussen und die
   Reihe rollte. Mit `flex: 1 1 auto` nimmt sie den Rest der Zeile, ihre
   Auswahl kuerzt sich selbst (statt der 46vw aus patch-listen.css).

   ⚠️ WARUM DIESER EIGENE BLOCK UND NICHT DER 1080er OBEN: dort gilt die Regel
   auch fuer die Tafel (768 und 1024 px), und DORT steht in derselben Reihe
   zusaetzlich das Bauteil «gespeicherte Ansichten» (es faellt erst unter
   721 px weg, sales-invoices.js). Gemessen mit `node
   scripts/_jede_breite_test.mjs`: die Auswahl wurde auf 768 und 1024 px auf
   8 x 44 px gequetscht — genau der Defekt, den das Haus «unter 8 px auf einer
   Breite» nennt. Die Tafel behaelt darum ihre feste Breite und ihren Rollweg;
   nachgeben soll nur das Telefon, wo die Reihe wirklich zu eng ist.
   `.so-toolbar__reihe >` statt `.so-toolbar `: derselbe Waehler zweimal in
   einem Blatt waere eine Doppelung, und der Doppel-Waechter zaehlt sie. */
@media (max-width: 720px) {
  body.lx-rechnungen .so-toolbar__reihe > .lst-ordnung { flex: 1 1 auto; min-width: 0; }
  body.lx-rechnungen .so-toolbar__reihe > .lst-ordnung select {
    max-width: 100%; width: 100%;
    min-width: 56px; /* der Daumen-Riegel — Begruendung unten */
  }
  /* UND SIE DARF NICHT UNTER DEN DAUMEN FALLEN (05.09.2026, Runde 2).
     GEMESSEN am Tor, sobald «rechnungen» dort mitlaeuft: `select#si-sort
     42.3 x 44 px` auf 390 px, also unter dem 44-px-Boden des Hauses — und im
     eigenen Bild stand «Zuletz» statt «Zuletzt erstellt». Der Fehler ist
     aelter als der Umbau (vorher mass die ganze Umhuellung 32 px, die Auswahl
     darin noch weniger); er war nur nie gemessen, weil diese Flaeche nicht am
     Tor stand. Die Antwort ist nicht ein Mindestmass in einer zu engen Zeile,
     sondern der Umzug ins Blatt (oben) — dort ist die Auswahl 300 px breit
     und ihr Wort steht ganz da. Der Boden bleibt als Riegel fuer den Fall,
     dass jemand sie je wieder in die Zeile stellt. Der Wert (56 px) steht in
     der `select`-Regel oben — ein Waehler, eine Regel je Block. */
}


/* ===========================================================================
   DIE TELEFON-ZEILE DER RECHNUNGEN — Ansichtswechsel · Ansicht · Filter
   ---------------------------------------------------------------------------
   NUR 720 px, und das ist die tragende Zeile dieses Blocks: die Grenze, an der
   das Bauteil entscheidet, ob es einen Griff stellt oder die offene Leiste
   (`amTelefon()`, components/ansicht-wahl.js), ist 720. Standen dieselben
   Regeln im 1080er-Block darueber, griffen sie auf der Tafel hochkant (768)
   und quer (1024) mit — auf Breiten, auf denen es den Griff nicht gibt.
   GEMESSEN dort, vor der Trennung: `.so-toolbar__reihe` 8 px breit (768) bzw.
   28 px (1024), ihre drei Kinder verstreut ueber die Zeile, die
   Ansichten-Leiste (698 px) quer darueber. Auf 1280 px war dieselbe Leiste
   in Ordnung — der Unterschied war allein diese Medienabfrage.
   =========================================================================== */
@media (max-width: 720px) {
  body.lx-rechnungen .so-toolbar > [data-slot="view"] { flex: 0 0 auto; }
  body.lx-rechnungen .so-toolbar .view-toggle { padding: 2px; gap: 2px; }
  body.lx-rechnungen .so-toolbar .view-toggle__btn {
    flex: 0 0 auto; min-width: 44px; padding-inline: 4px;
    font-size: 12px; letter-spacing: .03em;
  }
  /* Die Reihe (Ansichtswechsel + Sortierung) nimmt, was sie braucht, und gibt
     nach, wenn es eng wird — die zwei Griffe rechts behalten ihre Breite.
     `min-width: 0` bleibt die tragende Zeile (Begruendung oben, 18.08.). */
  body.lx-rechnungen .so-toolbar__reihe { flex: 1 1 0; }
  /* Die zwei Griffe sitzen rechts aussen, dort, wo der Daumen ohnehin liegt —
     dieselbe Anordnung wie auf «Heute/Leads». `margin-left: auto` am ersten
     der beiden schiebt das Paar an den Rand. */
  body.lx-rechnungen .so-toolbar > [data-slot="ansichten"] {
    flex: 0 0 auto; min-width: 0; margin-left: auto;
  }
  body.lx-rechnungen .so-toolbar > [data-slot="filter-griff"] {
    flex: 0 0 auto; min-width: 0; display: flex; align-items: center;
  }
  /* Der Halter ist eine reine Klammer um Griff und Blatt (der Griff muss beim
     Neuzeichnen der Leiste stehen bleiben, sonst ginge das offene Blatt mit).
     `display: contents` loest ihn im Bild auf: der Griff ist damit selbst das
     Kind der Zeile, und es entsteht kein zweiter Kasten mit eigener Breite.
     Das Blatt darin liegt ohnehin `fixed` ueber der Seite. */
  body.lx-rechnungen .si-filtergriff { display: contents; }
  /* Der Name der Ansicht darf kuerzen — er steht vollstaendig im Blatt, das
     der Griff oeffnet (`griffWort` faellt dann auf «Ansicht» zurueck). Die
     Sortierung daneben darf das nicht: eine Auswahl von 25 px ist keine
     Auswahl mehr. Darum eine Obergrenze fuer den Namen, keine fuer sie. */
  body.lx-rechnungen .so-toolbar .aw-griff { flex: 0 1 auto; max-width: 30vw; }
  /* Dieselbe Schrift und dasselbe Polster wie die Griffe auf «Heute/Leads»
     (patch-telefon-griffe.css, `.ll-leiste .lx-griff`) — gleiche Dinge sehen
     ueberall gleich aus, und die 12 px sind hier die Rechnung, die die vier
     Bedienteile in EINE Zeile bringt. */
  body.lx-rechnungen .so-toolbar .lx-griff {
    font-size: 12px; padding-inline: 6px; letter-spacing: .04em;
  }
}

/* ============================================================
   DIE WERKZEUGZEILE DER RECHNUNGEN BRICHT UM, STATT WEGZUROLLEN
   (Pruefer-Fund R2-F1, 05.09.2026)
   ============================================================
   GEMESSEN auf der Fundament-Buehne, `.so-toolbar__reihe` je Breite
   (client/scroll, eigene Messung des Pruefers):
     390 px   221/221    passt (Telefon-Bauart: Liste|Kanban + Griff «Filter»)
     430 px   261/261    passt
     768 px   712/974    262 px fehlen — «Kanban» lief von 668 bis 753 px
                         gegen einen Rand bei 740: das Wort ist MITTEN
                         DURCHGESCHNITTEN, und «Sortieren» steht ganz
                         ausserhalb des Bildes.
    1024 px   732/974    242 px fehlen — die Sortierung ist nur nach
                         seitlichem Rollen erreichbar, ohne Balken, ohne
                         Hinweis (iPad quer, eine der neun Geraetebreiten).
    1280 px   980/1006    26 px fehlen — der rechte Rand der Auswahl faellt weg.
    1366 px  1006/1006   passt.
   Drei der neun Geraetebreiten des Hauses also, und auf 768 px sieht der
   Eigentuemer genau das, was er am 05.09. beklagt hat: «alle Texte, Balken,
   alles ueberlappend … alles billige Ware».

   WARUM UMBRUCH UND NICHT DER GRIFF «FILTER» AUCH HIER: Das Griff-Vokabular
   (`.lx-griff`, `.lx-blatt-wirt`) lebt in `@media (max-width: 720px)`
   (patch-telefon-griffe.css). Ein Griff auf 768 px waere unbekleidet und sein
   Blatt bliebe `display: none` — ein Knopf, der sichtbar ist und nichts tut.
   Der Umbruch braucht kein neues Vokabular und keine Zahl: `flex-wrap: wrap`
   MISST selbst. Wo die Zeile passt (1366 px und darueber), bleibt sie eine
   Zeile und am Schreibtisch aendert sich kein Pixel; wo sie nicht passt,
   steht die zweite Reihe darunter statt hinter dem Rand. Die Nachbarliste
   «Kunden» traegt auf 768 px laengst mehrere Reihen (Umfang · Suche ·
   Ordnung · Ansicht) — gleiche Dinge sehen ueberall gleich aus.

   `overflow-x: auto` aus grund.css bleibt stehen: es ist der Notausgang,
   wenn ein EINZELNES Kind breiter ist als die Zeile (dann kann nichts
   umbrechen). Umbrechen kommt zuerst, Rollen bleibt der Rest.
   Beweis: scripts/_handy_verkauf_ui_test.mjs, Block «Werkzeugzeile bricht um»
   (768 · 1024 · 1280 · 1366 px, mit Gegenprobe). */
@media (min-width: 721px) {
  body.lx-rechnungen .so-toolbar__reihe { flex-wrap: wrap; row-gap: 8px; }
}

/* ============================================================
   Patch-Integration — Namensraum lx-ort/lx-suchzeile/bs- (Ortsschild, Bereiche, Bereichs-Start); Quelle: docs/design/patch-ortsschild.css
   ============================================================ */
/* =========================================================================
   Patch «Ortsschild · Bereiche · Bereichs-Start» — Welle 17.08.2026, Paket 1.
   Gehört als Block ans ENDE von public/style.css (nach dem Basis-Block, sonst
   greift kein Handy-Override — Memory project_css_cascade_mobile).
   Angehängt wird er ausschliesslich über
   `scripts/_naht_ortsschild_stil_anhaengen.mjs`, nie von Hand.

   Präfixe: lx-ort- (Ortsschild), lx-suchzeile (der ⌘K-Griff am Handy),
   bs- (Bereichs-Start). Farben, Radien und Abstände kommen ausschliesslich
   aus den Fundament-Tokens (style.css:29 ff.) — hier steht kein roher Hex.

   Owner-Klage, wörtlich: «man weiss nicht, wo was ist» · «man findet eine
   Funktion und dann nie wieder». Das Gesetz dazu: docs/BEREICHE.md §1, §3, §4.
   ========================================================================= */

/* --- 1 · Das Ortsschild (BEREICHE §3) -------------------------------------
   Es steht OBEN IN DER FLÄCHE, nicht in der Kopfzeile — so macht es die
   Owner-Referenz (`Portaluikomplett/ChatGPT Image 29. Juli 2026,
   13_25_57 (4).png`: «Partner › A.I.O. Ebikon GmbH … › VP-0001» über dem
   Titel, im Inhalt). Der Halter liegt zwischen der Reiterzeile und
   `#app-view`, also ausserhalb der Fläche, die ein View-Render neu schreibt,
   und optisch trotzdem in ihr. */
.lx-ort-halter { margin: 0 0 10px; }
.lx-ort-halter[hidden] { display: none; }
.lx-ort {
  /* `nowrap` seit dem 04.09.2026, gemessen statt gemeint: mit `wrap` brach
     das Schild bei einem langen Namen auf zwei Zeilen (44 -> 69 px), OBWOHL
     die Ellipse am letzten Glied schon griff. Flexbox bricht naemlich ZUERST
     um und schrumpft erst danach — ein Glied mit grosser Grundbreite geht auf
     eine eigene Zeile, statt sich kappen zu lassen. Ein Ortsschild ist eine
     Zeile (BEREICHE §3); der Ueberhang gehoert in die «…» des letzten
     Glieds, nicht in eine zweite Zeile. */
  display: flex; align-items: center; flex-wrap: nowrap; gap: 7px;
  font-size: 12.5px; color: var(--text-tertiary);
  min-width: 0;
}
/* EINE ZEILE, AUCH BEI EINEM LANGEN NAMEN (04.09.2026).
   GEMESSEN auf dem Wegweiser, 390 px: mit «Wache Muster Gebaeudereinigung und
   Facility Services AG Zweigniederlassung Bern» im letzten Glied wuchs das
   Schild von einer Zeile auf 88 px — drei Zeilen, die alles darunter nach
   unten schoben. Ein Ortsschild ist eine ZEILE (BEREICHE §3, Referenz
   13_25_57 (4)); waechst es, ist es kein Schild mehr.

   WAS HIER BEWUSST NICHT STEHT: `overflow: hidden` auf `.lx-ort__glied`.
   Der Weg-Glied-Anker IST ein Glied und traegt `position: relative` fuer
   seine unsichtbare Fangflaeche (`::after`, left/right -5px, der 44-px-Fix
   vom 26.08.). Ein `overflow: hidden` an derselben Stelle wuerde genau diese
   Fangflaeche beschneiden — die Regel haette den Finger-Boden still
   zurueckgenommen. Darum:
     nowrap        an JEDEM Glied      -> nichts bricht um
     0 0 auto      am Weg              -> die kurzen Ortswoerter schrumpfen nie
     Ellipse       am letzten Glied    -> der lange Name gibt nach, mit «…»
   Das letzte Glied ist ein `<span>` ohne Fangflaeche; dort ist das Kappen
   gefahrlos, und es ist das EINZIGE Glied mit veraenderlicher Laenge. */
.lx-ort__glied { min-width: 0; white-space: nowrap; }
/* Regel 2: jedes Glied ausser dem letzten ist ein WEG. */
.lx-ort__weg {
  color: var(--text-secondary); text-decoration: none;
  border-radius: var(--radius-button);
  transition: color var(--dur-fast) var(--ease);
}
/* DIE TAPFLÄCHE OHNE DIE HÖHE (Muster: patch-pool.css «pool-weg»). Am Rechner
   ist ein Glied 18.8 px hoch — unter dem Maus-Boden 24. Das Schild SOLL dort
   die schmale Zeile der Referenz bleiben (Regel im Block darunter), also
   wächst nicht die Zeile, sondern die Fangfläche: mittig, unsichtbar, dem
   Weg selbst gehörend. Am Finger trägt er ohnehin 44 px echte Höhe — dort ist
   das Kästchen die kleinere Zahl und ändert nichts. */
.lx-ort__weg { position: relative; flex: 0 0 auto; }
/* Und dieselbe Fangfläche trägt die BREITE. Gemessen 26.08.2026: «Heute» ist
   35.2 px breit, der Finger-Boden 44 — es fehlten 8.8 px. Die naheliegende
   Antwort (das Wort auf 44 px aufblasen) macht aus einer Textzeile ein
   Knopfband und lässt die Nachbarglieder aneinander stossen. Fünf Pixel je
   Seite genügen (45.2 px) und bleiben INNERHALB des Abstands: zwischen zwei
   Wegen steht immer ein Pfeil, also 6 px + Pfeil + 6 px. Das ferne Glied
   («Betrieb», 42.4 px) fehlten ohnehin nur 1.6. */
.lx-ort__weg::after {
  content: ""; position: absolute; left: -5px; right: -5px; top: 50%;
  height: 24px; transform: translateY(-50%);
}
.lx-ort__weg:hover { color: var(--accent-strong); }
.lx-ort__weg:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.lx-ort__glied--hier {
  color: var(--text-primary); font-weight: 600;
  overflow: hidden; text-overflow: ellipsis;
}
.lx-ort__pfeil { color: var(--text-tertiary); }

/* Grundgesetz 6: jede Bedienfläche hält 44px. Ein Ortsschild ist Bedienung —
   es ist der Rückweg. Am Rechner bleibt es die schmale Zeile der Referenz.
   DIESER Block steht VOR dem Handy-Block darunter, und das ist kein Zufall:
   `display: inline-flex` und `display: none` haben dieselbe Spezifität, also
   entscheidet die Reihenfolge. Stünde er danach, machte er die weggeblendeten
   Glieder wieder sichtbar — genau das ist beim ersten Lauf passiert und vom
   Wächter gefunden worden, bevor ein Bild entstand. */
/* 26.08.2026: die Grenze lief bei 900 px — und 1024 ist eine FINGER-Breite
   (geraete-masse.mjs). Dort fiel der Rückweg genau zwischen die Stühle: zu
   breit für die 900er-Regel, zu grob für die Maus. Dieselbe Bruchzone wie in
   patch-zug.css und grund.css §D-03 (Memory project_tablet_touch_breakpoint).
   Der Zeiger entscheidet, nicht der Bildschirm. */
@media (max-width: 1024px), (pointer: coarse) {
  .lx-ort__weg { display: inline-flex; align-items: center; min-height: 44px; }
  .lx-ort { gap: 6px; }
}
/* Regel 4: am Handy trägt das Schild nur die LETZTEN ZWEI Glieder; das erste
   steht in der Leiste am Daumen. Das entscheidet das CSS und nicht JS — sonst
   wäre jedes Drehen des Geräts ein Neubau. */
@media (max-width: 640px) {
  .lx-ort__glied--fern, .lx-ort__pfeil.lx-ort__glied--fern { display: none; }
}

/* …UND DIE ZWEITE HÄLFTE DERSELBEN REGEL, gemessen statt gemeint.
   §3.4 sagt, das erste Glied stehe am Handy «in der Leiste am Daumen». Genau
   dort steht es auch — und der aktive Reiter darüber sagt das zweite. Ein
   Schild, das nur diese beiden Wörter wiederholt, kostet am Handy 54 px und
   sagt nichts Neues. Gemessen am Pool (`scripts/_pool_ui_test.mjs`, 390×620):
   der Rahmen über der ersten Karte sprang damit von 201 auf 255 px — über die
   Ein-Drittel-Grenze, die aus dem Owner-Befund «der Inhalt begann erst bei 650
   von 844 px» entstanden ist.
   Es weicht darum genau dann, wenn ein anderes SICHTBARES Element dasselbe
   schon sagt: wenn die Reiterzeile steht UND das Schild kein drittes Glied
   trägt (kein `--fern` heisst: höchstens zwei Glieder). Eine AKTE behält ihr
   Schild immer — ihr letztes Glied ist der Name dieses einen Dings, und den
   sagt keine Leiste. Fehlt die Reiterzeile (eine Tür mit nur einem Punkt),
   bleibt das Schild ebenfalls stehen: dann ist es das Einzige, was den Ort
   nennt. */
@media (max-width: 900px) {
  body:has(#subnav:not([hidden])) #lx-ort:not(.lx-ort-halter--return):not(:has(.lx-ort__glied--fern)) { display: none; }
}

/* --- 2 · Der Griff zur einen Suche unter 900px ----------------------------
   Gemessen: unterhalb dieser Breite blendet style.css `.lx-top__suche` aus
   (der Handy-Kopf trägt bewusst keine Werkzeugleiste, Owner-Entscheid 08.08.
   am Referenzbild). Damit hatte ⌘K am Handy und am Tablet KEINEN Griff mehr —
   und die 18 Ziele, die nur dort stehen, waren unauffindbar. Die Zeile wohnt
   im Fach hinter «Mehr», bei den Schnellaktionen. Am Rechner ist sie aus:
   dort trägt der Kopf die Suche, und zwei sichtbare Wege wären EINHEIT §3.1. */
.lx-suchzeile { display: none; }
@media (max-width: 900px) {
  .lx-suchzeile {
    display: flex; align-items: center; gap: 9px; width: 100%;
    min-height: 44px; padding: 10px 12px; margin: 0 0 10px;
    border: 1px solid var(--line); border-radius: var(--radius-button);
    background: var(--surface-inset); color: var(--text-secondary);
    font: inherit; font-size: 13.5px; text-align: left; cursor: pointer;
  }
  .lx-suchzeile:hover { border-color: var(--line-strong); color: var(--text-primary); }
  .lx-suchzeile__ic { display: inline-flex; flex: none; width: 16px; height: 16px; }
  .lx-suchzeile__ic svg { width: 16px; height: 16px; }
  .lx-suchzeile__wort { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .lx-suchzeile__kbd {
    flex: none; font-family: var(--font-mono); font-size: 11px;
    color: var(--text-tertiary); border: 1px solid var(--line);
    border-radius: var(--radius-card); padding: 1px 5px;
  }
}

/* --- 3 · Der Bereichs-Start (BEREICHE §4) ---------------------------------
   Ortsschild + Name · Kennzahlen-Streifen (jede Zahl eine Tür) · «Was wartet»
   (Zeilen mit je einem Knopf) · die Wege. Nichts sonst. */
.bs-kopf { margin-bottom: 18px; }
.bs-kopf__wer { display: flex; align-items: flex-start; gap: 14px; }
/* Der Name bleibt auf JEDER Breite stehen. `.page-head` blendet ihren Titel am
   Handy aus (er wiederholte dort den aktiven Reiter) — auf einem Bereichs-Start
   ist der Name aber der Inhalt, nicht die Wiederholung. */
.bs-kopf h1 {
  margin: 0; font-size: 26px; font-weight: 650;
  letter-spacing: -.02em; color: var(--text-primary);
}
.bs-kopf__satz { margin: 4px 0 0; color: var(--text-secondary); font-size: 13.5px; }

/* Das Symbol-Quadrat im Ton des Bereichs. Die Farbe gehört dem BEREICH, nicht
   dem Ort — dieselbe Regel und dieselben Töne wie in der Zentrale
   (`--gz-…`). Die zwei neuen Bereiche bekommen die zwei Töne, die
   mit der Auflösung von «Aussenpartner» frei geworden sind.

   DIE ACHT TOENE STEHEN SEIT 25.08.2026 IM FUNDAMENT (docs/design/grund.css,
   `:root`) — zeichengleich uebernommen, keine Farbe geaendert. Sie hingen
   bis heute an `.bs` und galten damit ausschliesslich auf den sechs
   Bereichs-Starts; jede andere Flaeche des Bereichs kannte ihre eigene Farbe
   nicht. Was hier bleibt, ist der Rueckfall und die Zuordnung. */
.bs {
  --bs-feld: var(--tint-rgb);
}
.bs .bs-ic--zentrale          { --bs-feld: var(--bs-zentrale); }
.bs .bs-ic--akquise           { --bs-feld: var(--bs-akquise); }
.bs .bs-ic--verkauf           { --bs-feld: var(--bs-verkauf); }
.bs .bs-ic--betrieb           { --bs-feld: var(--bs-betrieb); }
.bs .bs-ic--standortbetreiber { --bs-feld: var(--bs-standortbetreiber); }
.bs .bs-ic--vertriebspartner  { --bs-feld: var(--bs-vertriebspartner); }
.bs .bs-ic--team              { --bs-feld: var(--bs-team); }
.bs .bs-ic--finanzen          { --bs-feld: var(--bs-finanzen); }

/* DER ORT FAERBT DIE FLAECHE — sparsam, und nur dort, wo EINHEIT §1.3 es
   erlaubt: im Soft-Feld hinter einem Symbol. `components/ortsschild.js`
   schreibt seit 25.08. bei JEDEM Flaechenwechsel `data-bereich="<key>"` an
   `#app-view` (dieselbe eine Stelle, die schon das Ortsschild zeichnet — ein
   Seitenkopf koennte es nicht, er vererbt nur an seine eigenen Kinder, nicht
   an die Flaeche daneben). Diese sieben Zeilen uebersetzen den Bereichs-
   Schluessel in den Ton, der fuer ihn laengst entschieden ist. `verkauf`
   fehlt hier mit Absicht: der Schluessel steht schon in patch-zentrale.css
   (Sach-Tabelle) und traegt dort denselben Wert — zwei Blaetter duerfen sich
   nicht denselben Selektor teilen (scripts/_stil_einmalig_test.mjs).
   `einstellen` bekommt bewusst KEINEN Ton: fuer ihn ist keiner entschieden,
   und eine erfundene Farbe waere genau das, was hier nicht passieren darf —
   sein Symbol bleibt im Tuerkis des Hauses. */
[data-bereich="zentrale"]          { --gz-feld: var(--bs-zentrale); }
[data-bereich="akquise"]           { --gz-feld: var(--bs-akquise); }
[data-bereich="betrieb"]           { --gz-feld: var(--bs-betrieb); }
[data-bereich="standortbetreiber"] { --gz-feld: var(--bs-standortbetreiber); }
[data-bereich="vertriebspartner"]  { --gz-feld: var(--bs-vertriebspartner); }
[data-bereich="team"]              { --gz-feld: var(--bs-team); }
[data-bereich="finanzen"]          { --gz-feld: var(--bs-finanzen); }
.bs-ic {
  display: grid; place-items: center; flex: none;
  width: 38px; height: 38px; border-radius: var(--radius-card);
  color: rgb(var(--bs-feld)); background: rgba(var(--bs-feld), .13);
}
.bs-ic svg { width: 19px; height: 19px; }

.bs-zahlen { margin-bottom: 18px; }
.bs-kachel .bs-ic { width: 30px; height: 30px; border-radius: var(--radius-card); }
.bs-kachel .bs-ic svg { width: 16px; height: 16px; }

/* «Was wartet» — nicht «5 überfällig», sondern die fünf, jede mit ihrer
   nächsten Handlung. */
.bs-liste { list-style: none; margin: 0; padding: 0; }
.bs-zeile {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; flex-wrap: wrap;
  padding: 11px 0; border-top: 1px solid var(--line);
}
.bs-zeile:first-child { border-top: 0; }
.bs-zeile__wer { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.bs-zeile__wer b { color: var(--text-primary); }
.bs-zeile__satz { color: var(--text-secondary); font-size: 12.5px; }
.bs-zeile--dringend .bs-zeile__satz { color: var(--bad-strong); }
.bs-zeile__knopf { flex: none; min-height: 44px; display: inline-flex; align-items: center; }
.bs-liste__mehr { margin: 10px 0 0; color: var(--text-tertiary); font-size: 12.5px; }
/* «Was wartet» beginnt als FRAGE-KOPF über den Kennzahlen (03.09.): die
   dringendste Zeile ist die Hauptsache des Bereichs, ihr Knopf die eine
   Hauptaktion. Das Kleid ist .panel.frage-kopf (grund.css); hier nur der Rest. */
.bs-frage { margin-bottom: 18px; }
.bs-frage__was { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.bs-frage__satz { font-size: 13px; font-weight: 400; color: var(--text-secondary); }
.bs-frage--dringend .bs-frage__satz { color: var(--bad-strong); }
/* «Leer heisst: ein ruhiger Satz, kein leerer Rahmen» (BEREICHE §4.3).
   Bis zum 18.08. trug diese Klasse den vollen Leerzustand (Symbolring +
   Überschrift + Text) — auf 390px gemessene 250 von 844 Pixeln für die
   Auskunft, dass nichts zu tun ist. Jetzt ist sie, was der Satz verlangt:
   eine Zeile. */
.bs-ruhig {
  margin: 2px 0 0; color: var(--text-secondary); font-size: 13.5px;
}

/* Die Wege — die Listen des Bereichs, je mit einem Satz, was man dort tut. */
.bs-wege__liste { display: grid; gap: 2px; }
.bs-weg {
  display: grid; grid-template-columns: 1fr auto; align-items: center;
  gap: 4px 12px; padding: 12px 0; min-height: 44px;
  border-top: 1px solid var(--line); text-decoration: none;
}
.bs-wege__liste > .bs-weg:first-child { border-top: 0; }
.bs-weg__wort { color: var(--text-primary); font-weight: 600; }
.bs-weg__satz { grid-column: 1; color: var(--text-secondary); font-size: 12.5px; }
.bs-weg__pfeil { grid-column: 2; grid-row: 1 / span 2; display: inline-flex; color: var(--text-tertiary); }
.bs-weg__pfeil svg { width: 17px; height: 17px; }
.bs-weg:hover { background: var(--surface-hover); }
.bs-weg:hover .bs-weg__wort { color: var(--accent-strong); }
.bs-weg:hover .bs-weg__pfeil { color: var(--accent-strong); }
.bs-weg:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

/* --- 4 · «Mein Tag» in der Zentrale --------------------------------------
   Gemessener Befund 17.08.: die Zentrale zeigte dem Owner alles ausser seinen
   eigenen Terminen, Aufgaben und Wiedervorlagen. Drei Zeilen, jede ein Weg —
   nie eine blosse Zahl (BEREICHE §8.2). */
.gz-tag { display: grid; gap: 2px; }
.gz-tag__zeile {
  display: grid; grid-template-columns: auto 1fr auto; align-items: center;
  gap: 12px; padding: 10px 0; min-height: 44px;
  border-top: 1px solid var(--line); text-decoration: none;
}
.gz-tag > .gz-tag__zeile:first-child { border-top: 0; }
.gz-tag__zahl {
  font-size: 21px; font-weight: 700; color: var(--text-primary);
  font-variant-numeric: tabular-nums; min-width: 1.6ch; text-align: right;
}
.gz-tag__wort { display: flex; flex-direction: column; gap: 1px; min-width: 0; color: var(--text-primary); }
.gz-tag__wort i { font-style: normal; font-size: 12.5px; color: var(--text-secondary); }
.gz-tag__zeile--warn .gz-tag__zahl { color: var(--warn-strong); }
.gz-tag__pfeil { display: inline-flex; color: var(--text-tertiary); }
.gz-tag__pfeil svg { width: 16px; height: 16px; }
.gz-tag__zeile:hover .gz-tag__wort { color: var(--accent-strong); }
.gz-tag__zeile:hover .gz-tag__pfeil { color: var(--accent-strong); }
.gz-tag__zeile:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

@media (max-width: 640px) {
  .bs-kopf__wer { gap: 11px; }
  .bs-kopf h1 { font-size: 21px; }
  .bs-ic { width: 34px; height: 34px; }
  .bs-zeile { align-items: flex-start; }
  .bs-zeile__knopf { width: 100%; justify-content: center; }
}
/* ============================================================
   Patch-Integration — Namensraum km-/kp-ort/kp-wege (Kundenwege); Quelle: docs/design/patch-kundenwege.css
   ============================================================ */
/* ============================================================
   Paket K · Die Wege des Kundenportals
   Namensraum: km- (Werbematerial), kp-wege (Ausweg-Zeile an einer Kampagne)

   Owner-Klage, wörtlich: «man weiss nicht, wo was ist» · «man findet eine
             Funktion und dann nie wieder».
   Gesetz:   docs/BEREICHE.md §7.5 (kein Weg endet im Nichts) · §8 (was Arbeit
             braucht, meldet sich — und der Ausweg steht dort, wo das Problem
             steht) · Grundgesetz 6 (390 px, 44 px Tapfläche).

   Die zwei Sachen, die dieser Block leistet, und sonst nichts:
     1  DIE AUSWEG-ZEILE (`kp-wege`) — «Briefing ausfüllen», «Entwurf ansehen»,
        «Material hochladen» dort, wo das Problem steht. Auf 390 px stapeln
        sie sich und halten je 44 px.
     2  DIE ABGABESTELLE (`km-`) — Regeln, Hochladeknopf, Dateiliste.
   NICHT hier: das Ortsschild. Es hat sein eigenes Blatt
        (`docs/design/patch-ortsschild.css`) und seinen eigenen Halter in der
        Schale; ein zweiter Selektor darauf wäre die Doppelung, die §10a
        verbietet.

   Genutzt aus dem Bestand (NICHT neu definiert): --text-secondary,
             --text-tertiary, --border, --hairline, --accent, --accent-rgb,
             --warn-strong, --warn-rgb, --surface-inset, --radius-card.
   Integration: scripts/_naht_kundenwege_stil_anhaengen.mjs
   ============================================================ */

/* --- 1 · Die Ausweg-Zeile an einer Kampagne -------------------------------
   Sie steht dort, wo das Problem steht: unter dem Kopf der Buchung. Auf dem
   Rechner nebeneinander, am Handy untereinander — nie zwei halbe Knöpfe. */
.kp-wege {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 10px 0 4px;
}
.kp-wege > .kk-tun { flex: 0 1 auto; }

/* Dieselbe Zeile INNERHALB einer Listenzeile («Benötigte Inhalte»): sie hängt
   sich hinter das Zustands-Abzeichen und bricht mit ihm um. Ohne die eigene
   Grundlinie stünde sie über die volle Breite und risse die Zeile auseinander. */
.kp-wege--zeile {
  margin: 0;
  flex: 0 0 auto;
  align-items: center;
}
.kk-inhalt .kp-wege--zeile { margin-left: 0; }

/* --- 1b · Das WOHIN in der Briefing-Karte ---------------------------------
   Sie steht in der Karte, in der die Zusage «ich schicke es euch» fällt — der
   Befund vom 17.08. war eine Zusage ohne Gegenstück. Abgesetzt durch eine
   Haarlinie statt durch eine Farbfläche: die Karte hat ihren Akzent schon. */
.bf-abgabe {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 12px;
  margin-top: 4px;
  padding-top: 10px;
  border-top: 1px solid var(--hairline);
}
.bf-abgabe__satz {
  margin: 0;
  flex: 1 1 220px;
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--text-secondary);
  text-wrap: pretty;
}
.bf-abgabe__tun { min-height: 44px; flex: 0 0 auto; }

/* --- 1c · Der Vorschau-Rahmen OHNE Vorschau -------------------------------
   `.bf-vorschau` hält 16:9 (patch-briefing.css §Freigabe) — richtig, solange
   ein Spot darin läuft. Ohne Lieferung steht dort seit Paket K der ehrliche
   Satz «Solange du sie nicht siehst, kannst du sie auch nicht freigeben» —
   und 16:9 machen daraus einen halben Bildschirm schwarze Fläche, genau das,
   was der Owner am 05.08. «diese schwarze leere Fläche» genannt hat.
   Ein eigener Zustand, kein zweiter Selektor auf `.bf-vorschau`: der Rahmen
   hört auf, ein Bildplatz zu sein, und wird zu dem, was er dann ist — ein
   Satz in einem Kasten. */
.bf-vorschau--leer {
  aspect-ratio: auto;
  min-height: 0;
  padding: 22px 16px;
  text-align: center;
}

/* --- 2 · Die Abgabestelle für Werbematerial (`#/k/material/:id`) ----------- */
.km-flaeche {
  display: grid;
  gap: 16px;
}

.km-panel { margin: 0; }

.km-satz {
  margin: 8px 0 0;
  color: var(--text-secondary);
  line-height: 1.5;
  text-wrap: pretty;
}

/* Der Grund einer Ablehnung. Er ist der wichtigste Satz dieser Fläche: ohne
   ihn weiss niemand, was zu ändern ist (Grundgesetz 2 — jedes Ergebnis hat
   eine Folge). Kante links statt Farbfläche: ein zweiter Farbblock neben dem
   Zustands-Abzeichen wäre ein zweiter Akzent. */
.km-satz--warn {
  padding-left: 10px;
  border-left: 3px solid rgba(var(--warn-rgb), .55);
  color: var(--warn-strong);
}

/* Was wir brauchen — aus `spot_regeln`, nie abgetippt. Sie steht VOR dem
   Hochladeknopf, damit niemand 50 MB durchs Netz schickt, um dann eine
   Absage zu lesen. */
.km-regeln {
  margin: 10px 0 0;
  padding: 8px 10px;
  border-radius: var(--radius-card);
  background: var(--surface-inset);
  border: 1px solid var(--hairline);
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--text-tertiary);
  overflow-wrap: anywhere;
}

.km-abgabe {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 14px;
}

/* Das Dateifeld ist unsichtbar, das Etikett ist der Knopf. Er muss darum
   selbst wie ein Knopf greifen — `.primary-btn` allein macht ein <label>
   nicht klickbar-hoch. */
.km-waehlen {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  cursor: pointer;
}

/* Eine Datei-Zeile. Am Handy bricht sie um: Name und Kennzeichen oben, Stand
   und «Ansehen» darunter — nichts läuft seitlich heraus. */
.km-datei {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
}
.km-datei .panel-row__main { min-width: 0; flex: 1 1 200px; }
.km-datei b { overflow-wrap: anywhere; }

.km-ansehen { min-height: 44px; }

@media (max-width: 640px) {
  /* Ein halber Knopf ist kein Knopf: auf 390 px steht jeder Weg auf voller
     Breite und hält seine 44 px. */
  .kp-wege { flex-direction: column; align-items: stretch; }
  .kp-wege > .kk-tun { width: 100%; }
  .km-abgabe { flex-direction: column; align-items: stretch; }
  .km-abgabe > * { width: 100%; }
  .bf-abgabe { flex-direction: column; align-items: stretch; }
  /* In der Spalte ist die Grundlage die HOEHE: `flex: 1 1 220px` riss sonst
     ein 220 px hohes Loch zwischen Satz und Knopf (gemessen am Bild, 390 px). */
  .bf-abgabe__satz { flex: 0 0 auto; }
  .bf-abgabe__tun { width: 100%; }
}

/* ==========================================================================
   PAKET KUNDENWELT (21.08.2026) — die Seite, die der zahlende Kunde sieht
   Namensraum: kk-schrittband · sf- (Schaufenster) · kk-bekommst · kk-ausgabe
               kk-nummer · kp-row__tage · kf- (Frag uns)

   Owner-Massstab: «Ein Mensch ohne jede Management-Ausbildung managt damit die
             ganze Firma allein» — und der Kunde hat gar keine Einfuehrung
             bekommen. Er sieht die Flaeche zum ersten Mal.
   Gesetz:   docs/BEREICHE.md §3 (jede Flaeche sagt, wo sie ist) · §6 (jede
             Zahl, die auf ein anderes Ding zeigt, ist ein Weg dorthin) ·
             §10 (ein Bauteil je Frage) · Grundgesetz 6 (390 px, 44 px).
   Genutzt aus dem Bestand (NICHT neu definiert): --text-secondary,
             --text-tertiary, --hairline, --line-strong, --accent,
             --accent-rgb, --accent-soft, --accent-line, --surface-inset,
             --surface-2, --radius-card, --on-accent.
   ========================================================================== */

/* --- 6 · Das Schrittband unter dem Kopf der Werkbank ----------------------
   Befund BEFUNDE-2026-08-17.md:606: den Schritt-Balken sah der Kunde erst,
   wenn er beim LETZTEN Schritt stand. Jetzt steht er in allen drei Schritten —
   und weil `cockpit.js` das Markup roh einsetzt, bleibt die Gestaltung hier,
   im Namensraum der Flaeche (BEREICHE §10a.4: `.cp` bekommt keinen weiteren
   Selektor). */
.kk-schrittband {
  padding: 8px 16px 0;
  overflow-x: auto;
  scrollbar-width: none;
}
.kk-schrittband::-webkit-scrollbar { display: none; }
.kk-schrittband .bs-schritte { margin: 0; }

@media (max-width: 720px) {
  /* Am Handy traegt das Band die Orientierung im Kauf — es darf nicht auf
     zwei Zeilen brechen und keine Zeile verschlucken.

     KORREKTUR 23.08.2026 — DIE REGEL GRIFF INS LEERE. Hier stand
     `flex-wrap: nowrap; min-width: max-content` an `.bs-schritte`. Das ist ein
     GRID (patch-buchungsstrecke.css:48), und `flex-wrap` tut an einem Grid
     nichts. Wirksam blieb darum patch-buchungsstrecke.css:451, das die drei
     Schritte auf 390 px UNTEREINANDER stellt — richtig fuer die
     alleinstehende Strecke, teuer in der Werkbank, wo direkt darunter die
     Arbeitsflaeche liegt.

     GEMESSEN am echten Safari-Mass 390 x 620 (scripts/_handy_karte_test.mjs):
       gestapelt   Band 166 px → Buehne 112 px fuer eine 225 px hohe Karte
       eine Zeile  Band  58 px → Buehne 220 px
     Der Owner sah dadurch einen waagrechten Streifen der Schweiz und nannte
     die Karte «komplett katastrophal auf dem Smartphone».

     Jetzt steht das Band wirklich in einer Zeile — waagrecht rollbar, wie es
     sein Behaelter oben ohnehin vorsieht (`overflow-x: auto`). Gequetscht wird
     nichts: die Schrift bleibt bei 13,5 px (Floor 11 px, DESIGN.md §2), kein
     Wort wird abgeschnitten. Bewiesen in scripts/_buchungsstrecke_ui_test.mjs
     («Die Schrittleiste der Werkbank steht auf 390px in EINER Zeile»).
     Die alleinstehende `.bs-schritte` bleibt unberuehrt. */
  .kk-schrittband { padding: 6px 12px 0; }
  .kk-schrittband .bs-schritte {
    display: flex; flex-wrap: nowrap; min-width: max-content;
    gap: 4px; margin: 0;
  }
  .kk-schrittband .bs-schritt-punkt { flex: 0 0 auto; }
  .kk-schrittband .bs-schritt-punkt__tun {
    flex-direction: row; justify-content: flex-start; align-items: center;
    gap: 8px; padding: 4px 10px; width: auto; white-space: nowrap;
  }
  .kk-schrittband .bs-schritt-punkt__wort { white-space: nowrap; }
}

/* --- 7 · Das Schaufenster: das Produkt als Objekt --------------------------
   Befund :634 — «Das Portal erklaert das Produkt mit keinem Wort». Die Antwort
   ist KEIN Erklaertext (Hausgesetz «ein Werkzeug erklaert sich nicht»),
   sondern die Sache: ein Bildschirm im Seitenverhaeltnis, das der Kunde
   bekommt, mit dem Durchlauf darunter. */
.kk-bekommst {
  display: grid;
  gap: 12px;
}
.sf { margin: 0; display: grid; gap: 8px; }
.sf-bild {
  position: relative;
  aspect-ratio: 16 / 9;
  display: grid;
  place-content: center;
  gap: 2px;
  text-align: center;
  border-radius: var(--radius-card);
  background: var(--surface-inset);
  box-shadow: inset 0 0 0 1px var(--line-strong);
}
.sf-bild__wort {
  font-size: 13px;
  font-weight: 650;
  letter-spacing: .02em;
  color: var(--accent-strong);
}
.sf-bild__sek {
  font-size: 11px;
  font-variant-numeric: tabular-nums;
  color: var(--text-tertiary);
}
/* Der Durchlauf als Balkenreihe: so viele Balken, wie es Plaetze gibt, die
   eigenen in Tuerkis. Der Kunde sieht auf einen Blick, wie oft SEIN Spot in
   einem Durchgang vorkommt — eine Zahl in einem Satz saehe er nicht. */
.sf-loop {
  display: flex;
  gap: 3px;
  height: 8px;
}
.sf-platz {
  flex: 1 1 0;
  border-radius: 2px;
  background: rgba(140, 168, 196, .16);
}
.sf-platz.is-mein { background: var(--accent); }
.sf-fuss {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 12px;
  font-size: 11.5px;
  font-variant-numeric: tabular-nums;
  color: var(--text-tertiary);
}

/* Die Leistung in Zahlen — neben dem Preis, nicht in einem Absatz daneben. */
.sf-leistung {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 18px;
  margin: 0;
}
.sf-leistung__paar { display: grid; gap: 1px; }
.sf-leistung dt {
  font-size: 14px;
  font-weight: 650;
  font-variant-numeric: tabular-nums;
  color: var(--text-primary);
}
.sf-leistung dd {
  margin: 0;
  font-size: 11px;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--text-tertiary);
}

/* Preis und Objekt liegen in der Ausgabe nebeneinander — am Handy
   untereinander, Preis zuerst. */
.kk-ausgabe {
  display: grid;
  gap: 14px;
  grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr);
  align-items: start;
}
@media (max-width: 900px) {
  .kk-ausgabe { grid-template-columns: minmax(0, 1fr); }
}

/* Die gesicherten Eckwerte an der Standortzeile (Befund :634, zweiter Teil).
   `tage_offen` steht seit 115:150 in der Antwort und wurde bis zum 21.08.
   weggeworfen. */
.kp-row__tage {
  font-size: 11.5px;
  font-variant-numeric: tabular-nums;
  color: var(--text-tertiary);
  white-space: nowrap;
}

/* --- 8 · Die Nummer IST der Weg (BEREICHE §6) -----------------------------
   Eine Belegnummer, die auf ein anderes Ding zeigt, traegt keinen Knopf und
   keine Farbflaeche — sie bekommt eine Unterlinie, die beim Zeigen erwacht.
   So bleibt die Zeile eine Zeile und wird trotzdem bedienbar. */
.kk-nummer {
  color: inherit;
  text-decoration: none;
  border-bottom: 1px solid rgba(var(--accent-rgb), .38);
  transition: color .12s ease, border-color .12s ease;
}
.kk-nummer:hover,
.kk-nummer:focus-visible {
  color: var(--accent-strong);
  border-bottom-color: var(--accent);
}
.kk-nummer--titel { border-bottom-width: 0; }
.kk-nummer--titel:hover,
.kk-nummer--titel:focus-visible { color: var(--accent-strong); }

@media (max-width: 1024px), (pointer: coarse) {
  /* Eine Nummer ist am Finger eine Tuer: sie braucht Trefflaeche, ohne die
     Zeile aufzureissen (Memory project_tablet_touch_breakpoint). */
  .kk-nummer {
    display: inline-block;
    min-height: 24px;
    padding: 6px 0;
  }
}

/* --- 9 · «Frag uns» — der Kanal (`#/k/kontakt`) ---------------------------
   Befund :655: «Kontakt ist eine Adresse, kein Kanal — und der Kunde muss
   seine Nummer selbst abtippen». Tap-only (Gesetz 7): Thema und Beleg werden
   angetippt, das Notizfeld ist freiwillig und sagt es. */
.kf-panel { display: grid; gap: 6px; }
.kf-frage {
  margin: 10px 0 2px;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--text-secondary);
}
.kf-themen,
.kf-belege { margin: 0; }
.kf-notiz {
  display: grid;
  gap: 6px;
  margin-top: 14px;
  font-size: 12.5px;
  color: var(--text-secondary);
}
.kf-notiz textarea {
  width: 100%;
  resize: vertical;
  min-height: 66px;
  padding: 10px 12px;
  border-radius: var(--radius-card);
  border: 1px solid var(--hairline);
  background: var(--surface-inset);
  color: var(--text-primary);
  font: inherit;
}
.kf-notiz textarea:focus-visible {
  outline: none;
  border-color: var(--accent-line);
}
.kf-abschluss {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 14px;
  margin-top: 14px;
}
.kf-klemme {
  font-size: 12px;
  color: var(--text-tertiary);
}

/* Der Verlauf — hier findet er die Antwort wieder.

   BEGRENZT AUF DIESES BAUTEIL (21.08.2026), und das ist kein Schönheitsgriff.
   Der Klassenname `kf-zeile` ist ZWEIMAL vergeben: der Offertenrechner baut
   damit seine Label-Wert-Zeilen (sales-konfigurator.js, 11 Stellen, Idiom
   «Stat-in-Rail» aus DESIGN.md §4 — Label und Zahl stehen auf DERSELBEN
   Schriftlinie, `align-items: baseline` in patch-konfigurator.css:834), und
   diese Fläche baut damit ihre Anliegen-Zeile (kunde-kontakt.js:256,
   `article.panel-row.kf-zeile`), die eine mehrzeilige Antwort trägt und darum
   oben bündig stehen muss.
   Als `.kf-zeile` stand die Regel hier NACKT, und dieses Blatt kommt in der
   Kaskade nach dem Konfigurator (Blatt 64 gegen 36, bauplan.json) — sie hat
   damit jede Zeile im Offertenrechner mitgenommen. Im Browser gemessen an der
   Endbetrag-Zeile (`.kf-zeile.is-stark`, Zahl 18 px gegen Label 13.5 px):
   die Unterkanten von Wort und Zahl lagen 6.8 px auseinander statt 1.8 px —
   die Zahl, auf die der Kunde schaut, hing 5 px unter ihrer Schriftlinie.
   Mit `.panel-row` davor trifft die Regel genau dieses Bauteil: der
   Offertenrechner ist wieder auf `baseline`, die Anliegen-Zeile bleibt auf
   `flex-start`. Beides gemessen, nicht angenommen. */
.panel-row.kf-zeile { align-items: flex-start; }
.kf-antwort {
  display: flex;
  gap: 8px;
  align-items: flex-start;
  margin: 8px 0 0;
  padding: 9px 11px;
  border-radius: var(--radius-card);
  background: var(--accent-soft);
  box-shadow: inset 0 0 0 1px var(--accent-line);
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--text-primary);
  text-wrap: pretty;
}
.kf-antwort .gz-ic { flex: 0 0 auto; color: var(--accent-strong); }

@media (max-width: 720px) {
  /* 390 px: jede Tap-Flaeche haelt 44 px, und der Absendeknopf steht ueber die
     ganze Breite — er ist die Handlung dieser Flaeche. */
  .kf-panel .tap-btn { min-height: 44px; }
  .kf-abschluss > .primary-btn { flex: 1 1 100%; min-height: 44px; }
  .kf-zeile .kk-tun { min-height: 44px; }
}
/* ============================================================
   Patch-Integration — Namensraum vg-/pd2-baum__knoten--weg (Verguetung eine Pflegestelle); Quelle: docs/design/patch-verguetung.css
   ============================================================ */
/* Paket G «Vergütung der Standortbetreiber» — Namensraum .vg-*

   Die Flaeche #/a/einstellungen?bereich=verguetung (views/admin-verguetung.js):
   die EINE Pflegestelle der wichtigsten Geldregel des Hauses. Dazu die eine
   Zeile, die der Geltungs-Baum im Betreiber-Dossier dazubekommen hat
   (.pd2-baum__knoten--weg) — die oberste Stufe ist dort jetzt ein Weg hierher.

   KEINE NEUE FARBE, KEIN NEUER ABSTAND. Alles kommt aus den Tokens:
   --surface-inset, --surface-2, --border, --text-primary/-secondary/-tertiary,
   --accent. Kacheln sind .stat (kennzahl-kachel.js), Kaesten sind .panel,
   Knoepfe sind .primary-btn/.ghost-btn, der Seitentitel kommt aus .page-head
   und wird hier NICHT angefasst.

   HANDY ZUERST GEDACHT (Grundgesetz 6). Auf 390 px stehen die Kacheln
   untereinander, der Kopf bricht um, der Knopf nimmt die volle Breite und
   traegt 44 px Hoehe, und jede Abweichungs-Zeile ist eine ganzflaechige
   Tuer — ein Weg, den man mit dem Daumen verfehlt, ist keiner. Kein Element
   ist breiter als sein Kasten; lange Betreiber- und Standortnamen brechen im
   Wort, statt die Seite seitlich herauslaufen zu lassen. */

/* --- Kopf ----------------------------------------------------------------- */
.vg-kopf { align-items: flex-start; gap: 12px 20px; flex-wrap: wrap; }
.vg-kopf > div { min-width: 0; flex: 1 1 260px; }
.vg-kopf .primary-btn { min-height: 44px; flex: none; }

/* --- Die Kaesten ---------------------------------------------------------- */
.vg-panel { padding: 16px 20px; margin-top: 16px; min-width: 0; }
.vg-panel .panel__header { padding: 0 0 12px; margin: 0; }
.vg-seit { font-size: 12.5px; color: var(--text-tertiary); white-space: nowrap; }

/* Die geplante Fassung traegt eine Kante in der Akzentfarbe: sie ist eine
   Tatsache mit Datum, keine Randnotiz — aber auch keine Warnung. */
.vg-panel--geplant { border-color: var(--accent-line); }

.vg-note { font-size: 12.5px; color: var(--text-secondary); margin: 10px 0 0; }
.vg-satz {
  margin: 12px 0 0; padding: 10px 12px;
  background: var(--surface-inset); border-radius: var(--radius-button);
  font-size: 13px; color: var(--text-primary); overflow-wrap: anywhere;
}
.vg-liste { margin: 0; padding-left: 18px; font-size: 13px; color: var(--text-primary); }
.vg-liste li { margin: 2px 0; }

/* --- Der Kennzahlen-Streifen ---------------------------------------------- */
/* Auto-fit statt fester Spaltenzahl: vier bis fuenf Kacheln am Rechner, eine
   Spalte am Handy — ohne einen zweiten Umbruchpunkt zu erfinden. */
.vg-kacheln {
  display: grid; gap: 10px;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
}
.vg-kacheln .stat { min-width: 0; }

/* --- Wer etwas anderes bekommt -------------------------------------------- */
.vg-abweichungen { display: grid; gap: 8px; margin-top: 4px; }
.vg-abweichung {
  display: grid; gap: 3px; min-height: 44px;
  padding: 10px 12px; min-width: 0;
  background: var(--surface-inset); border: 1px solid var(--border);
  border-radius: var(--radius-button);
  color: inherit; text-decoration: none;
}
.vg-abweichung:hover { border-color: var(--accent); }
.vg-abweichung__kopf {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 10px; min-width: 0;
}
.vg-abweichung__kopf strong { font-size: 13.5px; color: var(--text-primary); overflow-wrap: anywhere; }
.vg-abweichung__ort { font-size: 12px; color: var(--text-tertiary); overflow-wrap: anywhere; }
.vg-abweichung__ab { font-size: 12px; color: var(--text-tertiary); margin-left: auto; white-space: nowrap; }
.vg-abweichung__text { font-size: 12.5px; color: var(--text-secondary); overflow-wrap: anywhere; }
.vg-abweichung__grund { font-size: 12px; color: var(--text-tertiary); overflow-wrap: anywhere; }

/* --- Der Weg aus dem Betreiber-Dossier an die Pflegestelle ---------------- */
/* Derselbe Knoten wie bisher, nur als Tuer: Textfarbe erben, Unterstrich weg,
   und beim Zeigen dieselbe Akzentkante wie jede andere Tuer des Hauses. */
.pd2-baum__knoten--weg { color: inherit; text-decoration: none; }
.pd2-baum__knoten--weg:hover { border-color: var(--accent); }

/* --- Handy ---------------------------------------------------------------- */
@media (max-width: 640px) {
  .vg-panel { padding: 14px 14px; }
  .vg-kopf .primary-btn { width: 100%; }
  .vg-kacheln { grid-template-columns: 1fr; }
  .vg-abweichung__ab { margin-left: 0; }
}

/* ============================================================
   Patch-Integration — Namensraum ppx- (Betreiberportal); Quelle: docs/design/patch-betreiberportal.css
   ============================================================ */
/* ============================================================================
   Betreiberportal (#/pp) — Namensraum ppx-
   ----------------------------------------------------------------------------
   Vier Regeln, kein Blatt mehr. Sie tragen genau das, was das Portal am
   18.08.2026 dazubekommen hat und wofuer es im Haus noch keine Form gab:

     .ppx-warnung   die eine schlechte Nachricht oben — «1 Bildschirm meldet
                    sich nicht». Steht NUR, wenn wirklich etwas ist; ein
                    gruener Kasten «alles in Ordnung» waere Beruhigung ohne
                    Inhalt (BEREICHE §8).
     .ppx-screen    die Zeile eines auffaelligen Bildschirms: Satz links,
                    Handgriff rechts. Sie sass bis heute in `.vt-history` als
                    reiner Text — es gab dort nichts zu druecken.
     .ppx-tun       die Handgriff-Zeile am Fuss einer Standort-Karte.
     .ppx-btn       Grundgesetz 9 (Handy): jede Bedienflaeche >= 44px, auch
                    wenn `ghost-btn` daneben kleiner sein darf.

   Bewusst NICHT hier: `.stat__sub`, `.vt-row`, `.sl-badge--*`. Die gibt es im
   Haus laengst (grund.css bzw. patch-verkauf.css); ein zweites Vorkommen
   waere die Doppelung, die `node scripts/_stil_einmalig_test.mjs` rot macht —
   und in einer Welle darauf die stille Verschiebung, die niemand mehr
   zuordnen kann.
   ============================================================================ */

.ppx-warnung {
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin: 0 0 16px;
  padding: 12px 14px;
  border-radius: var(--radius-card);
  border: 1px solid color-mix(in srgb, var(--danger, #b3261e) 32%, transparent);
  background: color-mix(in srgb, var(--danger, #b3261e) 8%, var(--surface, #fff));
}
.ppx-warnung strong { font-size: 14px; line-height: 1.35; }
.ppx-warnung span { font-size: 12.5px; color: var(--text-secondary); line-height: 1.4; }

/* Der Handgriff steht NEBEN seinem Satz, nicht am anderen Ende des
   Bildschirms: auf 1400px riss `space-between` beide 1'100 Pixel auseinander,
   und der Knopf gehoerte optisch zu nichts mehr. */
.ppx-screen {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: 12px;
  flex-wrap: wrap;
  padding: 4px 0;
}
.ppx-screen small { color: var(--text-tertiary); line-height: 1.4; flex: 0 1 auto; }

.ppx-tun {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  margin-top: 8px;
}

.ppx-btn {
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

@media (max-width: 560px) {
  .ppx-screen { align-items: flex-start; flex-direction: column; gap: 6px; }
  .ppx-screen .ppx-btn { width: 100%; }
  .ppx-tun { justify-content: stretch; }
  .ppx-tun .ppx-btn { flex: 1; }
}
/* ============================================================
   Patch-Integration — Namensraum ra- (Rechnungs-Akte); Quelle: docs/design/patch-rechnungsakte.css
   ============================================================ */
/* DIE RECHNUNGS-AKTE — Namensraum `ra-` (Welle 2, Paket B, 18.08.2026).
   Fläche: public/src/views/rechnung-akte.js · Route #/v/invoice/:id

   WAS HIER STEHT UND WARUM SO WENIG: die Akte trägt das VERKAUFS-KLEID
   (`admin-page vk`, `vk-kopf`, `vk-tabs`, `vk-kacheln`, `pd2-kpis`, `panel`,
   `table-wrap`, `sl-badge`) — dieselben Bauteile wie Kundenakte und
   Offertenliste. Neu ist nur, was es im Haus noch NICHT gibt: die
   Nachbarschafts-Liste (BEREICHE §6) und die Schritt-Zeile (§7.2). Alles
   andere wäre ein zweites Kleid für dasselbe (BEREICHE §10). */

/* --- 0. Die Kennzeile ist ein SATZ, keine Reihe von Kacheln --------------- */
/* `.vk-kopf__ort` ist im Kundenkleid ein `inline-flex` mit Lücke — richtig für
   «Bern · 12 Buchungen», falsch für die Kennzeile einer Rechnung: dort stehen
   sechs Angaben, und am Telefon (390px) wurde jede ein eigenes Flex-Feld.
   Gemessen am Bild vom 18.08.: «RE-2026-0102» brach mitten in der Nummer auf
   drei Zeilen um. Eine Kennung, die man am Telefon ablesen soll, darf nie
   umbrechen (BEREICHE §5). Also fliesst die Zeile hier als Text, und die
   Kennung bleibt in einem Stück. */
body.lx-rechnungsakte .vk-kopf__ort {
  display: block; line-height: 1.6; max-width: 100%;
}
body.lx-rechnungsakte .vk-kopf__ort .lx-kennung { white-space: nowrap; }

/* --- 1. Der nächste Schritt: Satz links, Knopf rechts --------------------- */
/* §7.2 «Der nächste Schritt ist ein Knopf, kein Satz» — der Satz bleibt daneben
   stehen, damit man weiss WARUM, aber gedrückt wird der Knopf. */
.ra-schritt {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  padding: 14px 16px; margin-bottom: 14px;
}
.ra-schritt__text { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1 1 240px; }
/* Wort und Satz tragen das Frage-Kopf-Kleid (grund.css) — seit 03.09. */

/* --- 2. Die Nachbarn ----------------------------------------------------- */
/* «Jede Beziehung ist ein Weg, in beide Richtungen» (BEREICHE §6). Zwei
   Spalten am Rechner, eine am Telefon. */
.ra-nachbarn { padding: 14px 16px; margin-bottom: 14px; }
/* ZWEI SPALTEN, FEST — nicht `auto-fit`. Am Bild vom 18.08. (1400px) legte
   `auto-fit` fünf Zellen in Reihe eins, und die Regel «die ersten ZWEI tragen
   keine Trennlinie» stimmte damit nicht mehr: drei Zellen der ersten Reihe
   hatten eine Linie über sich, die nichts trennte. Bei fester Spaltenzahl ist
   die erste Reihe immer dieselbe, und die Linien sagen die Wahrheit. Zwei
   Spalten sind ausserdem die Lesebreite, in der die Untertitel («Teilzahlung ·
   CHF 12'000.00») nicht mehr abgeschnitten werden. */
.ra-nachbarn__liste {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0;
}
.ra-nachbar {
  display: flex; align-items: center; gap: 10px; min-width: 0;
  padding: 11px 12px; border: 0; border-top: 1px solid var(--border);
  background: transparent; color: inherit; text-align: left; text-decoration: none;
  font: inherit;
}
.ra-nachbar:nth-child(1), .ra-nachbar:nth-child(2) { border-top: 0; }
.ra-nachbar--weg { cursor: pointer; }
.ra-nachbar--weg:hover { background: rgba(var(--tint-rgb), .05); }
.ra-nachbar--weg:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.ra-nachbar__ic { --gz-ic-gr: 26px; flex: 0 0 auto; }
.ra-nachbar__text { display: flex; flex-direction: column; gap: 1px; min-width: 0; flex: 1 1 auto; }
.ra-nachbar__wort {
  font-size: 11px; letter-spacing: .08em; text-transform: uppercase;
  color: var(--text-secondary);
}
.ra-nachbar__titel {
  font-size: 13.5px; font-weight: 600;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ra-nachbar--multiline .ra-nachbar__titel { white-space: normal; overflow-wrap: anywhere; }
.ra-nachbar__sub {
  font-size: 11.5px; color: var(--text-secondary);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Der Pfeil steht NUR an einem Weg — an einer Zeile ohne Ziel wäre er ein
   Versprechen ohne Deckung (BEREICHE §11.2). */
.ra-nachbar__pfeil { flex: 0 0 auto; color: var(--text-secondary); display: inline-flex; }
.ra-nachbar__pfeil svg { width: 16px; height: 16px; }

/* --- 3. Der Versandstand auf der Übersicht ------------------------------- */
.ra-post-stand { padding: 10px 16px; margin-bottom: 14px; }
.ra-post-stand p { margin: 0; }

/* --- 4. Handy ------------------------------------------------------------ */
/* Tapflächen-Boden auf JEDEM Touch-Gerät, nicht erst unter 640px
   (Memory project_tablet_touch_breakpoint: 768/1024 sind die Bruchzone). */
@media (max-width: 1024px), (pointer: coarse) {
  .ra-nachbar { min-height: 44px; }
  .ra-schritt .primary-btn, .ra-schritt .ghost-btn { min-height: 44px; }
}
@media (max-width: 640px) {
  .ra-nachbarn__liste { grid-template-columns: minmax(0, 1fr); }
  /* Einspaltig gibt es keine zweite Zelle in Zeile 1 — nur die ERSTE steht
     ohne Trennlinie. */
  .ra-nachbar:nth-child(2) { border-top: 1px solid var(--border); }
  .ra-schritt { align-items: stretch; }
  .ra-schritt .primary-btn { width: 100%; }
}

/* ============================================================
   Patch-Integration — Namensraum lx-kennung/lx-akte-schnell/vk-gruppe__zelle--tuer (Akten-Kopf); Quelle: docs/design/patch-akte.css
   ============================================================ */
/* ============================================================
   DER AKTEN-KOPF — die drei Stuecke Kleid, die der Kanon neu braucht.
   Quelle im Baum: public/src/components/akte-kopf.js (BEREICHE.md §5).

   Es sind bewusst NUR drei Regeln. Der Akten-Kanon tauscht den Bauplan der
   drei Dossiers, nicht ihr Aussehen: Standortbetreiber und Vertrieb tragen
   weiter `pd2-*` (docs/design/patch-partnerdetail.css), der Kunde weiter
   `vk-*` (docs/design/patch-verkauf.css). Das Zusammenlegen der Namensraeume
   ist BEREICHE §13 Welle 8 und faellt nicht in diese Welle — es wuerde die
   Kaskade von 1.1 MB style.css bewegen, waehrend andere darin arbeiten.
   ============================================================ */

/* 1 · Die sichtbare Kennung (§5: «man muss sie am Telefon sagen koennen»).
   Neutral gehalten: sie liegt IN der Kennzeile und erbt deren Farbe und
   Groesse. Das eine, was sie braucht, sind Ziffern gleicher Breite — sonst
   tanzt «SB-0005» neben «SB-0012». */
.lx-kennung { font-variant-numeric: tabular-nums; letter-spacing: .02em; }
/* Im Kunden-Dossier steht sie als erstes Glied der Ortszeile; dort ist sie
   etwas leiser als der Ort daneben. */
.vk-kennung { color: var(--text-tertiary); }

/* 2 · Eine Kennzahl, die eine Tuer ist (§6: «Jede Zahl, die auf ein anderes
   Ding zeigt, ist ein Weg dorthin»). Sie bleibt Zeichen fuer Zeichen dieselbe
   Zelle — nur der Zeiger und ein Hauch Flaeche beim Ueberfahren sagen, dass
   man sie anfassen kann. */
.vk-gruppe__zelle--tuer { color: inherit; text-decoration: none; cursor: pointer; border-radius: var(--radius-card); }
.vk-gruppe__zelle--tuer:hover { background: var(--surface-2); }
.vk-gruppe__zelle--tuer:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* 3 · Die Zone der Schnellaktionen, direkt unter der Reiterzeile (§5
   Anatomie). Leer traegt sie keinen Abstand — eine Akte, die ihre
   Schnellaktionen im Cockpit fuehrt (Standortbetreiber), soll hier keine
   Luecke stehen lassen. */
.lx-akte-schnell:not(:empty) { margin: 14px 0 4px; }

/* 4 · Der Griff, der auf den Reiter zeigt, in dem man schon steht (§7.4: kein
   Knopf widerspricht dem Zustand). Er bleibt an seinem Platz — die Reihe darf
   beim Reiterwechsel nicht tanzen —, sagt aber, dass hier nichts mehr zu holen
   ist. */
.pd2-act.is-hier { opacity: .55; cursor: default; }
.pd2-act.is-hier:hover { background: var(--surface-2); border-color: var(--border); }

/* One compact record frame for customers, operators, employees and distribution. */
.record-workspace [data-akte-teil=kennzahlen] { margin:12px 0 20px; }
.record-workspace [data-akte-teil=kennzahlen] .stat-strip { display:grid; grid-template-columns:repeat(auto-fit,minmax(145px,1fr)); gap:0; background:var(--surface); border:1px solid var(--border); border-radius:var(--radius-card); overflow:hidden; margin:0; }
.record-workspace [data-akte-teil=kennzahlen] .stat { min-height:0; padding:16px 18px; border:0; border-radius:0; box-shadow:none; background:transparent; gap:4px; }
.record-workspace [data-akte-teil=kennzahlen] .stat+.stat { border-left:1px solid var(--border); }
.record-workspace [data-akte-teil=kennzahlen] .stat .gz-ic { display:none; }
.record-workspace [data-akte-teil=kennzahlen] .stat__label { text-transform:none; font-size:12px; line-height:1.4; letter-spacing:0; color:var(--text-secondary); }
.record-workspace [data-akte-teil=kennzahlen] .stat__value { font-size:24px; line-height:1.2; letter-spacing:-.035em; margin:0; }
.record-workspace [data-akte-teil=kennzahlen] .stat__sub { font-size:12px; line-height:1.5; display:block; }
.record-workspace [data-akte-teil=reiter] { gap:4px; margin:0 0 24px; border-bottom:1px solid var(--border); }
.record-workspace [data-akte-teil=reiter] button { min-height:44px; text-transform:none; letter-spacing:0; font-size:14px; }
.record-workspace [data-akte-teil=schnellaktionen]:empty { display:none; }
.record-workspace .panel__title { text-transform:none; letter-spacing:-.015em; font-size:18px; font-weight:650; }
.person-work-leads { margin-bottom:28px; }
.person-work-leads__head h2 { margin:0; font-size:20px; letter-spacing:-.025em; }
.person-work-leads__head p { margin:5px 0 0; font-size:13px; color:var(--text-secondary); }
.person-work-leads__layout { display:grid; grid-template-columns:210px minmax(0,1fr); gap:24px; align-items:start; }
.person-lead-stages { display:grid; gap:4px; }
.person-lead-stage { display:grid; grid-template-columns:1fr auto; gap:6px 12px; width:100%; padding:10px 12px; min-height:52px; border:1px solid transparent; border-radius:var(--radius-button); color:var(--text); background:transparent; text-align:left; cursor:pointer; font:inherit; font-size:13px; text-transform:none; letter-spacing:0; }
.person-lead-stage strong { font-variant-numeric:tabular-nums; font-weight:650; }
.person-lead-stage:hover,.person-lead-stage[aria-pressed=true] { background:var(--surface); border-color:var(--border); }
.person-lead-stage[aria-pressed=true] { border-color:var(--accent); }
.person-lead-stage__track { grid-column:1/-1; background:var(--surface-inset); height:5px; border-radius:4px; overflow:hidden; }
.person-lead-stage__track i { display:block; height:100%; background:var(--accent); border-radius:4px; }
.person-lead-stage[data-stage=open] i { background:var(--text-tertiary); }
.person-lead-stage[data-stage=later] i { background:var(--warn); }
.person-lead-stage[data-stage=lost] i { background:var(--danger); }
.person-lead-stages__note { font-size:12px; line-height:1.5; color:var(--text-secondary); margin:8px 12px; }
.person-lead-browser { min-width:0; background:var(--surface); border:1px solid var(--border); border-radius:var(--radius-card); padding:16px; }
.person-lead-search { display:block; margin-bottom:12px; }
.person-lead-search input { width:100%; min-height:44px; font:inherit; font-size:14px; background:var(--bg); border:1px solid var(--border); padding:10px 12px; border-radius:var(--radius-button); color:var(--text); }
.person-lead-region { display:block; font-size:12px; color:var(--text-secondary); margin-top:4px; }
.person-lead-browser .team-table { font-size:13px; }
.person-lead-browser .team-table td { padding:12px 8px; }
.person-lead-browser .team-table th { padding:8px; }
.person-lead-pagination { display:flex; align-items:center; justify-content:space-between; gap:12px; padding:0 0 12px; font-size:12px; color:var(--text-secondary); }
.person-lead-pagination>div { display:flex; gap:8px; }
.person-lead-stage:focus-visible,.person-lead-search input:focus-visible { outline:2px solid var(--accent); outline-offset:2px; }
@media(max-width:1050px) {
  .person-work-leads__layout { grid-template-columns:minmax(0,1fr); gap:16px; }
  .person-lead-stages { grid-template-columns:repeat(auto-fit,minmax(140px,1fr)); }
  .person-lead-stages__note { grid-column:1/-1; margin:4px 12px; }
}
@media(max-width:600px) {
  .record-workspace [data-akte-teil=kennzahlen] .stat-strip { grid-template-columns:1fr 1fr; }
  .record-workspace [data-akte-teil=kennzahlen] .stat { padding:12px; }
  .record-workspace [data-akte-teil=kennzahlen] .stat__value { font-size:22px; }
  .record-workspace [data-akte-teil=kennzahlen] .stat:nth-child(odd) { border-left:0; }
  .record-workspace [data-akte-teil=kennzahlen] .stat:nth-child(n+3) { border-top:1px solid var(--border); }
  .person-work-leads__head { align-items:start; }
  .person-lead-browser { padding:12px; }
  .person-lead-pagination { flex-wrap:wrap; }
}

/* Person work: the current selection and original records come before administration. */
@media(max-width:600px) {
  .person-lead-stages { display:flex; flex-wrap:nowrap; overflow-x:auto; gap:6px; padding:2px 0 6px; scroll-snap-type:x proximity; }
  .person-lead-stage { display:flex; align-items:center; flex:0 0 auto; width:auto; gap:10px; min-height:44px; padding:8px 12px; border-color:var(--border); scroll-snap-align:start; }
  .person-lead-stage__track,.person-lead-stages__note { display:none; }
  .person-lead-pagination { position:sticky; top:68px; z-index:2; background:var(--surface); padding:8px 0; margin-bottom:6px; }
  .person-lead-browser .table-wrap table.team-table tbody tr { display:grid; grid-template-columns:minmax(0,1fr) minmax(0,1fr); gap:4px 12px; padding:8px 10px; margin-bottom:8px; }
  .person-lead-browser .table-wrap table.team-table tbody tr td[data-label] { display:flex; align-items:center; flex-wrap:wrap; justify-content:space-between; gap:4px; padding:0; min-width:0; }
  .person-lead-browser .table-wrap table.team-table tbody tr td[data-label]::before { position:static; width:auto; margin:0; }
  .person-lead-browser .table-wrap table.team-table tbody tr td[data-label="Firma"] { grid-column:1/-1; display:block; }
  .person-lead-browser .table-wrap table.team-table tbody tr td[data-label="Firma"] a { display:flex; align-items:center; min-height:44px; }
  .person-lead-browser .table-wrap table.team-table tbody tr td[data-label="Zuletzt"] { grid-column:1/-1; justify-content:flex-start; gap:8px; color:var(--text-secondary); }
}
.operator-account,.operator-account__journal{display:grid;gap:20px;min-width:0}
.operator-account__head{display:flex;align-items:center;gap:32px;padding:22px 0;border-bottom:1px solid var(--border);flex-wrap:wrap}
.operator-account__head>div>span{font-size:12px;color:var(--text-secondary)}
.operator-account__head h2{font-size:clamp(25px,3vw,38px);letter-spacing:-.045em;line-height:1.2;margin:5px 0;font-variant-numeric:tabular-nums}
.operator-account__head p{font-size:12px;color:var(--text-secondary);margin:0}
.operator-account__head dl{display:flex;gap:28px;margin:0}
.operator-account__head dt{font-size:12px;color:var(--text-secondary);margin-bottom:5px}
.operator-account__head dd{margin:0;font-size:17px;font-weight:650;font-variant-numeric:tabular-nums}
.operator-account__actions{margin-left:auto;display:flex;align-items:center;gap:12px;flex-wrap:wrap}
.operator-account__actions details summary,.operator-account__plan>summary,.operator-account__detail>summary{cursor:pointer;min-height:44px;display:flex;align-items:center;gap:9px;list-style:none;font-size:13px}
.operator-account__actions details summary:after,.operator-account__plan>summary:after,.operator-account__detail>summary:after{content:'+';font-size:17px}
.operator-account details[open]>summary:after{content:'−'}
.operator-account__actions details>div{display:flex;flex-wrap:wrap;gap:8px}
.operator-account__plan{border-bottom:1px solid var(--border);padding-bottom:4px}
.operator-account__plan>summary{font-weight:600}
.operator-account__plan>div{padding:4px 0 16px}
.operator-account__filters{display:flex;align-items:end;flex-wrap:wrap;gap:12px}
.operator-account__filters label{display:grid;gap:6px;min-width:125px;flex:1;font-size:12px;color:var(--text-secondary)}
.operator-account__filters input,.operator-account__filters select{width:100%;min-height:42px;min-width:0;font-size:13px}
.operator-account__filter-options{display:contents}
.operator-account__more-filters{display:none}
.operator-account__filter-note{margin:0;width:100%;font-size:12px;color:var(--text-secondary)}
.operator-account__error{color:var(--danger,#a33b30);margin:0;width:100%;font-size:13px}
.operator-account__trend{border:1px solid var(--border);border-radius:12px;padding:16px 20px;background:var(--bg-elevated)}
.operator-account__trend header{display:flex;gap:12px;align-items:baseline;justify-content:space-between}
.operator-account__trend h3,.operator-account__selection h3{font-size:15px;margin:0}
.operator-account__trend header>span{font-size:12px;color:var(--text-secondary)}
.operator-account__months{display:flex;align-items:end;gap:8px;overflow-x:auto;overscroll-behavior-x:contain;padding-top:15px}
.operator-account__months button{flex:1;min-width:48px;display:grid;gap:6px;border:0;border-radius:6px;background:transparent;padding:4px 8px;color:var(--text-secondary);font:inherit;font-size:11px;cursor:pointer}
.operator-account__months button:hover{background:var(--bg-hover)}
.operator-account__bars{height:64px;display:flex;gap:4px;align-items:end;justify-content:center;border-bottom:1px solid var(--border)}
.operator-account__bars i,.operator-account__bars b{width:14px;max-height:64px;border-radius:3px 3px 0 0;display:block;background:#2f7d6b;transition:height .18s ease}
.operator-account__bars b{background:#b98a42}
.operator-account__legend{display:flex;align-items:center;flex-wrap:wrap;gap:18px;font-size:11px;color:var(--text-secondary);margin:12px 0 0}
.operator-account__legend>span:before{content:'';display:inline-block;width:8px;height:8px;border-radius:2px;background:#2f7d6b;margin-right:5px}
.operator-account__legend>span+span:before{background:#b98a42}
.operator-account__legend small{margin-left:auto;font-size:11px}
.operator-account__selection{display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:14px}
.operator-account__selection p{margin:5px 0 0;font-size:12px;color:var(--text-secondary)}
.operator-account__selection nav{display:flex;align-items:center;gap:8px;font-size:12px;color:var(--text-secondary)}
.operator-account__selection nav>span{margin-right:6px;font-variant-numeric:tabular-nums}
.operator-account__entries{min-width:0}
.operator-account__row{display:grid;grid-template-columns:86px minmax(180px,1fr) 130px 130px 64px;gap:18px;align-items:center;padding:14px 0;border-top:1px solid var(--border);font-size:13px;min-width:0}
.operator-account__row time{font-size:12px;color:var(--text-secondary);font-variant-numeric:tabular-nums}
.operator-account__entry,.operator-account__state{display:grid;gap:5px;min-width:0}
.operator-account__entry span{line-height:1.4;overflow-wrap:anywhere}
.operator-account__entry a{color:var(--text-primary);text-underline-offset:3px}
.operator-account__entry small,.operator-account__state small{font-size:11px;color:var(--text-secondary)}
.operator-account__state .badge{justify-self:start}
.operator-account__amount{text-align:right;font-variant-numeric:tabular-nums;white-space:nowrap}
.operator-account__amount.is-outgoing{color:var(--text-secondary)}
.operator-account__detail[open]{grid-column:1/-1;border-left:2px solid var(--border);padding-left:14px}
.operator-account__detail p{margin:4px 0;font-size:12px;overflow-wrap:anywhere;color:var(--text-secondary)}
.operator-account__detail button{margin-top:10px}
.operator-account__empty{padding:30px 0;color:var(--text-secondary);font-size:14px}
@media(max-width:1000px){.operator-account__row{grid-template-columns:78px minmax(140px,1fr) 110px 110px;gap:12px}.operator-account__detail{grid-column:2/-1}.operator-account__detail>summary{min-height:30px}.operator-account__actions{margin-left:0}}
@media(max-width:600px){
 [data-operator-section=ledger] #pd-groups,[data-operator-section=ledger] #pd-edit{display:none}
 .operator-account,.operator-account__journal{gap:14px}
 .operator-account__head{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:12px;padding:10px 0}
 .operator-account__head h2{font-size:27px}
 .operator-account__head dl{display:grid;gap:8px;text-align:right}
 .operator-account__head dt{font-size:11px;margin-bottom:2px}
 .operator-account__head dd{font-size:14px}
 .operator-account__head p{max-width:160px;line-height:1.4;font-size:11px}
 .operator-account__actions{grid-column:1/-1;width:100%;gap:12px}
 .operator-account__actions>button{min-height:44px}
 .operator-account__filters{gap:8px}
 .operator-account__filters label{flex-basis:calc(50% - 8px);min-width:0;gap:4px}
 .operator-account__filters>button{min-height:44px}
 .operator-account__more-filters{display:inline-flex;align-items:center;justify-content:center;order:2}
 .operator-account__filter-options{display:none;order:1;width:100%;gap:8px;flex-wrap:wrap}
 .operator-account__filters[data-expanded=true] .operator-account__filter-options{display:flex}
 .operator-account__filters>button[type=submit],.operator-account__filters>[data-account-reset]{order:2}
 .operator-account__filter-note,.operator-account__error{order:3;line-height:1.4}
 .operator-account__filter-note{font-size:11px}
 .operator-account__trend{padding:12px}
 .operator-account__trend header{display:flex;align-items:start;gap:10px}
 .operator-account__trend header>span{font-size:11px;max-width:110px;text-align:right}
 .operator-account__trend h3{font-size:14px}
 .operator-account__months{padding-top:8px}
 .operator-account__bars{height:40px}
 .operator-account__legend{gap:12px;margin-top:8px}
 .operator-account__legend small{margin-left:0;width:100%}
 .operator-account__selection{gap:8px}
 .operator-account__selection nav{width:100%;justify-content:space-between}
 .operator-account__row{grid-template-columns:minmax(0,1fr) auto;gap:7px 12px;align-items:start}
 .operator-account__row time{grid-column:1/-1}
 .operator-account__entry{grid-column:1;grid-row:2}
 .operator-account__entry a{display:inline-flex;min-height:44px;align-items:center}
 .operator-account__amount{grid-column:2;grid-row:2;font-size:13px}
 .operator-account__state{grid-column:1;grid-row:3}
 .operator-account__detail{grid-column:2;grid-row:3}
 .operator-account__detail>summary{min-height:44px}
 .operator-account__detail[open]{grid-column:1/-1;grid-row:4}
}
@media(prefers-reduced-motion:reduce){.operator-account__bars i,.operator-account__bars b{transition:none}}

/* A payment selection stays attached to its original operator account. */
.operator-account__due { margin: 0 0 20px; padding: 16px; border: 1px solid var(--line); border-radius: 12px; background: var(--panel); }
.operator-account__due > header { display: flex; align-items: center; justify-content: space-between; gap: 14px; flex-wrap: wrap; }
.operator-account__due > header span, .operator-account__due > p { color: var(--muted); font-size: 13px; }
.operator-account__due h3 { margin: 5px 0 0; font-size: 24px; font-variant-numeric: tabular-nums; }
.operator-account__due-periods { display: flex; flex-wrap: wrap; gap: 8px; margin: 12px 0; }
.operator-account__due-periods button { display: flex; align-items: center; gap: 12px; min-height: 44px; flex-wrap: wrap; }
.operator-account__due-periods strong { font-variant-numeric: tabular-nums; }
.operator-account__due button:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
.operator-payment-plan__unavailable { padding: 12px 0; color: var(--muted); }
@media (max-width:600px) {
 .operator-account__due { padding: 12px; }
 .operator-account__due-periods { display: grid; grid-template-columns: minmax(0,1fr); }
 .operator-account__due-periods button { justify-content: space-between; width: 100%; }
 .operator-account__due h3 { font-size: 21px; }
}
/* ============================================================
   Patch-Integration — Namensraum tp- (Provision des eigenen Teams); Quelle: docs/design/patch-teamprovision.css
   ============================================================ */
/* Paket C «Provision des eigenen Teams» — Namensraum .tp-*

   Drei Orte teilen sich dieses Blatt, weil sie EINE Sache zeigen:
     · #/a/einstellungen?bereich=teamprovision  (views/admin-teamprovision.js)
       die Pflegestelle — der Satz für alle, mit Geltung ab Datum und Verlauf
     · #/m/team-provision                        (views/team-provision.js)
       die Leute, ihr Stand und der Lauf mit Prüfschritt
     · der Streifen «Meine Provision» auf «Heute» (views/advisor-leads.js)
       und der Weg ins Dossier in der Personen-Liste (.tp-namensweg)

   KEINE NEUE FARBE, KEIN NEUER ABSTAND. Alles kommt aus den Tokens:
   --surface-inset, --border, --text-primary/-secondary/-tertiary, --accent,
   --medium. Kacheln sind .stat (kennzahl-kachel.js), Kästen sind .panel,
   Knöpfe sind .primary-btn/.ghost-btn, Kopf und Schrittleiste der Lauf-Fläche
   kommen aus patch-abrechnungslauf.css (Namensraum ar-) — dieselbe Bauform
   wie die beiden anderen Läufe des Hauses, kein zweites Bild dafür.

   HANDY ZUERST GEDACHT (Grundgesetz 6). Auf 390 px stehen die Kacheln
   untereinander, jede Personenzeile bricht in drei Blöcke um, jeder Knopf
   nimmt die volle Breite und trägt 44 px Höhe, und kein Name läuft seitlich
   hinaus — lange Namen brechen im Wort. */

/* --- Kopf der Pflegestelle ------------------------------------------------ */
.tp-kopf { align-items: flex-start; gap: 12px 20px; flex-wrap: wrap; }
.tp-kopf > div { min-width: 0; flex: 1 1 260px; }
.tp-kopf .primary-btn { min-height: 44px; flex: none; }

/* --- Die Kästen ----------------------------------------------------------- */
.tp-panel { padding: 16px 20px; margin-top: 16px; min-width: 0; }
.tp-panel .panel__header { padding: 0 0 12px; margin: 0; }
.tp-seit { font-size: 12.5px; color: var(--text-tertiary); white-space: nowrap; }

/* Eine geplante Fassung ist eine Tatsache mit Datum, keine Randnotiz — aber
   auch keine Warnung. Etwas, für das heute NICHTS gilt, ist eines. */
.tp-panel--geplant { border-color: var(--accent-line); }
.tp-panel--warn { border-color: var(--warn); }

.tp-note { font-size: 12.5px; color: var(--text-secondary); margin: 10px 0 0; }
.tp-satz {
  margin: 12px 0 0; padding: 10px 12px;
  background: var(--surface-inset); border-radius: var(--radius-button);
  font-size: 13px; color: var(--text-primary); overflow-wrap: anywhere;
}

/* --- Kennzahlen ----------------------------------------------------------- */
/* Auto-fit statt fester Spaltenzahl: vier Kacheln am Rechner, eine Spalte am
   Handy — ohne einen zweiten Umbruchpunkt zu erfinden. */
.tp-kacheln {
  display: grid; gap: 10px;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
}
.tp-kacheln .stat { min-width: 0; }

/* --- Eine Zeile: Abweichung, Vorschau, Befund ----------------------------- */
.tp-zeilen { display: grid; gap: 8px; margin-top: 4px; }
.tp-zeile {
  display: grid; gap: 3px; min-height: 44px;
  padding: 10px 12px; min-width: 0;
  background: var(--surface-inset); border: 1px solid var(--border);
  border-radius: var(--radius-button);
  color: inherit; text-decoration: none;
}
a.tp-zeile:hover { border-color: var(--accent); }
.tp-zeile--warn { border-color: var(--warn); }
.tp-zeile__kopf {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 10px; min-width: 0;
}
.tp-zeile__kopf strong { font-size: 13.5px; color: var(--text-primary); overflow-wrap: anywhere; }
.tp-zeile__ab { font-size: 12px; color: var(--text-tertiary); margin-left: auto; white-space: nowrap; }
.tp-zeile__text { font-size: 12.5px; color: var(--text-secondary); overflow-wrap: anywhere; }
.tp-zeile__grund { font-size: 12px; color: var(--text-tertiary); overflow-wrap: anywhere; }

/* --- Die Leute auf der Lauf-Fläche ---------------------------------------- */
.tp-leute { display: grid; gap: 8px; }
.tp-person {
  display: grid; gap: 8px 16px; align-items: center;
  grid-template-columns: minmax(160px, 1.4fr) minmax(220px, 1.6fr) auto;
  padding: 10px 12px; min-width: 0;
  background: var(--surface-inset); border: 1px solid var(--border);
  border-radius: var(--radius-button);
}
.tp-person__wer { display: grid; gap: 2px; min-width: 0; }
.tp-person__satz { font-size: 12px; color: var(--text-tertiary); overflow-wrap: anywhere; }
.tp-person__geld { display: flex; flex-wrap: wrap; gap: 4px 18px; min-width: 0; }
.tp-person__geld span { display: grid; gap: 1px; }
.tp-person__geld small { font-size: 11px; color: var(--text-tertiary); }
.tp-person__geld b { font-size: 13.5px; color: var(--text-primary); font-variant-numeric: tabular-nums; }
.tp-person__griffe { display: flex; flex-wrap: wrap; gap: 8px; justify-content: flex-end; }
.tp-person__griffe .ghost-btn,
.tp-person__griffe .primary-btn { min-height: 44px; }

/* Der Name IST der Weg ins Dossier — hier und in der Personen-Liste
   (views/manager-team.js). Ein Knopf, der wie Text aussieht, aber wie eine
   Tür wirkt: Farbe erben, kein Rahmen, 44 px Griff. */
.tp-person__name,
.tp-namensweg {
  background: none; border: 0; padding: 0; margin: 0;
  font: inherit; color: inherit; text-align: left; cursor: pointer;
  /* `break-word`, nicht `anywhere`: mit `anywhere` ist die kleinste Breite
     der Namensspalte EIN Buchstabe — sobald die Nachbarspalten (Chips in
     Versalien) druecken, fiel der Name auf 35 px und drei Zeilen (Breiten-
     probe 03.09., team@768/1024). Das laengste Wort bleibt ganz. */
  min-height: 44px; overflow-wrap: break-word;
}
.tp-person__name:hover,
.tp-namensweg:hover { color: var(--accent); }
.tp-person__name:focus-visible,
.tp-namensweg:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* --- Quittung und Bericht des Laufs --------------------------------------- */
.tp-quittung {
  display: grid; gap: 2px; margin-top: 12px; padding: 10px 12px;
  background: var(--surface-inset); border-radius: var(--radius-button);
}
.tp-quittung strong { font-size: 14px; color: var(--text-primary); }
.tp-quittung span { font-size: 12.5px; color: var(--text-secondary); }
.tp-bericht { margin-top: 14px; }
.tp-bericht h3 {
  font-size: 13px; color: var(--text-secondary); margin: 14px 0 6px;
  text-transform: none; letter-spacing: 0;
}

/* --- «Meine Provision» auf «Heute» ---------------------------------------- */
.tp-streifen .panel__hint { color: var(--text-tertiary); font-weight: 400; }
.tp-meine { list-style: none; margin: 10px 0 0; padding: 0; display: grid; gap: 6px; }
.tp-meine li {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 14px;
  padding: 8px 10px; min-width: 0;
  background: var(--surface-inset); border-radius: var(--radius-button);
  font-size: 12.5px; color: var(--text-secondary);
}
.tp-meine li strong {
  margin-left: auto; font-size: 13.5px; color: var(--text-primary);
  font-variant-numeric: tabular-nums;
}
.tp-meine li small { font-size: 11.5px; color: var(--text-tertiary); }

/* --- Handy ---------------------------------------------------------------- */
@media (max-width: 640px) {
  .tp-panel { padding: 14px 14px; }
  .tp-kopf .primary-btn { width: 100%; }
  .tp-kacheln { grid-template-columns: 1fr; }
  .tp-zeile__ab { margin-left: 0; }
  .tp-person { grid-template-columns: 1fr; }
  .tp-person__griffe { justify-content: flex-start; }
  .tp-person__griffe .ghost-btn,
  .tp-person__griffe .primary-btn { flex: 1 1 100%; }
  .tp-meine li strong { margin-left: 0; }
}

/* ============================================================
   Patch-Integration — Namensraum la- (Lead-Akte); Quelle: docs/design/patch-leadakte.css
   ============================================================ */
/* DIE LEAD-AKTE — Namensraum `la-` (Welle 2, Paket A, 18.08.2026).
   Fläche: public/src/views/lead-akte.js · Route #/lead/:id

   WAS HIER STEHT UND WARUM SO WENIG: die Akte trägt das KLEID DES DOSSIERS
   (`admin-page gz`, `gz-kopf pd2-kopf`, `pd2-tabs`, `pd2-kpis`, `pd2-acts`,
   `panel`, `stat`, `table-wrap`, `sl-badge`, `activity-item`, `info-card`,
   `objection-card`, `appt-card`) — dieselben Bauteile wie die Akte des
   Standortbetreibers und die fünf Reiter, die aus dem Fenster hierher gezogen
   sind. Neu ist nur, was es im Haus noch NICHT gibt: die Nachbarschafts-Liste
   (BEREICHE §6), die Schritt-Zeile (§7.2) und der Kennzahlen-Streifen dieser
   Akte. Alles andere wäre ein zweites Kleid für dasselbe (BEREICHE §10). */

/* --- 0. Der Name auf der Lead-Karte ist ein WEG --------------------------- */
/* BEREICHE §6: «Jeder Name, der auf ein anderes Ding zeigt, ist ein Weg
   dorthin.» Der Firmenname führt seit dem 18.08. auf `#/lead/:id`. Er soll
   dabei aussehen wie zuvor — die Karte ist als Ganzes anklickbar, ein blau
   unterstrichener Name mitten darin wäre ein zweites Versprechen. */
.firm-card__weg { color: inherit; text-decoration: none; }
.firm-card__weg:hover { text-decoration: underline; }
.firm-card__weg:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: var(--radius-card); }
/* DIE TAPFLÄCHE OHNE DIE HÖHE (Muster: patch-pool.css «pool-weg»). Der Name
   ist 19 px hoch — unter dem Maus-Boden 24. Ihn wirklich höher zu setzen
   würde die Zeilenhöhe jeder Karte ändern, also die Gestalt. Stattdessen
   bleibt der Text, wie er ist, und die FANGFLÄCHE wird 24 px: mittig über
   ihm, dem Anker selbst gehörend. `position:relative` steht nicht am `<a>`,
   sondern muss dazu — ohne ihn hinge das Kästchen an der Karte. */
.firm-card__weg { position: relative; }
.firm-card__weg::after {
  content: ""; position: absolute; left: 0; right: 0; top: 50%;
  height: 24px; transform: translateY(-50%);
}
/* Am Finger sind es 44. Gemessen 26.08.2026 auf 390/430/768/1024 px, in
   BEIDEN Achsen: die Fangfläche ist genau so breit wie der Name (x 62–257 auf
   390), die Auswahlbox steht links davon (x 27–49), Telefon und Netz rechts
   bzw. eine Zeile tiefer (y 265–309). Sie überdeckt auf keiner der vier
   Breiten irgendeinen Nachbargriff — und selbst ein Fehltipp landete auf der
   Karte, die an dieselbe Stelle führt (manager-pool.js). */
@media (max-width: 1024px), (pointer: coarse) {
  .firm-card__weg::after { height: 44px; }
}

/* --- 1. Der nächste Schritt: Satz links, Knopf rechts --------------------- */
/* §7.2 «Der nächste Schritt ist ein Knopf, kein Satz» — der Satz bleibt daneben
   stehen, damit man weiss WARUM, aber gedrückt wird der Knopf. */
/* Kleid, Etikett und Frage kommen aus dem EINEN Frage-Kopf in grund.css
   (`.panel.frage-kopf`, v397); hier nur die Anordnung. Er steht im Akten-Kopf
   über den Kennzahlen (Slot `frage`, components/akte-kopf.js). */
.la-schritt {
  display: flex; align-items: center; gap: 14px 18px; flex-wrap: wrap;
  margin-bottom: 14px;
}
.la-schritt__text { display: flex; flex-direction: column; gap: 4px; min-width: 0; flex: 1 1 240px; }
.la-schritt__fall { font-size: 12px; color: var(--text-secondary); }

/* --- 2. Die Notiz -------------------------------------------------------- */
/* Sie steht dort, wo sie gelesen wird, und wird dort geändert — ein Feld
   braucht keinen eigenen Kasten (BEREICHE §5). */
.la-notiz { padding: 14px 16px; margin-bottom: 14px; }
.la-notiz__text { margin: 6px 0 0; white-space: pre-wrap; }
.la-notiz__akt { display: flex; justify-content: flex-end; margin-top: 8px; }

/* --- 3. Die Nachbarn ----------------------------------------------------- */
/* «Jede Beziehung ist ein Weg, in beide Richtungen» (BEREICHE §6). Zwei
   Spalten am Rechner, eine am Telefon — feste Spaltenzahl, damit die Regel
   «die ersten ZWEI tragen keine Trennlinie» auch stimmt. */
.la-nachbarn { padding: 14px 16px; margin-bottom: 14px; }
.la-nachbarn__liste {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0;
}
.la-nachbar {
  display: flex; align-items: center; gap: 10px; min-width: 0;
  padding: 11px 12px; border: 0; border-top: 1px solid var(--border);
  background: transparent; color: inherit; text-align: left; text-decoration: none;
  font: inherit;
}
.la-nachbar:nth-child(1), .la-nachbar:nth-child(2) { border-top: 0; }
.la-nachbar--weg { cursor: pointer; }
.la-nachbar--weg:hover { background: rgba(var(--tint-rgb), .05); }
.la-nachbar--weg:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.la-nachbar__ic { --gz-ic-gr: 26px; flex: 0 0 auto; }
.la-nachbar__text { display: flex; flex-direction: column; gap: 1px; min-width: 0; flex: 1 1 auto; }
.la-nachbar__wort {
  font-size: 11px; letter-spacing: .08em; text-transform: uppercase;
  color: var(--text-secondary);
}
.la-nachbar__titel {
  font-size: 13.5px; font-weight: 600;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.la-nachbar__sub {
  font-size: 11.5px; color: var(--text-secondary);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Der Pfeil steht NUR an einem Weg — an einer Zeile ohne Ziel wäre er ein
   Versprechen ohne Deckung (BEREICHE §11.2). */
.la-nachbar__pfeil { flex: 0 0 auto; color: var(--text-secondary); display: inline-flex; }
.la-nachbar__pfeil svg { width: 16px; height: 16px; }

/* --- 4. Der Kennzahlen-Streifen ------------------------------------------ */
/* Jede Zahl ist eine Tür in den Reiter, der sie erklärt (BEREICHE §5) — darum
   sind es Knöpfe, keine Kästen. Sie sollen trotzdem aussehen wie die Kacheln
   der anderen Akten; die Knopf-Vorgaben des Browsers werden dafür abgeräumt. */
.la-kacheln {
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 14px;
}
/* Wer die Offerten nicht lesen DARF, bekommt keine Kachel mit einer erfundenen
   Null (BEREICHE §11.2/§11.6) — die Reihe traegt dann drei und laesst kein Loch
   stehen. Gegenpruefung 18.08. */
.la-kacheln--drei { grid-template-columns: repeat(3, minmax(0, 1fr)); }
/* EINE KACHEL-BAUART (25.08.): dieselbe Karte wie `.stat` — `--surface`
   statt `--surface-1`, Radius 14 statt 12, `18px 20px` statt `12px 14px`.
   Die Lead-Akte war die einzige Flaeche mit einer EINGELASSENEN Kachel
   (`--surface-1` liegt TIEFER als der Grund) — dieselbe Zahl sah dort aus
   wie ein Formularfeld und drei Reiter weiter wie eine Karte. */
.la-kachel {
  display: flex; flex-direction: column; gap: 2px; align-items: flex-start;
  border: 1px solid var(--border); background: var(--surface);
  font: inherit; color: inherit; text-align: left; cursor: pointer;
  border-radius: var(--radius-card); padding: 18px; min-width: 0;
}
.la-kachel:hover { background: var(--surface-hover); border-color: var(--line-strong); }
.la-kachel:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* Der Wert ist meist eine Zahl, manchmal ein kurzes Wort («heute 14:00»).
   Beides muss in dieselbe Kachel passen, auch am Telefon — darum waechst die
   Schrift mit der Breite, statt eine feste Groesse zu erzwingen. */
.la-kachel .stat__value { font-variant-numeric: tabular-nums; font-size: clamp(17px, 2.1vw, 26px); }
.la-kachel .stat__sub {
  font-size: 11.5px; color: var(--text-secondary); max-width: 100%;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* --- 5. Kopfzeile: die Nummer ist ein Weg, die Priorität ein Chip --------- */
.la-tel { color: inherit; text-decoration: none; display: inline-flex; align-items: center; gap: 4px; position: relative; }
.la-tel:hover { text-decoration: underline; }
/* Am FINGER trägt die Nummer längst 44 px (§8 unten). Am Rechner mass sie
   98.5 x 21.3 — unter dem Maus-Boden 24. Auch hier die Fangfläche statt der
   Höhe: die Kennzeile der Akte behält ihren Zeilenfall. */
.la-tel::after {
  content: ""; position: absolute; left: 0; right: 0; top: 50%;
  height: 24px; transform: translateY(-50%);
}
.la-tel svg { width: 14px; height: 14px; }
.la-prio--hoch { border-color: var(--warn-strong); }
.la-warn { color: var(--low); }

/* --- 6. Die Abschnitte der Reiter ---------------------------------------- */
.la-abschnitt { padding: 14px 16px; margin-bottom: 14px; }
.la-abschnitt > .panel__title { margin-top: 0; }

/* COS-Etappe 0.4 (01.09.2026) — «Warum es zuletzt so ausging» in der Übersicht.
   EINE Deklaration, und sie sagt etwas: dieselbe Inset-Bar wie der Ergebnis-
   Eintrag im Verlauf (`.activity-item--outcome`, grund.css:2943-2947). Beide
   Orte zeigen DIESELBE Tatsache — der Akzent sagt dem Auge, dass es dieselbe
   Sache ist, und nicht zwei. Kein Rahmen, keine Fläche, kein Aufsehen: der
   Block steht unter «Nächster Schritt» und darf ihn nicht überstimmen.
   (Eine Klasse ohne Regel wäre stumm — genau der Fehler, den `today-more--tuer`
   am selben Tag hatte.) */
.la-ergebnis { box-shadow: inset 2.5px 0 0 var(--accent); }
.la-ergebnis .outcome-block__head { margin-bottom: 8px; }

/* COS-Etappe 0.2 (01.09.2026) — «Was sonst noch bekannt ist», eingeklappt.
   Der Ausklapper folgt Zeichen für Zeichen `.ku-mehr` (patch-offerte.css:248):
   dieselbe Frage, dieselbe Anmutung, derselbe Pfeil. Ein zweites Aussehen für
   «mehr zeigen» wäre genau der Wildwuchs, den `_muster_test.mjs` verbietet.
   min-height 46px trägt den Griff-Boden; `list-style:none` + der eigene Pfeil
   ersetzen das Browser-Dreieck, das in keiner Engine gleich aussieht. */
.la-restwissen > details > summary {
  display: flex; align-items: center; gap: 8px;
  min-height: 46px; cursor: pointer;
  font-size: 13px; font-weight: 550; color: var(--text-secondary);
  list-style: none;
}
.la-restwissen > details > summary::-webkit-details-marker { display: none; }
.la-restwissen > details > summary::after {
  content: '';
  margin-left: auto; width: 8px; height: 8px;
  border-right: 1.6px solid currentColor;
  border-bottom: 1.6px solid currentColor;
  transform: rotate(45deg) translate(-2px, -2px);
  transition: transform var(--transition);
}
.la-restwissen > details[open] > summary::after { transform: rotate(-135deg) translate(-2px, -2px); }
.la-restwissen > details > summary:hover { color: var(--text-primary); }
.la-restwissen > details > .modal-grid { margin-top: 10px; }

/* --- 7. Die Kennzeile ist ein SATZ, keine Reihe von Kacheln --------------- */
/* Dieselbe Vorsicht wie in der Rechnungs-Akte: die Kennung darf am Telefon
   nie umbrechen (BEREICHE §5). */
body.lx-leadakte .pd2-kopf__meta { line-height: 1.7; max-width: 100%; }
body.lx-leadakte .pd2-kopf__meta .lx-kennung { white-space: nowrap; }

/* --- 7b. Eine Angabe und woher sie kommt (COS 1) -------------------------- */
/* Die Herkunft steht UNTER dem Wert und ist leiser als er: sie beantwortet
   eine Rückfrage, sie stellt keine. Kein Rahmen, kein Feld, keine Kachel —
   es ist derselbe Gedanke wie die Kennzeile oben (Abschnitt 7): ein Satz,
   keine Reihe von Behältern.

   Der Rohtext bleibt sichtbar, aber am leisesten. Er ist der Beleg, mit dem
   sich eine Fehl-Trennung nachweisen lässt; ihn zu verstecken hiesse, dem
   Berater das Original zu nehmen, sobald die Maschine sich einmal irrt. */
.la-aussage__wert { margin: 2px 0 0; }
.la-aussage__herkunft {
  margin: 1px 0 0;
  font-size: 11.5px; line-height: 1.45;
  color: var(--text-tertiary, var(--text-secondary));
}
.la-aussage__roh {
  margin: 6px 0 0;
  font-size: 11px; line-height: 1.4;
  color: var(--text-tertiary, var(--text-secondary));
  opacity: .72;
}

/* WIDERSPRUCH: eigenes Wort, eigene Kante — nie Farbe allein. Ein farbenblindes
   Auge sieht die Kante und liest das Wort; beides trägt für sich. Die Kante
   sitzt links, weil dort das Auge die Karte beginnt, und ist schmal genug,
   dass sie die Rasterbreite der Nachbarkarten nicht verschiebt. */
.la-aussage--streitig {
  border-left: 2px solid var(--warn, var(--text-secondary));
  padding-left: 10px;
}
.la-aussage__streit {
  margin-left: 6px;
  font-size: 11px; font-weight: 550;
  color: var(--warn, var(--text-secondary));
  white-space: nowrap;
}
/* Zwei Angaben untereinander brauchen eine Zäsur, sonst liest sich die
   zweite Herkunft als Fortsetzung der ersten. */
.la-aussage--streitig .la-aussage__wert + .la-aussage__herkunft + .la-aussage__wert {
  margin-top: 8px; padding-top: 8px;
  border-top: 1px solid var(--border);
}

/* --- 8. Handy ------------------------------------------------------------ */
/* Tapflächen-Boden auf JEDEM Touch-Gerät, nicht erst unter 640px
   (Memory project_tablet_touch_breakpoint: 768/1024 sind die Bruchzone). */
@media (max-width: 1024px), (pointer: coarse) {
  body.lx-leadakte .la-nachbar,
  body.lx-leadakte .la-kachel,
  body.lx-leadakte .icon-btn,
  body.lx-leadakte .appt-link-btn,
  body.lx-leadakte .ghost-btn,
  body.lx-leadakte .primary-btn,
  body.lx-leadakte .pd2-act,
  body.lx-leadakte .modal__tab { min-height: 44px; }
  body.lx-leadakte .la-tel { min-height: 44px; }
}
@media (max-width: 900px) {
  .la-kacheln { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 640px) {
  .la-nachbarn__liste { grid-template-columns: minmax(0, 1fr); }
  /* Einspaltig gibt es keine zweite Zelle in Zeile 1 — nur die ERSTE steht
     ohne Trennlinie. */
  .la-nachbar:nth-child(2) { border-top: 1px solid var(--border); }
  .la-schritt { align-items: stretch; }
  .la-schritt .primary-btn, .la-schritt .ghost-btn { width: 100%; }
  body.lx-leadakte .editable-grid { grid-template-columns: minmax(0, 1fr); }
}

/* --- 9. COS-Etappe 2/3 (02.09.2026): Eignung, Gespraech, Personen, Einstieg --- */
/* Ein Urteil je Zielart: Zielart, Klasse, Satz — eine Zeile (`panel-row`,
   der Listen-Kanon des Hauses), kein Kasten.
   Gesetzt schlaegt gerechnet; das Wort «gesetzt» steht dabei, damit ein
   Berater sieht, ob ein Mensch oder eine Regel geurteilt hat. */
.la-eignung__zeile { display: grid; grid-template-columns: minmax(120px, 1fr) auto; gap: 2px 12px; align-items: baseline; }
.la-eignung__ziel { font-weight: 600; }
.la-eignung__klasse { font-size: 12.5px; color: var(--text-secondary); white-space: nowrap; }
.la-eignung__klasse--1 { color: var(--high, var(--text-primary)); font-weight: 600; }
.la-eignung__klasse--4 { color: var(--text-tertiary); }
.la-eignung__satz { grid-column: 1 / -1; font-size: 12.5px; line-height: 1.45; color: var(--text-secondary); }
.la-eignung__satz b { font-weight: 550; color: var(--text-tertiary); }
.la-eignung__fuss { margin: 10px 0 0; display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }

/* Das Gespraech: was der Kunde gesagt hat (Zeilen) und die EINE naechste
   Frage (ein Satz, ein Knopf). Nie ein Fragebogen. */
.la-gespraech__liste { margin: 0 0 10px; }
.la-gespraech__zeile { display: flex; gap: 10px; align-items: baseline; font-size: 13.5px; }
.la-gespraech__was { flex: 0 0 auto; color: var(--text-secondary); font-size: 12.5px; min-width: 120px; }
.la-gespraech__wort { font-weight: 550; }
.la-gespraech__wann { margin-left: auto; font-size: 11.5px; color: var(--text-tertiary); white-space: nowrap; }
.la-gespraech__frage { display: flex; gap: 10px; align-items: center; flex-wrap: wrap;
  padding: 10px 12px; border-radius: var(--radius-card); background: var(--surface-2);
  box-shadow: inset 2.5px 0 0 var(--accent); }
.la-gespraech__frage-text { flex: 1 1 220px; font-size: 14px; font-weight: 600; }
.la-gespraech__fertig { font-size: 12.5px; color: var(--text-tertiary); margin: 0; }

/* Personen an der Firma: Name fuehrt, Rolle und Haltung daneben, Kontakt darunter. */
.la-personen__liste { margin: 0 0 10px; }
.la-person { display: grid; grid-template-columns: 1fr auto; gap: 2px 10px; align-items: baseline; }
.la-person__name { font-weight: 600; }
.la-person__rolle { font-size: 12.5px; color: var(--text-secondary); }
.la-person__meta { grid-column: 1 / -1; display: flex; flex-wrap: wrap; gap: 4px 12px; font-size: 12.5px; color: var(--text-secondary); }
.la-person__griffe { display: flex; gap: 6px; }
.la-person__griffe .ghost-btn { min-height: 36px; padding: 6px 10px; font-size: 12.5px; }
.la-person__entscheider { font-size: 11px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--accent-strong); }

/* Der Einstieg als Feld: das Original bleibt unter dem Feld lesbar. */
.la-einstieg__feld { width: 100%; min-height: 120px; resize: vertical; font: inherit; font-size: 14px; line-height: 1.5;
  padding: 10px 12px; border-radius: var(--radius-card); border: 1px solid var(--border); background: var(--surface); color: var(--text-primary); }
.la-einstieg__griffe { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 8px; align-items: center; }
.la-einstieg__warnung { margin: 8px 0 0; padding: 9px 12px; border-radius: var(--radius-card);
  background: rgba(var(--warn-rgb), .07); box-shadow: inset 2.5px 0 0 var(--warn);
  font-size: 12.5px; color: var(--warn-strong); }
.la-einstieg__original { margin: 10px 0 0; font-size: 12px; line-height: 1.45; color: var(--text-tertiary); }
.la-einstieg__original summary { cursor: pointer; min-height: 36px; display: flex; align-items: center; }

/* --- 10. COS-Etappe 4 (02.09.2026): Versprochen · Eingetreten --- */
/* Je gesendeter Offerte eine Zeile (`panel-row`, kein Kasten): links das
   Versprechen (aus der Offerte), rechts die Wirkung (was der Kunde nannte) —
   nebeneinander, nie verrechnet.
   Fehlt die Zahl, steht «nicht erhoben»; nichts wird geschaetzt. Dieselben
   Klassen tragen den Block in der Lead-Akte und in der Kundenakte. */
.la-wirkung__zeile { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 4px 16px; }
.la-wirkung__kopf { grid-column: 1 / -1; display: flex; gap: 10px; align-items: baseline; flex-wrap: wrap; }
.la-wirkung__nr { font-weight: 600; }
.la-wirkung__zeit { margin-left: auto; font-size: 11.5px; color: var(--text-tertiary); white-space: nowrap; }
.la-wirkung__spalte { display: grid; gap: 2px; min-width: 0; }
.la-wirkung__titel { font-size: 11.5px; letter-spacing: .02em; text-transform: uppercase; color: var(--text-tertiary); }
.la-wirkung__wert { font-size: 13.5px; line-height: 1.45; overflow-wrap: anywhere; }
.la-wirkung__wert--zahl { font-size: 20px; font-weight: 600; line-height: 1.2; font-variant-numeric: tabular-nums; }
.la-wirkung__wert--offen { color: var(--text-secondary); }
.la-wirkung__herkunft { font-size: 11.5px; color: var(--text-tertiary); }
.la-wirkung__fuss { grid-column: 1 / -1; display: flex; gap: 8px; flex-wrap: wrap; align-items: center; margin-top: 2px; }
.la-wirkung__fuss .ghost-btn { min-height: 44px; }
@media (max-width: 480px) {
  .la-wirkung__zeile { grid-template-columns: minmax(0, 1fr); }
}

/* --- 11. WERBEWEGE (06.09.2026): was ein Weg WIRKLICH gekostet hat --- */
/* Owner 06.09.: «wenn jemand sagt ja ich 3000 Fr. investiere ich lieber in
   Social Media dann habe ich viel mehr Anfragen — aber viel mehr ist ja nicht
   immer gleich besser.» Zwei Wege nebeneinander, jeder mit seinen Eingaben und
   direkt darunter seiner Rechnung. Kopf, Sachverhalte und Farben kommen aus
   grund.css (frage-kopf, sachverhalt) — hier steht nur das Layout.
   Bauteil: components/wegvergleich.js */
.wv__spalten { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; margin-top: 14px; }
/* min-width: 0 ist Pflicht, nicht Kosmetik: ein Grid-Kind waechst sonst mit
   seinem laengsten Wort ueber die Spalte hinaus, und weil ein Vorfahr clippt,
   gaebe es keinen Scrollbalken — nur fehlenden Text (Owner-Vorfall 31.08.). */
/* SPALTE ALS SAEULE, DAMIT DIE ZWEI ERGEBNISSE AUF EINER LINIE STEHEN
   (06.09.2026). Seit die linke Spalte eine Zeile mehr traegt (woher die
   Zahlen kommen), war sie hoeher als die rechte — und die beiden Zahlen, die
   der Kunde vergleichen soll, standen 100 px versetzt uebereinander. Zwei
   Dinge, die man nebeneinander legt, muessen auf einer Linie liegen, sonst
   vergleicht das Auge Hoehe statt Wert. `margin-top: auto` am Ergebnis
   schiebt es an den Fuss der Saeule; unter 720 px, wo die Spalten
   untereinander stehen, gibt es keinen freien Platz und die Regel tut
   nichts. */
.wv-spalte { min-width: 0; display: flex; flex-direction: column; gap: 8px;
  padding: 12px; border: 1px solid var(--border); border-radius: var(--radius-card); }
/* Der Vorschlag traegt eine blaeuliche Toenung — «hier bin ich, das ist unser
   Weg». Verschiedene Farben fuer verschiedene Bedeutungen (Referenz 03.09.). */
.wv-spalte--b { background: rgba(var(--accent-rgb), .07); border-color: rgba(var(--accent-rgb), .34); }
.wv-spalte > .panel__header { margin: 0 0 2px; }

/* EIN KASTEN, EINE KANTE — UND ZWAR ALS GRUNDREGEL, NICHT ALS AUSNAHME
   (Owner 06.09.2026: «Hier sind die Eingabefelder versetzt und nicht schoen
   gleich», Bild auf 390 px).

   Die zweite Spalte stand hier auf `minmax(96px, auto)`. `auto` bemisst sich
   JE GITTER neu, und jedes `.wv-feld` ist ein eigenes Gitter — also bekam
   jede Zeile die Breite ihres eigenen Inhalts, und untereinander entstand
   eine Treppe. Drei Beinamen haben das einzeln repariert (--zahl, --umkehr,
   und die Namenszeile rechts); vier Stellen taten es nicht, und der Owner
   hat genau die gesehen. Darum steht der Deckel jetzt in der GRUNDREGEL:
   wer morgen ein Feld ohne Beinamen hinzufuegt, steht von selbst in der
   Flucht, statt die naechste Treppe zu bauen.

   `minmax(96px, 200px)`: 96 px, damit eine vierstellige Zahl auch auf 390 px
   in den Kasten passt; 200 px, damit ein Eingabekasten auf 1920 px nicht ueber
   die halbe Spalte laeuft. Gemessen nach der Aenderung — alle neun Breiten,
   linke UND rechte Kante je Spalte deckungsgleich (siehe § unten). */
.wv-feld { display: grid; grid-template-columns: minmax(0, 1fr) minmax(96px, 200px); gap: 4px 10px;
  align-items: center; min-width: 0; }
.wv-feld__wort { font-size: 11.5px; letter-spacing: .02em; text-transform: uppercase; color: var(--text-tertiary); }
/* DIE EINHEIT BEKOMMT IHREN PLATZ, OB SIE DA IST ODER NICHT.
   Als Flex-Zeile war die Einheit ein Nachbar des Kastens: «CHF» (23,75 px)
   schob den Kasten um 30 px nach links, «Min» (20,0 px) um 26, «im Monat»
   (50,4 px) um 56 — und eine Zeile ohne Einheit gar nicht. Vier Kaesten
   untereinander, vier verschiedene rechte Kanten (gemessen 06.09. auf 390 px:
   329,25 · 302,59 · 312,11 in der Umkehrfrage). Als Gitter mit FESTER zweiter
   Spalte ist der Platz reserviert, auch wenn kein Wort darin steht — und
   damit endet jeder Kasten einer Spalte an derselben Stelle.
   `--wv-einheit` ist der Stellknopf: 30 px reichen fuer «CHF» und «Min»; wo
   laengere Woerter stehen, hebt der Block den Wert (siehe .wv-feld--umkehr).
   Waechter dagegen, dass ein neues Wort still herauslaeuft: der Prueflauf
   `npm run test:wv-flucht` misst scrollWidth gegen clientWidth JEDER Einheit. */
.wv-feld__eingabe { display: grid; grid-template-columns: minmax(0, 1fr) var(--wv-einheit, 30px);
  align-items: center; gap: 6px; min-width: 0; }
/* 44px ist der Griff-Boden des Hauses (grund.css). Er steht hier ausdruecklich,
   weil ein Berater diese Felder im Gespraech am Handy tippt. */
.wv-feld__input { min-height: 44px; min-width: 0; width: 100%; padding: 6px 10px;
  background: var(--input-bg, transparent); color: var(--text-primary);
  border: 1px solid var(--border); border-radius: var(--radius-card);
  font-size: 15px; font-variant-numeric: tabular-nums; text-align: right; }
.wv-feld__input:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.wv-feld--name .wv-feld__input { text-align: left; font-variant-numeric: normal; }
.wv-feld__einheit { font-size: 11.5px; color: var(--text-tertiary); white-space: nowrap; }

/* EIN BEINAME MUSS NACH SEINER GRUNDREGEL STEHEN (gemessen 06.09.2026).
   `.wv-feld--satz` stand elf Zeilen WEITER OBEN als `.wv-feld`. Beide wiegen
   gleich schwer (eine Klasse), also gewann die spaetere — und die Spaltenbreiten
   des Beinamens taten seit dem ersten Tag nichts. Sichtbar war es daran, dass
   der Stundensatz-Kasten am rechten Fensterrand klebte (x=1152..1350 auf 1400),
   waehrend sein Wort ganz links stand: genau das, was der Kommentar
   ausschliessen wollte («rechts sah er aus, als gehoere er nur zum Vorschlag»).
   Hier unten wirkt er. */
/* UND SEINE ERSTE SPALTE DARF NICHT `auto` SEIN (gemessen 06.09.2026, zweite
   Runde). Der Stundensatz und der Monatslohn stehen UNTEREINANDER, und ihre
   Beschriftungen sind verschieden lang («Was kostet eine Stunde?» gegen
   «Monatslohn der Person»). Mit `auto` richtete sich jedes Feld nach SEINEM
   Wort: auf 1440 px begann der eine Kasten bei x=471,84 und der andere bei
   x=469,20. Schaltet der Berater auf «Andere Person je Weg», tragen die
   Beschriftungen die WEGNAMEN — auf 390 px standen die drei Kaesten dann bei
   x=143,13 · 123,06 · 179,00, eine Treppe von 55,9 px. Eine feste Spalte
   (190 px, dieselbe wie in der Umkehrfrage) haelt sie in einer Flucht; sie
   darf auf schmalen Geraeten schrumpfen (`minmax(0, …)`), das Wort bricht
   dann um, statt den Kasten zu verschieben. */
.wv-feld--satz { grid-template-columns: minmax(0, 190px) minmax(120px, 180px);
  justify-content: start; gap: 4px 12px; }

/* DIE VIER ZAHLENFELDER EINER SPALTE FANGEN LINKS AN DERSELBEN STELLE AN.
   Gemessen am 1400er Bild vor dieser Regel: «Bezahlt» 457, «Anfragen» 487,
   «Minuten je Anfrage» 461, «Abschluesse» 487 — eine Treppe von 30 px, und
   30 px ist genau die Breite von «CHF». Ursache: `.wv-feld` gibt der zweiten
   Spalte `auto`, und `auto` bemisst sich JE GITTER neu; jedes Feld ist ein
   eigenes Gitter, also schob jede Zeile mit Einheit ihren Kasten nach links.
   Dieselbe Reparatur wie bei den Umkehr-Feldern: eine feste Spaltenbreite.
   Und die Einheit bekommt ihren eigenen, immer gleich breiten Platz (gemessen:
   «CHF» 23.8 px, «Min» 20.0 px) — sonst waeren zwar die Kaesten gleich, die
   Zahlen darin aber wieder um die Breite der Einheit versetzt.

   06.09., ZWEITE RUNDE: Beide Zeilen dieser Reparatur stehen jetzt in der
   GRUNDREGEL `.wv-feld` / `.wv-feld__eingabe` — jedes Feld bekommt denselben
   Deckel und denselben Einheitenplatz, nicht nur das mit diesem Beinamen.
   Der Beiname bleibt als Traeger der Begruendung und als Griff fuer die
   Messung stehen; er setzt nichts mehr, was die Grundregel nicht schon sagt.
   Das Namensfeld der rechten Spalte (fuenfte Kante ueber denselben vier
   Kaesten: es endete bei x=1364 statt x=1328) und das Auswahlfeld der linken
   sind damit ebenfalls versorgt — siehe `.wv-feld--wahl`.

   06.09., DRITTE RUNDE — «MONATE» BRAUCHT MEHR PLATZ ALS «CHF». Die neue
   Zeile «Laufzeit» traegt die Einheit «Monate»; der Platz der Grundregel
   reicht fuer «CHF» (24 px) und «Min» (20 px), nicht fuer «Monate» (41 px —
   alle drei am Blatt gemessen, Probe S3). Ohne eigenen Wert liefe das Wort aus
   seinem Kasten — unsichtbar, weil ein Vorfahr clippt und darum kein
   Rollbalken erschiene (Owner-Vorfall 31.08.).
   Der Wert ist DERSELBE wie bei den Umkehr-Feldern (56 px), nicht ein
   zweiter: eine Zahl fuer denselben Zweck.

   UND ER GILT DER GANZEN SPALTE, NICHT NUR DEN ZAHLENFELDERN. Zuerst stand er
   auf `.wv-feld--zahl` — damit hatten die fuenf Zahlenzeilen 56 px und die
   Namenszeile darueber (Auswahl links, Textfeld rechts) weiter 30 px, also
   zwei rechte Kanten in einer Spalte: 324 px gegen 298 px auf 390 px Breite,
   gemessen, Probe S2 rot. Der Einheitenplatz ist eine Eigenschaft der SPALTE,
   nicht des einzelnen Feldes: nur wenn ihn jedes Feld gleich breit reserviert,
   endet jeder Kasten an derselben Stelle — ob ein Wort darin steht oder nicht.
   Die Stundensatz-Zeile bleibt aussen vor: sie steht ueber den Spalten in
   einer eigenen Reihe und teilt mit ihnen keine Kante.
   Gemessen nach der Aenderung, alle neun Breiten: links 6 Kaesten, rechts 7,
   je EINE linke und EINE rechte Kante (Probe S2). */
.wv-spalte .wv-feld { --wv-einheit: 56px;
  grid-template-columns: minmax(0, 1fr) minmax(122px, 226px); }
/* 06.09.2026 — WARUM DIESE ZEILE HIER STEHT UND NICHT DAVOR: Die Regel darueber
   hat ZWEI Klassen und schlaegt damit die einspaltige Regel des Herkunfts-
   Kastens (.wv-feld--sicher, eine Klasse). Der Kasten «Woher die Zahlen des
   Kunden» wurde dadurch in eine 226-px-Zelle gepresst: aus einer ruhigen Reihe
   (75 px) wurden drei ausgefranste (144 px), auf jeder Breite — genau die
   Unordnung, die der Owner am Morgen des 06.09. reklamiert hat, an derselben
   Flaeche am selben Tag neu erzeugt.
   Gleiche Kraft (zwei Klassen) reicht NICHT allein: bei gleicher Staerke
   gewinnt die SPAETERE Regel. Darum steht sie hier unten, nicht oben — der
   erste Versuch stand davor und blieb wirkungslos (Probe S10 fing es). */
.wv-spalte .wv-feld--sicher { grid-template-columns: minmax(0, 1fr); }

/* WAS EINE STUNDE KOSTET — eine Zeile, die ein zweites Feld holen kann.
   Owner 06.09.: «wer geht diese Anfragen an?» Der Chef zu 150 und die
   Angestellte zu 45 sind der ganze Unterschied; solange es dieselbe Person
   ist, steht weiter genau EIN Feld da. Der Griff daneben holt das zweite,
   die Hilfe darunter fuehrt vom Monatslohn zur Stunde. */
.wv-satz { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 18px; margin: 12px 0 0; }
.wv-satz .wv-feld--satz { margin: 0; }
.wv-satz__frage { flex-basis: 100%; }
.wv-satz__paar { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 18px; min-width: 0; }
.wv-satz__griff { min-height: 44px; }
/* Die Hilfe bekommt eine eigene Zeile: sie gehoert unter den Satz, nicht
   neben ihn — und sie steht nur da, solange das Satzfeld leer ist. */
.wv-satz__hilfe { flex-basis: 100%; display: flex; flex-wrap: wrap; align-items: center; gap: 8px 18px; }
.wv-satz__vorschlag { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px;
  margin: 0; font-size: 12.5px; color: var(--text-secondary); }
.wv-satz__vorschlag .ghost-btn { min-height: 44px; }

/* WAS EINER FRAGE NOCH FEHLT — an der Stelle, an der ihr Ergebnis staende.
   Kein Kasten, kein Zeichen, kein Absatz: eine Zeile mit den Namen der Felder,
   die leer sind. Sie steht nur, wenn in dieser Frage schon etwas eingetragen
   ist — auf der leeren Flaeche wartet niemand auf ein Ergebnis. */
.wv-fehlt { margin: 0; max-width: 402px; font-size: 12.5px; color: var(--text-secondary); }

/* `margin-top: auto` statt eines festen Abstands: es schiebt den Ergebnis-
   block an den Fuss der Saeule, damit die zwei Zahlen, die der Kunde
   vergleichen soll, auf EINER Linie stehen (s.o. bei .wv-spalte). Wo kein
   freier Platz ist — untereinander auf dem Handy — loest `auto` zu 0 auf und
   der Abstand kommt aus dem `gap: 8px` der Saeule. */
.wv-spalte__ergebnis { margin-top: auto; padding-top: 10px; border-top: 1px solid var(--border); display: grid; gap: 4px; }
.wv-erg { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; min-width: 0; }
.wv-erg__wort { font-size: 11.5px; color: var(--text-tertiary); min-width: 0; }
.wv-erg__wert { font-size: 13.5px; font-variant-numeric: tabular-nums; white-space: nowrap; }
/* Die eine Zahl, um die es geht. Sie ist die groesste auf der Flaeche — was
   wichtig ist, sieht man zuerst (Referenz: Ordnung wichtig → nebensaechlich). */
.wv-erg--gross { align-items: baseline; margin-bottom: 2px; }
.wv-erg--gross .wv-erg__wert { font-size: 22px; font-weight: 600; line-height: 1.15; color: var(--text-primary); }

.wv__urteil { margin-top: 14px; }
/* Die Umkehrfrage: der Kunde setzt sich die Messlatte selbst. Sie steht
   abgesetzt, weil sie nicht zur Rechnung gehoert, sondern zum Gespraech. */
.wv-umkehr { margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--border);
  display: grid; gap: 10px; }
.wv-umkehr__frage { font-size: clamp(15px, 1.8vw, 18px); font-weight: 400; line-height: 1.35;
  color: var(--text-primary); text-wrap: balance; }
/* EINE Spaltenbreite fuer alle drei Felder. Mit `auto` richtete sich jedes
   Feld nach der Laenge SEINES Wortes — die Eingaben standen als Treppe bei
   x=22, x=68 und x=220 (gemessen 06.09. am 1400er Bild). Was untereinander
   steht, faengt links an derselben Stelle an.

   UND IHRE RECHTE KANTE BRAUCHT DENSELBEN SCHUTZ (06.09., zweite Runde).
   Links standen die drei schon in einer Flucht, rechts nicht: «CHF» ist
   23,75 px breit, «Monate» 40,89 und «im Monat» 50,41 — die drei Kaesten
   endeten auf 390 px bei x=329,25 · 312,11 · 302,59, 26,7 px Unterschied
   ueber drei Zeilen, die untereinander stehen. Genau das hat der Owner im
   Bild gesehen. `--wv-einheit: 56px` reserviert hier den Platz des laengsten
   Wortes (50,41 px + 5,6 px Luft fuer fremde Schriftmasse); die Grundregel
   `.wv-feld__eingabe` macht daraus fuer alle drei denselben Kasten. */
.wv-feld--umkehr { --wv-einheit: 56px;
  grid-template-columns: minmax(0, 190px) minmax(140px, 220px); justify-content: start; gap: 4px 12px; align-items: center; }
/* Die Antwort gehoert zu IHRER Frage, nicht an den rechten Rand der Flaeche:
   ohne Deckel zog `space-between` das Wort nach links und die Zahl 1000 px
   weiter nach rechts, und dazwischen stand nichts. */
.wv-umkehr .wv-erg--gross { max-width: 402px; }
/* Die zweite Frage ist die Ausweichfrage — sie steht leiser und abgesetzt. */
.wv-umkehr__frage--zweite { margin-top: 6px; padding-top: 12px; border-top: 1px solid var(--border);
  font-size: clamp(13.5px, 1.5vw, 15px); color: var(--text-secondary); }

/* Unter 720px stehen die Wege untereinander: nebeneinander waeren die Zahlen
   auf 390 px zweistellig umbrochen, und eine Zahl, die umbricht, ist keine. */
@media (max-width: 720px) {
  .wv__spalten { grid-template-columns: minmax(0, 1fr); }
}

/* --- 11b. WERBEWEGE, GESPEICHERT (06.09.2026) --------------------------- */
/* Der Weg links ist eine WAHL aus dem Katalog des Owners, kein freies Feld:
   ein freier Text erzeugt «Social Media», «social media» und «Insta» als drei
   Wege, die dasselbe sind — und dann laesst sich ueber Kunden hinweg nichts
   mehr zusammenzaehlen. Die Grundform des Auswahlfelds kommt aus grund.css;
   hier stehen nur Breite und Griff-Boden, damit die Zeile so hoch ist wie die
   Zahlenfelder daneben. */
.wv-feld__wahl { min-height: 44px; min-width: 0; width: 100%; }
/* DER LANGE KATALOGEINTRAG DARF DIE BESCHRIFTUNG NICHT AUFFRESSEN. Ein
   `auto`-Track waechst bis zum laengsten Eintrag der Liste («Brancheneintrag
   (local.ch, search.ch, Google)») — auf 390 px blieb von «WEG» ein «W» uebrig,
   gemessen im Bild leadakte-390-werbewege.png. Diese Lehre gilt weiter; die
   Grundregel loest sie inzwischen selbst, weil die Beschriftung dort
   `minmax(0, 1fr)` bekommt und der Kasten einen Deckel.

   UND DER KASTEN STEHT IN DER FLUCHT SEINER SPALTE (06.09., zweite Runde).
   Hier stand `auto minmax(0, 1fr)`: das Auswahlfeld nahm die ganze Restbreite
   und war damit der einzige Kasten der linken Spalte, der woanders anfing und
   woanders aufhoerte als die vier darunter — gemessen auf 390 px x=135,61 bis
   346, waehrend «Bezahlt», «Anfragen», «Minuten je Anfrage» und «Abschluesse»
   von 146 bis 310 liefen; auf 1440 px x=399,61 bis 818 gegen 618 bis 782.
   Rechts daneben stand die Vorschlagsspalte mit fuenf geraden Zeilen. Ein
   Kasten, der aus der Reihe faellt, ist genau das, was der Owner «versetzt
   und nicht schoen gleich» nennt.

   WAS DAS KOSTET, UND WARUM ES TROTZDEM RICHTIG IST: der laengste
   Katalogeintrag wird im schmalen Kasten abgeschnitten. Abgeschnitten war er
   auf dem Handy vorher auch — gemessen mit dem laengsten Eintrag des Katalogs
   («Brancheneintrag (local.ch, search.ch, Google)», Saat 20260907000000) auf
   390 px: der Kasten hielt vorher 210,39 px und danach 164 px, gebraucht
   haette das ganze Wort 250,05 px. Ganz gelesen hat man ihn dort also nie.
   Und er steht vollstaendig im Bild: die Leiste der erfassten Wege darueber
   traegt jeden Weg mit ganzem Namen und Umbruch (`.la-weg__wort`,
   `overflow-wrap: anywhere`), den offenen sichtbar hervorgehoben. Beim
   Aufklappen steht die Liste ohnehin in voller Breite.

   Hier steht darum KEINE eigene Spaltenregel mehr: die Grundregel `.wv-feld`
   sagt dasselbe, und zwei Stellen fuer denselben Wert sind die Bauart, an der
   ein Haus spaeter die eine aendert und die andere vergisst. */

/* WIE SICHER SIND DIESE ZAHLEN — vier Griffe, kein Formular (Owner-Kapitel 20,
   «minimale notwendige Friktion»). Bauart `.seg`/`.seg__btn` aus grund.css,
   derselbe Aktiv-Stil wie im ganzen Haus.
   UMBRUCH AUSDRUECKLICH ERLAUBT, mit demselben Grund wie beim Zeitraum-
   Schalter (grund.css, Befund 23.08.): die vier Woerter sind zusammen laenger
   als eine Handy-Zeile, `overflow-x: clip` am Koerper schnitte sie ohne
   Rollbalken ab — und ein Knopf, den man nicht antippen kann, ist eine tote
   Tuer. Solange alles in eine Zeile passt, aendert die Regel nichts. */
.wv-feld--sicher { grid-template-columns: minmax(0, 1fr); gap: 6px; margin-top: 2px; }
.wv-sicher { flex-wrap: wrap; max-width: 100%; }
/* DER GRIFF-BODEN GILT AUCH AUF DEM GROSSEN BILDSCHIRM (gemessen 06.09.2026).
   grund.css setzt die 44 px unter `@media (max-width:1024px),(pointer:coarse)`
   — auf einem Laptop mit Maus also nicht. Diese vier Griffe massen dort 30 px
   (Breiten 1280 bis 1920, Probe S5 vor dieser Regel rot). Der Berater tippt
   sie im Gespraech an, oft am angedockten Geraet mit Fingerbedienung, und der
   Rechner wird zum Kunden herumgedreht. Dieselbe Regel steht in diesem Blatt
   schon zweimal (`.wv-satz__griff`, `.wv-satz__vorschlag .ghost-btn`) — zwei
   Griffe wurden vergessen, nicht ausgenommen. */
.wv-sicher .seg__btn { min-height: 44px; }

/* Der Speicherstand steht leise neben der Ueberschrift der linken Spalte und
   nur, wenn es etwas zu sagen gibt. Form und Fehlerfarbe wie
   `.cal-note__status` — ein Stand-Wort im ganzen Haus. */
.wv-stand { margin-left: auto; min-width: 0; font-size: 11.5px;
  color: var(--text-tertiary); text-align: right; overflow-wrap: anywhere; }
.wv-stand.is-err { color: var(--bad-strong); }

/* --- 11c. DIE ERFASSTEN WEGE DES KUNDEN (06.09.2026) -------------------- */
/* Ein Kunde hat mehrere Wege hinter sich; die Tabelle laesst sie ausdruecklich
   zu («KEIN eindeutiger Schluessel auf (firm_id, kanal)»). Sichtbar war bis
   heute genau EINER — wer im Auswahlfeld wechselte, machte aus dem einen Weg
   den anderen und verlor den ersten samt seinen Zahlen. Hier stehen sie alle,
   je einer ein Griff; daneben «Weiterer Weg» und «Weg entfernen».
   Die Leiste steht UEBER dem Vergleich, auf dem Grund der Seite — wie die
   Schnellaktionen darueber, kein zweiter Kasten mit zweitem Etikett. */
.la-wege { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 8px; margin: 0 0 12px; }
.la-wege[hidden] { display: none; }
.la-wege__liste { display: flex; flex-wrap: wrap; gap: 8px; min-width: 0; flex: 1 1 auto; }
/* KEIN ABSCHNEIDEN, AUCH NICHT MIT PUENKTCHEN. Ein Katalogeintrag heisst
   «Social Media (Instagram, Facebook, TikTok)» — mit `text-overflow` bliebe
   auf 390 px «Social Media (Instagr…» stehen, und zwei Wege desselben Kunden
   waeren nicht mehr zu unterscheiden. Der Griff bricht darum um und wird
   hoeher, statt schmaler zu luegen (Lehre 31.08.: der Ueberlauf ohne
   Rollbalken ist der gefaehrlichste). `34ch` haelt ihn am Rechner in Form. */
.la-weg {
  display: flex; flex-direction: column; align-items: flex-start; gap: 1px;
  min-height: 44px; min-width: 0; max-width: min(100%, 34ch);
  padding: 5px 12px; text-align: left; cursor: pointer;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-card); color: var(--text-secondary); font: inherit;
}
.la-weg:hover { background: var(--surface-hover); border-color: var(--line-strong); }
.la-weg:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* Der offene Weg traegt dieselbe blaeuliche Toenung, die auf dieser Flaeche
   «hier bin ich» heisst (.wv-spalte--b, Abschnitt 11). NIE Farbe allein: er
   traegt `aria-pressed` und eine kraeftigere Kante dazu — ein farbenblindes
   Auge und eine Vorlesehilfe erkennen ihn genauso. */
.la-weg.is-offen {
  background: rgba(var(--accent-rgb), .12);
  border-color: rgba(var(--accent-rgb), .45);
  color: var(--text-primary);
}
.la-weg__wort { font-size: 12.5px; font-weight: 550; line-height: 1.3; overflow-wrap: anywhere; }
.la-weg__zahl { font-size: 11.5px; color: var(--text-tertiary); font-variant-numeric: tabular-nums; }
/* Die zwei Handgriffe stehen rechts aussen, weg von den Wegen selbst: was man
   OFT tut (einen Weg antippen) liegt links, was man SELTEN tut, rechts. */
.la-wege__griffe { display: flex; flex-wrap: wrap; gap: 8px; margin-left: auto; }
.la-wege__akt { min-height: 44px; }
/* Unter 720 px steht die Flaeche einspaltig (Abschnitt 11). Dann tragen die
   zwei Griffe die volle Breite und liegen unter den Wegen statt neben ihnen —
   `margin-left: auto` schoebe sie sonst in eine eigene, halb leere Zeile. */
@media (max-width: 720px) {
  .la-wege__griffe { margin-left: 0; width: 100%; }
  .la-wege__akt { flex: 1 1 140px; }
  /* VOLLE BREITE, DAMIT DIE WEGE EINE SPALTE BILDEN. Nach Inhalt bemessen
     standen sie auf 390 px verschieden breit untereinander (gemessen im Bild
     leadakte-zwei-wege-390.png: 180 px gegen 330 px) — eine ausgefranste
     Kante, die aussieht wie ein Fehler. Untereinander heisst hier: eine
     Kante links, eine rechts. */
  .la-wege__liste { width: 100%; }
  .la-weg { width: 100%; max-width: 100%; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   11d · DER ZEIGEN-STAND — der Bildschirm wird herumgedreht (06.09.2026)
   ═══════════════════════════════════════════════════════════════════════════
   Der Wegvergleich ist zum ZEIGEN gebaut: der Berater tippt die Zahlen des
   Kunden ein, und der Kunde sieht das Ergebnis wachsen. Ueber dem Rechner
   steht aber die Akte — «Wiedervorlage ueberfaellig 1 Tag», «2x verteilt»,
   «Umverteilen», der Name der Beraterin. Nichts davon gehoert vor den Gast.

   KEIN EIGENER BEREICH: Kapitel 9 des Auftragsdokuments haelt fest, dass ein
   Unternehmen EIN Objekt mit mehreren Sichten ist und nicht viele Bereiche
   braucht — «WAEHREND BERATUNG: adaptive Discovery und Zahlen». Dies ist
   dieser Zustand, kein zweiter Ort.

   ZWEI DINGE VERSCHWINDEN, DIE MEHR SIND ALS ZIERAT:
   `.wv-feld--sicher` (die vier Griffe «Nachgesehen/Genannt/Geschaetzt/
   Uebernommen») und `.wv-stand` (das Wort neben der Ueberschrift der linken
   Spalte: «speichert …», «gespeichert», rot «nicht gespeichert», «Weg waehlen
   zum Speichern») gehen den Kunden nichts an. Die Griffe sind die Einschaetzung
   des BERATERS ueber die Glaubwuerdigkeit seines Gegenuebers — steht
   «Geschaetzt» auf dem Bildschirm, waehrend der Kunde seine Zahlen nennt, ist
   das Gespraech vorbei. Und der Speicherstand ist unsere Maschine: «nicht
   gespeichert» las bis zum 06.09. der Kunde mit, waehrend er auf den
   umgedrehten Bildschirm schaute. Gezaehlt wurden damals zwei Stellen; es
   waren drei.

   AUSBLENDEN IST ANZEIGE, NIE DATENENTZUG (Owner-Korrektur 31.08.). Der Stand
   wird NICHT geleert: `views/lead-akte.js` schreibt weiter in dasselbe
   Element, und der Rueckweg zeigt, was inzwischen gilt. Darum eine Regel am
   Koerper und keine Klasse am Element — `wegSagen()` setzt `className` bei
   jedem Wort neu und wuerde jede dort abgelegte Marke wegwischen.

   Der Einheiten-Kasten und der Satz «Rechts: angenommen» BLEIBEN: sie erklaeren
   dem Kunden, warum Anfragen nicht gleich Anfragen sind und dass die rechte
   Spalte gerechnet und nicht erlebt ist — das ist das Argument, nicht das
   Urteil ueber ihn.

   Ebene 400: ueber Seite und Kopfzeile (200/210), unter Modalen (999+) und
   Meldungen (1400) — ein Fehler muss auch im Gespraech sichtbar bleiben. */
.wv__zeigen-leiste {
  display: flex;
  justify-content: flex-end;
  margin: -2px 0 10px;
}
/* Derselbe Griff-Boden wie bei den vier Sicherheits-Griffen: 38 px gemessen
   auf 1280 bis 1920, wo grund.css seine 44 px nicht setzt. Dieser Knopf ist
   der einzige, den der Kunde auf dem umgedrehten Bildschirm sieht. */
.wv__zeigen-leiste .ghost-btn { min-height: 44px; }
/* Zwei Knoepfe, von denen CSS je einen zeigt — kein Text, der per JS springt
   und beim naechsten Neuzeichnen wieder falsch stuende. */
.wv__zeigen-aus { display: none; }
body.lx-wv-zeigen .wv__zeigen-an { display: none; }
body.lx-wv-zeigen .wv__zeigen-aus { display: inline-flex; }

body.lx-wv-zeigen { overflow: hidden; }
body.lx-wv-zeigen .wv {
  position: fixed;
  inset: 0;
  z-index: 400;
  margin: 0;
  border: 0;
  border-radius: 0;
  overflow: auto;
  padding: clamp(16px, 3vw, 40px);
  background: var(--bg);
}
/* Auf einem breiten Bildschirm liefe die Zeile sonst ueber die ganze Wand und
   waere aus zwei Metern Abstand nicht mehr zu lesen. */
body.lx-wv-zeigen .wv > * {
  max-width: 1100px;
  margin-inline: auto;
}
/* Der Rueckweg bleibt erreichbar, auch wenn der Kunde weit nach unten liest. */
body.lx-wv-zeigen .wv__zeigen-leiste {
  position: sticky;
  top: 0;
  z-index: 1;
  padding-bottom: 8px;
  background: var(--bg);
}
/* DREI DINGE VERSCHWINDEN, DIE MEHR SIND ALS ZIERAT — der Speicherstand, die
   vier Sicherheits-Griffe und (seit 06.09.2026) die Zeile, die sagt, dass
   noch nicht hinterlegt ist, wie viele Menschen einen Bildschirm sehen.
   Im Zeigen-Stand sitzt der KUNDE daneben und liest mit. Der Speicherstand
   und die Griffe sind unsere Arbeit an seinen Zahlen; die dritte Zeile ist
   der Zustand unserer Einstellungen. Keines davon geht ihn etwas an, und
   jedes von ihnen wirft eine Frage auf, die vom Vergleich wegfuehrt.
   ENTFERNT WIRD NICHTS: der Berater sieht alle drei, sobald er den
   Zeigen-Stand verlaesst (Owner-Regel «Anzeige ist nicht Datenbestand»). */
body.lx-wv-zeigen .wv-stand,
body.lx-wv-zeigen .wv-chancen-ersatz,
/* 06.09.2026: JEDE «Fehlt: …»-Zeile ist eine Meldung des Hauses an den
   Berater — sie sagt, was er noch eintippen muss. Der Kunde, dem der
   Bildschirm hingedreht wird, soll sie nie lesen; er saehe sonst neben
   einem Strich statt einer Zahl, dass unserem System etwas fehlt.
   Die Klasse steht hier statt einzelner Saetze, damit der naechste
   «Fehlt»-Satz nicht wieder vergessen wird. */
body.lx-wv-zeigen .wv-fehlt,
body.lx-wv-zeigen .wv-feld--sicher { display: none; }

/* --- 11c. DER LESESTAND — derselbe Rechner auf einer Flaeche, die nicht
   erfasst (06.09.2026) ---------------------------------------------------

   Der Offerten-Rechner zeigt seit heute denselben Vergleich. Was der Kunde
   ERLEBT hat (linke Spalte), wohnt aber in seiner Akte: dort steht die Leiste
   der erfassten Wege, dort haengt der Schreibweg, dort entscheidet der
   Berater, ob ein Wechsel eine Berichtigung ist oder ein zweiter Weg. Ein
   zweiter Schreibweg fuer dieselbe Zeile waere die zweite Wahrheit, die
   dieses Haus nicht will — also liest die andere Flaeche nur
   (`wegvergleichHtml({nurLesenA:true})`).

   UND MAN SIEHT ES, statt es zu erfahren. Ein Eingabekasten, in den man nicht
   tippen kann, ist die aergerlichste Form einer Sperre: er sieht aus wie eine
   Einladung. Darum traegt der gelesene Wert gar keinen Kasten — er steht als
   Zahl da, wie jede andere Zahl der Flaeche, und der Weg zum Aendern steht
   darunter (`.wv__rueckweg`). Verschiedene Formen fuer verschiedene
   Bedeutungen; die Farbe allein traegt hier nichts.

   KEINE ZWEITE FARBWELT: Grund, Haarlinie, Blau und Bernstein stehen in
   grund.css und sind aus der Owner-Referenz gemessen. Hier steht keine
   einzige neue Farbe. */
.wv-spalte--fest { background: transparent; }
/* Kein Eingabekasten, wo nichts einzugeben ist. Das Gitter der Zeile bleibt
   (`.wv-feld` setzt es), damit die Werte links und rechts auf derselben
   Linie liegen — der ganze Sinn der zwei Spalten. */
.wv-feld--fest .wv-feld__input {
  border: 0; background: transparent; padding-left: 0;
  color: var(--text); font-variant-numeric: tabular-nums;
  cursor: default;
}
.wv-feld--fest .wv-feld__wort { color: var(--text-secondary); }
/* Der Name des Wegs — er ist der Titel der Spalte, nicht ein Feld. */
.wv-feld__fest {
  min-width: 0; color: var(--text); font-weight: 600;
  overflow-wrap: anywhere;
}
/* Der Rueckweg dorthin, wo die linke Spalte entsteht. Rechtsbuendig wie die
   Zeigen-Leiste darueber — dieselbe Art Griff, dieselbe Kante. */
.wv__rueckweg { display: flex; justify-content: flex-end; margin: 10px 0 0; }
/* Griff-Boden: 1280 bis 1920 setzt grund.css seine 44 px nicht
   (dieselbe Rechnung wie bei `.wv__zeigen-leiste .ghost-btn`). */
.wv__rueckweg .ghost-btn { min-height: 44px; }
/* Im Zeigen-Stand sitzt der KUNDE daneben. «Werbewege des Kunden pflegen» ist
   unsere Arbeit an seinen Zahlen und geht ihn nichts an — dieselbe Regel wie
   fuer Speicherstand und Sicherheits-Griffe. */
body.lx-wv-zeigen .wv__rueckweg { display: none; }

/* Lead work: current action first, supporting information on demand. */
.akte-workspace { --work-gap:24px; }
.akte-workspace .pd2-kopf { margin-bottom:18px; }
.akte-workspace .pd2-kopf__zeile h1 { font-size:clamp(23px,2.4vw,32px); line-height:1.2; }
.akte-workspace .pd2-kopf__meta { line-height:1.7; }
.akte-workspace__action { display:flex; align-items:center; justify-content:space-between; gap:24px; padding:18px 22px; margin-bottom:18px; background:var(--surface); border:1px solid var(--line); border-left:3px solid var(--accent); }
.akte-workspace__action>[data-slot="frage"] { flex:1; min-width:0; }
.akte-workspace__action .la-schritt { margin:0; padding:0; border:0; background:transparent; box-shadow:none; }
.akte-workspace__action .frage-kopf__frage { font-size:18px; line-height:1.45; }
.akte-workspace__action .pd2-kopf__aktionen { flex:0 1 auto; flex-wrap:wrap; }
.akte-workspace__action .pd2-kopf__aktionen button { min-height:44px; }
.akte-workspace__details { margin-top:24px; border-top:1px solid var(--line); }
.akte-workspace__details>summary { min-height:52px; padding:16px 0; font-weight:600; font-size:13px; color:var(--text-secondary); cursor:pointer; }
.akte-workspace__details .pd2-kpis { margin:4px 0 16px; }
.la-work-grid { display:grid; grid-template-columns:minmax(0,1fr) minmax(250px,320px); gap:var(--work-gap); align-items:start; }
.la-work-main,.la-work-context { min-width:0; }
.la-work-main { display:flex; flex-direction:column; gap:20px; }
.la-work-main>.panel { margin:0; }
.la-work-main h2,.la-work-context>h2 { font-size:16px; line-height:1.4; margin:0 0 12px; font-weight:600; }
.la-work-context { border-left:1px solid var(--line); padding-left:24px; }
.la-work-context>h2 { color:var(--text-secondary); font-size:13px; margin:4px 0 8px; }
.la-context { border-bottom:1px solid var(--line); }
.la-context>summary { padding:15px 0; min-height:48px; font-size:13px; line-height:1.5; font-weight:550; cursor:pointer; overflow-wrap:anywhere; }
.la-context>summary>span { color:var(--text-tertiary); font-variant-numeric:tabular-nums; margin-left:6px; }
.la-context>.panel { padding:0 0 16px; margin:0; border:0; box-shadow:none; background:transparent; }
.la-context>.panel>h2 { display:none; }
.la-context .la-nachbar { padding:12px 0; }
.la-context .la-nachbar__ic { display:none; }
.la-context .la-eignung__zeile { grid-template-columns:minmax(0,1fr); padding:12px 0; gap:6px; }
.la-context .la-gespraech__zeile { padding:12px 0; }
.la-work-offer { display:flex; flex-wrap:wrap; gap:16px; align-items:center; justify-content:space-between; border:1px solid var(--line); background:var(--surface); padding:20px; }
.la-work-offer>div { flex:1 1 240px; }
.la-work-offer h2 { margin-bottom:6px; }
.la-work-offer p { margin:0; color:var(--text-secondary); font-size:13px; line-height:1.5; }
.la-work-offer>a { min-height:44px; flex:0 1 auto; white-space:normal; text-align:left; }
.la-work-offer>a svg { width:16px; height:16px; }
.la-work-appointments { border-bottom:1px solid var(--line); padding-bottom:6px; }
.la-work-appointment { display:flex; align-items:center; gap:12px; justify-content:space-between; padding:10px 0 14px; }
.la-work-appointment>div { min-width:0; }
.la-work-appointment strong { display:block; font-size:14px; }
.la-work-appointment>div>span,.la-work-appointment p { display:block; color:var(--text-secondary); font-size:13px; line-height:1.5; margin:4px 0 0; overflow-wrap:anywhere; }
.la-work-appointment .appt-link-btns { flex-shrink:0; }
.la-work-main .la-gespraech__frage { margin:0; padding:0 0 4px; border:0; background:transparent; box-shadow:none; }
.la-work-main .la-notiz { padding:20px; }
.la-work-main .la-notiz textarea { min-height:100px; }
.la-work-main .la-ergebnis { border-left:2px solid var(--line); }
.akte-workspace summary:focus-visible { outline:2px solid var(--accent); outline-offset:3px; }
@media(max-width:1050px) {
  .akte-workspace__action { align-items:flex-start; flex-direction:column; gap:12px; }
  .la-work-grid { grid-template-columns:minmax(0,1fr) minmax(220px,270px); gap:20px; }
  .la-work-context { padding-left:20px; }
}
@media(max-width:760px) {
  .akte-workspace { --work-gap:20px; }
  .akte-workspace__action { padding:16px; margin-bottom:12px; }
  .akte-workspace__action .pd2-kopf__aktionen { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); width:100%; justify-content:flex-start; }
  .akte-workspace__action .pd2-kopf__aktionen button { flex:1 1 120px; white-space:normal; }
  .akte-workspace__action .pd2-kopf__aktionen button:last-child:nth-child(odd) { grid-column:1/-1; }
  .la-work-grid { grid-template-columns:minmax(0,1fr); }
  .la-work-context { border-left:0; border-top:1px solid var(--line); padding:16px 0 0; }
  .la-work-offer,.la-work-main .la-notiz { padding:16px; }
  .la-work-offer>div { flex-basis:100%; }
  .la-work-offer>a { width:100%; justify-content:space-between; }
  .la-work-appointment { align-items:flex-start; flex-wrap:wrap; }
  .la-work-appointment>div { flex:1 1 200px; }
  .la-work-main .la-gespraech__frage { align-items:stretch; }
  .la-work-main .la-gespraech__frage button { width:100%; }
  .la-context .la-nachbar__text { min-width:0; }
}

/* Customer work uses the existing case shell with a reachable overview. */
.customer-workspace>.vk-kopf { margin-bottom:12px; }
.customer-workspace__mobile-nav { display:none; }
.customer-workspace>.akte-workspace__action { border:0; background:transparent; padding:0; margin:0 0 16px; }
.customer-workspace>.akte-workspace__action .lx-seitenkopf__akt { display:flex; flex-wrap:wrap; gap:8px; }
.customer-workspace>.akte-workspace__action:has(.lx-seitenkopf__akt:empty) { display:none; }
.customer-workspace>.akte-workspace__details { margin:0 0 16px; border-top:1px solid var(--line); border-bottom:1px solid var(--line); }
.customer-workspace>.akte-workspace__details>summary { min-height:48px; padding:14px 0; font-size:14px; line-height:1.45; }
.customer-workspace__administration { display:flex; flex-wrap:wrap; gap:8px; padding:0 0 16px; }
.customer-workspace .vk-werte { flex-wrap:wrap; overflow:visible; gap:10px 22px; }
.customer-workspace .vk-werte__paar { flex:0 1 auto; flex-wrap:wrap; }
.customer-workspace .vk-werte__label { white-space:normal; }
.customer-workspace .vk-panel__kopf { flex-wrap:wrap; }
@media(max-width:760px) {
  .customer-workspace>.vk-kopf h1 { font-size:22px; line-height:1.25; overflow-wrap:anywhere; }
  .customer-workspace__mobile-nav { display:block; margin:0 0 16px; }
  .customer-workspace>.vk-tabs { display:none; }
  .customer-workspace__mobile-nav .field { min-width:0; }
  .customer-workspace>.akte-workspace__details>summary { padding:12px 0; }
  .customer-workspace .vk-werte__paar { width:100%; justify-content:space-between; }
}

/* The embedded offer has an explicit return on desktop as well as mobile. */
.akte-workspace__action [data-lead-context="contact-actions"] { border:0; grid-column:1/-1; width:100%; }
.akte-workspace__action [data-lead-context="contact-actions"]>summary { min-height:44px; padding:12px 0; color:var(--text-secondary); }
.la-contact-actions { display:flex; flex-wrap:wrap; gap:8px; padding:4px 0 0; }
/* ============================================================
   Patch-Integration — Namensraum lx-standortakte/lx-spotakte (Akten des Betriebs); Quelle: docs/design/patch-betriebsakte.css
   ============================================================ */
/* DIE AKTEN DES BETRIEBS — Namensräume `lx-standortakte` / `lx-spotakte`
   (Welle 3, Paket D, 18.08.2026).
   Flächen: public/src/views/standort-akte.js  · Route #/v/locations/:id
            public/src/views/spot-akte.js      · Route #/v/mediathek/:id

   WARUM HIER SO WENIG STEHT: beide Akten tragen bestehende Kleider — die
   Standort-Akte das Dossier-Kleid des Standortbetreibers (`admin-page gz`,
   `pd2-kopf`, `pd2-tabs`, `pd2-kpis`, `stat-strip`), die Spot-Akte das
   Verkaufs-Kleid der Rechnungs-Akte (`admin-page vk`, `vk-kopf`, `vk-tabs`,
   `vk-kacheln`). Die Nachbarn und die Schritt-Zeile kommen aus
   `patch-rechnungsakte.css` (`ra-*`), die Loop-Punkte aus `patch-signage.css`
   (`sig-loop`/`sig-slot`), die Vorschau aus `patch-mediathek.css`
   (`mk-vorschau`). Ein zweites Kleid für dieselbe Anatomie wäre genau die
   Doppelung, gegen die BEREICHE §10 und `scripts/_stil_einmalig_test.mjs`
   gebaut sind. Neu ist nur, was es im Haus noch NICHT gibt. */

/* --- 1. Der Bildschirm-ANKER --------------------------------------------- */
/* Ein Bildschirm bekommt keine eigene Route, sondern eine Adresse in der Akte
   seines Standorts (`?tab=bildschirme&screen=…`, Begründung im Kopf von
   views/standort-akte.js). Damit die Adresse mehr ist als ein Versprechen,
   muss man am Bildschirm SEHEN, welche Zeile gemeint war. Dieselbe Sprache wie
   überall im Haus für «du bist hier»: `is-hier`. */
body.lx-standortakte .info-card.is-hier {
  border-color: var(--accent-line);
  background: var(--accent-soft);
}
body.lx-standortakte .info-card.is-hier > strong { color: var(--accent-strong); }

/* --- 2. Der Loop über den Bildschirmen ------------------------------------ */
/* Er steht EINMAL über den Zeilen, nicht je Zeile: gebucht wird der Standort,
   und derselbe Loop läuft auf allen seinen Bildschirmen. In einem `panel`
   braucht er darum etwas Luft nach unten, die er auf der Betriebstafel aus
   ihrem eigenen Zeilenabstand bekommt. */
body.lx-standortakte .sig-loop { margin: 4px 0 14px; }

/* --- 3. Die Zeilen der Bildschirm-Liste ----------------------------------- */
/* Das Auswahlfeld für den Zustand sitzt in derselben Karte wie Kennung und
   Abzeichen — ohne Abstand klebte es am Text darüber. */
body.lx-standortakte .info-card[data-screen] .field { margin-top: 8px; }
body.lx-standortakte .info-card[data-screen] > strong {
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px;
}

/* --- 4a. Die Kennzeile der Spot-Akte ist ein SATZ, keine Reihe ------------ */
/* `.vk-kopf__ort` ist im Verkaufs-Kleid ein `inline-flex` mit Luecke — richtig
   fuer «Bern · 12 Buchungen», falsch fuer die Kennzeile eines Spots: dort
   stehen fuenf Angaben (Kunde · Kampagne · Version · Format · hochgeladen von),
   und auf 390 px wurde jede ein eigenes Flex-Feld, das ueber die Kante ragte —
   am Bild vom 18.08. gemessen. Dieselbe Heilung, die die Rechnungs-Akte fuer
   ihre sechs Angaben gebraucht hat; sie steht hier eigens, weil sie an DIESEM
   Namensraum haengt und nicht an jenem (ein Selektor gehoert genau einem
   Blatt, `scripts/_stil_einmalig_test.mjs`).
   Und der Titel: ein Dateiname bricht nicht, also darf er ueberlaufen — er
   bekommt darum eine Bruchregel statt einer Breite. */
body.lx-spotakte .vk-kopf__ort { display: block; line-height: 1.7; max-width: 100%; }
body.lx-spotakte .vk-kopf__zeile { max-width: 100%; }
body.lx-spotakte .vk-kopf h1 { overflow-wrap: anywhere; }

/* --- 4. Die Vorschau in der Spot-Akte ------------------------------------- */
/* `mk-vorschau.is-gross` ist in der Galerie eine Kachel unter vielen; hier ist
   sie das erste, was man sieht — sie steht darum als Block, nicht inline. */
body.lx-spotakte .mk-vorschau.is-gross { display: block; margin: 0 auto; }

/* --- 5. Handy ------------------------------------------------------------- */
/* Tapflächen-Boden auf JEDEM Touch-Gerät, nicht erst unter 640px
   (Memory project_tablet_touch_breakpoint: 768/1024 sind die Bruchzone).
   Beide Akten führen ihre Nachbarn und Zeilen in Tabellen weiter — ein Weg,
   den man am Telefon nicht trifft, ist kein Weg (Hausregel 9). */
@media (max-width: 1024px), (pointer: coarse) {
  body.lx-standortakte .sl-table a,
  body.lx-spotakte .sl-table a,
  body.lx-standortakte .info-card a,
  body.lx-spotakte .info-card a {
    display: inline-flex; align-items: center; min-height: 44px;
  }
  body.lx-standortakte .sl-edit-grid input,
  body.lx-standortakte .sl-edit-grid select,
  body.lx-standortakte .info-card[data-screen] select { min-height: 44px; }
}
@media (max-width: 720px) {
  /* DIE KLEBENDE HANDGRIFF-LEISTE GEHOERT IN EIN FENSTER, NICHT AUF EINE SEITE.
     `.modal-actions { position: sticky; bottom: 0 }` (grund.css, ab 720px) ist
     fuer den Fuss eines Modals gebaut: dort scrollt EIN Kasten, und die Leiste
     bleibt sichtbar. Das Bearbeiten-Formular des Standorts wohnt seit dem
     18.08. auf einer SEITE — dort klebte dieselbe Leiste am unteren Rand des
     Bildschirms und legte sich ueber das erste Feld («Salon»). Am Bild vom
     18.08. gemessen und nachgerechnet: Leiste 1058–1120, Feld 1054–1121.
     Auf der Seite steht die Leiste darum am ENDE des Formulars, wo sie
     hingehoert.

     GEGENPRUEFUNG 18.08.: die erste Fassung dieser Regel nannte nur
     `.sl-edit-grid` — also genau EINE der sechs Leisten dieser zwei Akten. Vier
     weitere klebten weiter: «Zur Betriebstafel» (Uebersicht), «Bildschirm
     hinzufuegen» (Bildschirme), «Vereinbarung oeffnen» (Verguetung) und, in der
     Spot-Akte, «Freigeben · Zurueckweisen» (Freigaben) — auf 390 px lagen sie
     ueber dem Text darunter. Ein Fehler, der an EINER Stelle geheilt wird und
     an vier weiteren stehen bleibt, ist nicht geheilt (Hausregel 7).
     Die Regel gilt darum fuer JEDE Leiste im Inhaltsbereich dieser zwei
     Flaechen. `#app-view` grenzt sie sauber ab: die Fenster des Hauses
     (`components/app-dialog.js`) haengen an `document.body`, ausserhalb davon —
     ihr Fuss klebt also weiter, wie er soll. */
  body.lx-standortakte #app-view .modal-actions,
  body.lx-spotakte #app-view .modal-actions {
    position: static; background: transparent; border-top: 0;
    margin-top: 10px; padding: 0;
  }
}
@media (max-width: 640px) {
  /* EIN ZEITRAUM IST ZWEI DATEN — UND DAMIT LAENGER ALS EINE KARTENSPALTE.
     Am Bild UND nachgemessen (Gegenpruefung 18.08., echte Schale auf 390 px):
     im Reiter «Wo er lief» wird die Tabelle zur Karte mit zwei Spalten
     (patch-konfigurator.css, ab 640px). Die Zelle «Zeitraum» traegt
     `class="nw"` — kein Umbruch — und «18.08.2026 – 17.09.2026» sprengte damit
     die Spalte: die Zeile war 379 px breit in einem 362 px breiten Kasten, und
     das Enddatum stand 17 px hinter der Kante, unerreichbar.
     Auf der Karte darf der Zeitraum darum umbrechen. Am grossen Bildschirm
     bleibt `nw` unangetastet — dort ist Platz, und ein Datum, das mitten
     durchbricht, liest sich schlecht. */
  body.lx-spotakte .sl-table td.nw { white-space: normal; }
}
@media (max-width: 640px) {
  body.lx-standortakte .sig-loop { flex-wrap: wrap; }
}

/* Die Handgriff-Leiste klebt in einem Fenster — nicht auf einer Seite.
   ---------------------------------------------------------------------------
   `grund.css:1288` macht `.modal-actions` ab 720px zu `position: sticky;
   bottom: 0`. Im Fuss eines Fensters ist das richtig: der Rumpf scrollt, die
   Knöpfe bleiben. Die Standort-Akte ist aber eine SEITE — dort klebt dieselbe
   Regel am unteren Fensterrand und legt sich über das erste Formularfeld
   («Salon»), gemessen am 18.08. auf 390px im Wächter
   `_betrieb_verdrahtung_test.mjs` (E1).

   Es ist die Klasse, nicht die Fläche: ein Bauteil, das für ein Fenster
   gemacht ist, wurde auf einer Seite wiederverwendet. Sauber wäre ein eigener
   Name für die Seiten-Knopfleiste (BEREICHE §10, Welle 8 «ein Bauteil je
   Frage»). Bis dahin hebt diese Regel die Fenster-Eigenschaft genau dort auf,
   wo es kein Fenster gibt — eng auf das Formular der Akte gefasst, damit sie
   kein fremdes Fenster trifft. */
@media (max-width: 720px) {
  body.lx-standortakte .sl-edit-grid .modal-actions {
    position: static; z-index: auto; background: none;
    border-top: 0; padding-bottom: 0;
  }
}
/* ============================================================
   Patch-Integration — Namensraum lx-unten__zahl/gz-karte__wartet/gz-wartet (Signale); Quelle: docs/design/patch-signale.css
   ============================================================ */
/* SIGNALE — «nichts wartet still» (docs/BEREICHE.md §8, Welle 5 · Paket C)
   ===========================================================================
   Namensraum: lx-unten__zahl · gz-karte__wartet · gz-wartet

   DREI neue Selektoren, sonst nichts. Die Zeilen von «Was wartet» tragen
   bereits die Gestalt aus `patch-ortsschild.css` (.bs-liste/.bs-zeile/
   .bs-ruhig) — sie sind dort bewusst NICHT auf `.bs` eingeschraenkt, und die
   Zentrale zeichnet ab jetzt dieselben Zeilen mit demselben Bauteil. Eine
   zweite Gestalt fuer dieselbe Zeile waere genau die Doppelung, gegen die
   `scripts/_stil_einmalig_test.mjs` gebaut ist.

   Auch der Zaehler in der SEITENLEISTE ist nicht neu: `.nav-tab__badge` steht
   seit Iter 31 im Grundstock (grund.css:4735) und traegt jetzt statt der einen
   Aufgaben-Zahl die Zahl JEDER Tuer. Neu ist nur, was es vorher nirgends gab:
   dieselbe Zahl an der Leiste am Daumen und an der Bereichs-Karte. */

/* --- 1 · Die Zahl an der Leiste am Daumen (nur Handy) ---------------------
   Die Seitenleiste haengt ihre Zahl neben das Wort (`margin-left:auto`). Hier
   geht das nicht: `.lx-unten__ziel` ist eine SPALTE (Symbol ueber Wort) auf
   76px Breite — eine Zahl in der Zeile wuerde das Wort abschneiden. Sie sitzt
   deshalb als Punkt oben rechts am Symbol, genau wie in der eingeklappten
   Seitenleiste (`.sidebar-collapsed .nav-tab__badge`). Der Traeger bekommt
   dafuer `position: relative`; die Zahl selbst faengt keinen Zeigerdruck ab,
   sonst waere ein Teil der 48px-Tapflaeche taub.

   WARUM `:has(...)` UND NICHT `.lx-unten__ziel { position: relative }`: der
   nackte Selektor steht schon in `patch-chrome.css`. Ihn hier ein zweites Mal
   zu schreiben ist genau die blattuebergreifende Doppelung, die
   `scripts/_stil_einmalig_test.mjs` rot macht (und zu Recht: zwei Blaetter
   haetten dann eine Meinung zu demselben Traeger). Die Bedingung ist ausserdem
   ehrlicher — der Traeger braucht den Bezugspunkt NUR, solange wirklich eine
   Zahl an ihm haengt. */
.lx-unten__ziel:has(.lx-unten__zahl) { position: relative; }
.lx-unten__zahl {
  position: absolute;
  top: 2px;
  right: calc(50% - 20px);
  min-width: 16px;
  height: 16px;
  padding: 0 4px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-card);
  background: var(--bad);
  color: #fff;
  font-size: 11px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  line-height: 1;
  pointer-events: none;
}

/* --- 2 · Die Zahl an der Bereichs-Karte der Zentrale ----------------------
   Sie steht zwischen Titel und Zustands-Chip und traegt bewusst NICHT den
   Alarm-Ton der Tuer: hier ist sie eine Tatsache neben sechs anderen
   Tatsachen, kein Weckruf. Der Chip behaelt seinen Platz ganz rechts
   (`patch-zentrale.css`: `.gz-karte__kopf .gz-chip { margin-left: auto }`) —
   deshalb schiebt diese Zahl sich mit demselben Mittel nach rechts und der
   Chip folgt ihr unmittelbar. `flex: 0 0 auto`, damit sie dem Titel nie
   Breite wegnimmt. */
.gz-karte__wartet {
  flex: 0 0 auto;
  margin-left: auto;
  display: inline-flex;
  align-items: center;
  height: 20px;
  padding: 0 8px;
  border-radius: var(--radius-card);
  border: 1px solid var(--hairline-strong, var(--hairline));
  background: rgba(var(--tint-rgb), .06);
  color: var(--text-secondary);
  font-size: 11.5px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* --- 3 · Der Abschnitt «Was wartet» in der Zentrale -----------------------
   Er benutzt die Zeilen-Gestalt des Bereichs-Starts unveraendert. Was hier
   steht, ist nur der Rahmen, den die Zentrale ihren Bloecken gibt: ein Kasten
   mit Innenabstand, damit die Zeilen nicht am Rand kleben, und ein ruhiger
   Satz, der ohne Rahmen auskommt (§4.3). */
.gz-wartet .bs-liste { margin: 0; }
.gz-wartet .bs-zeile { padding: 10px 0; }
.gz-wartet .bs-ruhig { margin: 0; }

@media (max-width: 640px) {
  /* Am Handy traegt die Karte weniger Breite: die Zahl darf den Titel nicht
     verdraengen. Sie bleibt, der Titel kuerzt sich — der Chip ganz rechts ist
     das Erste, was Platz abgibt (er steht ohnehin schon in der Farbe). */
  .gz-karte__wartet { padding: 0 6px; font-size: 11px; }
}

/* ============================================================
   Patch-Integration — Namensraum zug-/ns- (Der eine Zug: naechster Schritt, Fall-Weg); Quelle: docs/design/patch-zug.css
   ============================================================ */
/* ============================================================================
   DER EINE ZUG — Namensraum `zug-` / `ns-` (BEREICHE §7)
   ============================================================================
   Zwei Bauteile, sonst nichts:

   1. `.ns-schritt` — die EINE Schritt-Zeile aus components/naechster-schritt.js
      («Der naechste Schritt ist ein Knopf, kein Satz», §7.2). Sie hat dieselbe
      Anatomie wie `.ra-schritt` in der Rechnungs-Akte, die den Zug am 18.08.
      als Erste gezeigt hat — Wort links, Handlung rechts. Die Rechnungs-Akte
      BEHAELT ihren Namensraum: sie reicht ihn dem Bauteil als `klasse` herein.
      Zwei Namen fuer dieselbe Anatomie sind hier kein Widerspruch, sondern die
      Bedingung dafuer, dass kein Selektor in zwei Blaettern steht
      (scripts/_stil_einmalig_test.mjs).

   2. `.zug-kette` — der Weg eines Vorgangs in der Fall-Akte. Jede Zeile ein
      Schritt, jeder erledigte Schritt nennt sein echtes Ding und traegt den
      Weg dorthin (§6), der offene traegt den Weg zu seiner Arbeit (§7.5).

   Handy: 390 px, jede Bedienflaeche >= 44 px, kein Querlauf.
   ========================================================================= */

/* --- 1. Die eine Schritt-Zeile ------------------------------------------- */
.ns-schritt {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  padding: 14px 16px; margin-bottom: 14px;
}
.ns-schritt__text { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1 1 240px; }
/* Schrift und Farbe von Wort und Satz kommen seit 03.09. aus dem Frage-Kopf
   (.frage-kopf__wort / .frage-kopf__frage in grund.css) — hier nur das Layout. */

/* Die Fall-Akte traegt denselben Bau unter eigenem Namen; der Rahmen und der
   Grund kommen vom Frage-Kopf (03.09.: kein Seitenstreifen mehr). */
.zug-schritt-panel {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  padding: 14px 16px; margin-bottom: 14px;
}
.zug-schritt-panel__text { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1 1 240px; }
.zug-schritt-panel__wort {
  font-size: 11px; letter-spacing: .08em; text-transform: uppercase;
  color: var(--text-secondary);
}
.zug-schritt-panel__satz { font-size: 14.5px; font-weight: 600; }

/* --- 2. Die Kette: der Weg dieses Vorgangs -------------------------------- */
.zug-kette { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; }
.zug-schritt {
  display: grid;
  grid-template-columns: 22px minmax(0, 1fr) minmax(0, 1.2fr) auto;
  align-items: center; gap: 10px;
  padding: 10px 4px;
  border-top: 1px solid var(--border);
}
.zug-schritt:first-child { border-top: 0; }
.zug-schritt__zeichen {
  width: 22px; height: 22px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 12px; line-height: 1;
  background: var(--surface-2, rgba(127, 127, 127, .12));
  color: var(--text-secondary);
}
.zug-schritt.is-erledigt .zug-schritt__zeichen {
  background: var(--good-soft, rgba(34, 160, 90, .16));
  color: var(--good-strong, #1d8a52);
}
.zug-schritt.is-dran .zug-schritt__zeichen {
  background: var(--warn-soft, rgba(214, 150, 20, .18));
  color: var(--warn-strong, #a8760a);
}
.zug-schritt__wort { font-weight: 600; font-size: 14px; min-width: 0; }
.zug-schritt.is-erledigt .zug-schritt__wort { font-weight: 500; color: var(--text-secondary); }
.zug-schritt__ding {
  font-size: 13px; color: var(--text-secondary);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.zug-schritt.is-dran { background: var(--warn-bg, rgba(214, 150, 20, .06)); }

/* Der ehrliche Satz ueber der Meldeschicht — leise, aber da. */
.case-hinweis { font-size: 12.5px; color: var(--text-secondary); margin: 0 0 10px; }

/* --- 2b. Der Nachtrag im Altbestand -------------------------------------- */
/* Gegenpruefung Paket P (18.08.2026): ein Fall, der VOR Migration
   20260819100011 offen stand, fuehrt seinen alten Schritt weiter, obwohl das
   Objekt laengst da ist (`fall_stand.weicht_ab`). Die Meldeschicht sagt das
   jetzt selbst — und diese Zeile ist KEINE Fehlermeldung, sondern eine
   Erklaerung. Sie bekommt darum den ruhigen Ton der Kette, nicht das Rot einer
   Absage. `.case-step__hint` selbst wohnt in docs/design/grund.css und bleibt
   dort; hier steht nur der Zusatz (scripts/_stil_einmalig_test.mjs). */
.case-step--nachtrag { border-left: 3px solid var(--good-strong, #1d8a52); }
.case-step__hint--nachtrag {
  color: var(--good-strong, #1d8a52);
  font-weight: 600;
}

/* --- 3. Der naechste Schritt auf der Lead-Karte --------------------------- */
/* `.kanban-card__next` gehoert dem Brett (public/style.css) und bleibt dort —
   hier steht nur, was aus dem Satz eine TUER macht (§7.2). */
.kanban-card__next--tuer {
  display: inline-flex; align-items: center;
  color: var(--accent-strong, var(--info-strong));
  text-decoration: none; font-weight: 600;
}
.kanban-card__next--tuer:hover, .kanban-card__next--tuer:focus-visible { text-decoration: underline; }

/* --- 4. Der naechste Schritt in der Fall-Liste ---------------------------- */
/* Die Zeile trug den Schritt bisher als fetten Text. Jetzt ist er ein Weg zu
   der Arbeit (§7.2) — sichtbar als Weg, aber leiser als der Titel daneben, der
   in den Fall fuehrt. `.mi-mission__schritt` gehoert dem Missionen-Blatt und
   bleibt dort; hier steht nur, was aus dem Satz eine Tuer macht. */
.mi-schritt-tuer {
  display: inline-flex; align-items: center; min-height: 24px;
  color: var(--accent-strong); text-decoration: none;
}
.mi-schritt-tuer:hover { text-decoration: underline; }
.mi-schritt-tuer:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: var(--radius-card); }
.mi-schritt-tuer::after { content: '›'; margin-left: 6px; color: var(--accent); font-size: 14px; line-height: 1; }

/* --- Handy (390 px): kein Querlauf, jeder Griff >= 44 px ------------------ */
@media (max-width: 720px) {
  .ns-schritt, .zug-schritt-panel { align-items: stretch; }
  .ns-schritt .primary-btn, .ns-schritt .ghost-btn,
  .zug-schritt-panel .primary-btn, .zug-schritt-panel .ghost-btn {
    width: 100%; min-height: 44px;
    display: inline-flex; align-items: center; justify-content: center;
  }
  /* Zwei Reihen statt vier Spalten: Zeichen + Wort oben, Ding + Tuer unten.
     Damit passt die laengste Zeile («Rechnung stellen · RE-2026-0042») ohne
     Querlauf auf 390 px. */
  .zug-schritt {
    grid-template-columns: 22px minmax(0, 1fr);
    grid-template-areas: 'zeichen wort' 'ding ding' 'tuer tuer';
    row-gap: 6px;
  }
  .zug-schritt__zeichen { grid-area: zeichen; }
  .zug-schritt__wort { grid-area: wort; }
  .zug-schritt__ding { grid-area: ding; white-space: normal; }
  .zug-schritt > .primary-btn, .zug-schritt > .ghost-btn {
    grid-area: tuer; min-height: 44px;
    display: inline-flex; align-items: center; justify-content: center;
  }
}

/* --- Der Finger-Boden gilt auf JEDEM Touch-Gerät, nicht erst unter 720 px -- */
/* Gemessen 26.08.2026: «Nächster Schritt: …» war auf 768 und 1024 px 612 x 24
   px — breit genug, 20 px zu flach. Die 44er-Zeile stand im 720er-Block, und
   768/1024 sind genau die Bruchzone, die er nicht erreicht
   (Memory project_tablet_touch_breakpoint; dieselbe Lehre steht in
   grund.css §D-03 und patch-leadakte.css §8). Der Layout-Umbau darüber bleibt
   beim Handy — nur der GRIFF-Boden zieht auf alle Touch-Breiten um. */
@media (max-width: 1024px), (pointer: coarse) {
  .kanban-card__next--tuer { min-height: 44px; }
  .mi-schritt-tuer { min-height: 44px; }
}

/* ═══ DIE AKTE IST EINE ARBEITSFLAECHE, KEIN AKTENSCHRANK ═══════════════════
   OWNER-BEFUND 27.08.2026, woertlich: «all diese Logs und was passiert ist —
   das gehoert doch hinten in den Log-Bereich oder irgendetwas, wenn ich das
   hervornehmen moechte. Hier muss Arbeit ausgefuehrt werden und nicht
   Riesen-Informationen.»
   Auf seinem Bild (FA-2026-0163, iPhone) fuellte «Was bisher geschah» den
   halben Bildschirm: dreimal derselbe Zeitstempel, dreimal derselbe Name,
   «Objekt verbunden». Nichts davon ist eine Handlung.
   Es bleibt vollstaendig da und ist EINEN Griff entfernt — die Bauart der
   sechs anderen `details` des Hauses (Muster `.ax-register`,
   patch-ausnahmen.css:202): Dreieck weg, eigener Winkel rechts, der kippt. */
.case-protokoll > summary {
  list-style: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 8px;
  /* Der Griff ist die ganze Zeile — an der Maus 24 px (WCAG 2.2 AA),
     am Finger 44 px (Block unten). Kein `::after`-Kunstgriff noetig:
     die Zeile IST die Flaeche. */
  min-height: 24px;
  font-size: 14px;
  font-weight: 600;
  color: var(--text-primary);
}
.case-protokoll > summary::-webkit-details-marker { display: none; }
.case-protokoll > summary::after {
  content: '';
  margin-left: auto;
  width: 8px; height: 8px;
  border-right: 1.6px solid var(--text-tertiary);
  border-bottom: 1.6px solid var(--text-tertiary);
  transform: rotate(45deg) translate(-2px, -2px);
  transition: transform var(--dur-fast) var(--ease);
}
.case-protokoll[open] > summary::after { transform: rotate(-135deg) translate(-2px, -2px); }
.case-protokoll[open] > summary { margin-bottom: 12px; }
/* Die Zahl sagt VOR dem Oeffnen, wie viel dahinter liegt — sonst ist ein
   zugeklappter Kasten eine Frage statt einer Auskunft. */
.case-protokoll__zahl {
  font-size: 12px;
  font-weight: 500;
  color: var(--text-secondary);
  background: rgba(var(--tint-rgb), .10);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-badge);
  padding: 1px 8px;
}

/* Was der Vorgang ausgelassen hat — eine Zeile, kein Kasten.
   OWNER-BEFUND desselben Tages: bei einem Kunden, der direkt im Rechner
   entstand, standen «Lead anrufen · steht noch aus» und zwei weitere ueber
   einer Kette, die bis zur bezahlten Rechnung durch war. Sie sind jetzt aus
   der Kette heraus — und stehen hier, damit nichts verschwiegen ist. */
.zug-kette__ausgelassen {
  margin: 10px 0 0;
  font-size: 12.5px;
  color: var(--text-tertiary);
}

@media (max-width: 1024px), (pointer: coarse) {
  .case-protokoll > summary { min-height: 44px; }
}

/* ============================================================
   Patch-Integration — Namensraum lx-seitenkopf (Der eine Seitenkopf); Quelle: docs/design/patch-seitenkopf.css
   ============================================================ */
/* =========================================================================
   Patch «Der eine Seitenkopf» — Welle 18.08.2026, Paket M (Muster).
   Gehört als Block ans ENDE von public/style.css. Angehängt wird er
   ausschliesslich über `scripts/_naht_seitenkopf_stil_anhaengen.mjs`, nie von
   Hand; zusammengesetzt wird die Datei von `scripts/stil-bauen.mjs`.

   Präfix: lx-seitenkopf. Farben, Radien und Abstände kommen ausschliesslich
   aus den Fundament-Tokens — hier steht kein roher Hex.

   WAS HIER STEHT UND WAS AUSDRÜCKLICH NICHT.
   Die Bauart selbst ist `.page-head` (grund.css:2840) — Titel links,
   Handgriffe rechts, am Handy fällt der Titel weg, weil ihn die Kopfzeile
   trägt. Sie wird hier NICHT angefasst und NICHT neu definiert: ein Selektor
   gehört EINEM Blatt (BEREICHE.md §10a.3, Wächter `_stil_einmalig_test.mjs`).

   Was `.page-head` allein nicht kann, ist der Fall «Titel + Erklärsatz +
   Handgriff»: als drei Geschwister in einer Reihe stünde der Satz NEBEN dem
   Titel statt darunter. Dafür — und nur dafür — gibt es hier eine Spalte.
   Zwei Flächen bauen sie heute schon von Hand (`views/admin-verguetung.js:129`,
   `views/admin-teamprovision.js:94`); ab jetzt kommt sie aus
   `components/seiten-kopf.js`.
   ========================================================================= */

/* --- 1 · Die linke Spalte: Titel über Erklärsatz ---------------------------
   `min-width: 0` ist Pflicht, nicht Kosmetik: ohne sie kann ein langer
   Erklärsatz das Flex-Kind über die Zeile hinausdrücken, und der Handgriff
   rechts wandert aus dem Bild. Die 4 px unter dem Titel sind dieselben, die
   `.admin-page__head h1` seit dem 06.08. hat — der Abstand bleibt, wenn eine
   Fläche von der alten Bauart auf die eine umzieht. */
.lx-seitenkopf__wort { min-width: 0; flex: 1 1 auto; }
.lx-seitenkopf__wort h1 { margin: 0 0 4px; }

/* --- 1b · Die Reihe NEBEN dem Titel --------------------------------------
   Sieben Flächen hatten dafür je eine eigene Hülle, alle mit demselben Inhalt:
   `.dw-kopf__zeile`, `.ei-kopf__zeile`, `.po-kopf__zeile`, `.pj-kopf__zeile`,
   `.ag-kopf__zeile`, `.wz-kopf__zeile`, `.ar-kopf__zeile` — display:flex,
   gap 12px, flex-wrap. Sie sind am 18.08. aus ihren Blättern entfernt worden;
   das hier ist dieselbe Reihe, EINMAL.
   `align-items: baseline` steht so in fünf der sieben Vorlagen und ist der
   richtige Grund: ein Zähler von 12.5px soll auf der Schriftlinie des 26px-
   Titels sitzen, nicht in seiner Mitte schweben. */
.lx-seitenkopf__zeile {
  display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; min-width: 0;
}
.lx-seitenkopf__zeile h1 { margin: 0; }

/* --- 1c · Wenn die Fläche ihren Namen SELBST trägt ------------------------
   Die Werkbank (`components/cockpit.js`) zeichnet ihren `<h1>` selbst — auf
   `#/k/buchen` standen darum zwei Überschriften übereinander (Gegenprüfung
   Paket M, 18.08.2026). Dort tritt der eine Seitenkopf zurück, und zwar über
   `hidden`: das ist die Sprache des Browsers für «gilt hier nicht», und
   Vorleseprogramme überspringen ihn damit ebenfalls.
   Die Regel ist nötig, weil `.page-head` `display: flex` setzt und damit die
   Vorgabe des Browsers für `[hidden]` überstimmt — ohne diese Zeile bliebe der
   Kopf sichtbar, und das Attribut wäre eine stille Lüge. */
.lx-seitenkopf[hidden] { display: none; }

/* --- 2 · Die rechte Hälfte: die Handgriffe --------------------------------
   Die Haupthandlung einer Fläche sass am 17.08. an 16 verschiedenen Orten.
   Sie hat ab jetzt EINEN: hier. Mehrere Handgriffe stehen nebeneinander und
   brechen erst um, wenn die Zeile zu eng wird — nie einzeln untereinander. */
.lx-seitenkopf__akt { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; }

/* --- 3 · Am Handy ---------------------------------------------------------
   `.page-head` blendet den Titel unter 900 px aus (grund.css:2843) und legt
   sich flach, wenn nur der Titel darin steht. Trägt der Kopf einen
   Erklärsatz, darf er NICHT flach werden — der Satz sagt, was man hier tut,
   und ist am Handy oft die einzige Erklärung. Dieselbe Entscheidung wie in
   patch-chrome.css:606 für die alte Bauart, hier für die eine. */
@media (max-width: 900px) {
  .lx-seitenkopf:has(.admin-page__hint) { display: block; margin-bottom: 12px; }
  .lx-seitenkopf__wort h1 { display: none; }
  /* Dieselbe Handy-Regel wie `.page-head h1` (grund.css:2843): den Namen trägt
     unter 900 px die Kopfzeile der App. Was NEBEN dem Titel stand — Chip,
     Zähler, Fortschritt — bleibt: das ist Inhalt, keine Beschriftung. */
  .lx-seitenkopf__zeile h1 { display: none; }
  .lx-seitenkopf__zeile { gap: 8px; }
  /* …UND DIE HUELLE, DIE DABEI UEBRIG BLIEB (26.08.2026, gemessen).
     Die Zeile darueber nimmt den Titel weg. Was dann noch in der Zeile steht,
     ist der Platz fuer Zahl oder Chip — und der ist beim ersten Zeichnen NOCH
     LEER, auf einer Flaeche ohne Inhalt sogar dauerhaft (views/projekte.js:327
     setzt bei null Projekten bewusst nichts: der Leerzustand darunter sagt es
     schon). Zurueck blieb eine Flex-Zeile mit 0 x 0 px.
     Gemessen an dem Tag, an dem neun bisher UNBELICHTETE Flaechen zum ersten
     Mal auf allen neun Geraetebreiten gemessen wurden: `dateien` und
     `projekte` je auf 390, 430 und 768 px — auf 1280 px trug dieselbe Zeile
     105.7 x 39 px. Genau die Form des Owner-Befundes vom 25.08. («die Karte
     mass 9 x 0»): nicht `display:none`, sondern NULL GROSS.
     `:has()` fragt die einzige Frage, die hier zaehlt: steht in dieser Zeile
     ausser dem weggeblendeten Titel ueberhaupt etwas? Sobald die Zahl
     eintrifft, ist der Platzhalter nicht mehr `:empty` und die Zeile kommt von
     selbst zurueck — kein JS, kein zweiter Zustand, den jemand pflegen muss.
     Das Haus benutzt `:has()` bereits (patch-ortsschild.css §1). */
  .lx-seitenkopf__zeile:not(:has(> :not(h1):not(:empty))) { display: none; }
  .lx-seitenkopf__akt { gap: 8px; }

  /* --- 3b · EIN KOPF, DESSEN EINZIGER GRIFF IN DIE DAUMENLEISTE GEZOGEN IST
     -----------------------------------------------------------------------
     Steht die Leiste am Daumen, ist der Griff im Kopf aus (grund.css,
     `body:has(.lx-unten) [data-neu-handgriff]`) — sonst laese man auf EINER
     Flaeche zweimal «Neu». Der Titel ist am Handy ohnehin aus (die Kopfzeile
     der App traegt ihn). Zurueck blieb ein Kasten von 362 x 0 px, der auf
     jeder anderen Breite 732 x 44 px misst: die Geister-Kachel, die das
     Hausgesetz «jede Bildschirmgroesse ist normal» verbietet.

     GEMESSEN am 05.09.2026 auf der Buehne, 390 x 620:
       kunden  @390  header.page-head.lx-seitenkopf.vk-kopf  362 x 0 px, Rand 8 px
       kunden @1024  derselbe Kopf                           732 x 44 px
     Die Offertenliste hatte denselben Fall und trug dafuer bis heute eine
     eigene Zeile (patch-offertenliste.css) — zwei Abschriften derselben
     Frage. Sie steht jetzt EINMAL hier und gilt fuer beide.

     DIE GRENZE IST DIE DER LEISTE (900 px), nicht die eines Rasters: `:has()`
     fragt den BAUM, und das `nav` steht auf jeder Breite darin (main.js,
     `montiereUnterleiste`) — nackt geschrieben naehme die Regel dem
     Zwischenfeld 901..1080 px den Kopf UND die Leiste zugleich, und auf
     `#/v/offers` gaebe es dort keinen Weg mehr zu einer neuen Offerte.

     DREI BEDINGUNGEN, DAMIT SIE NUR DEN LEEREN KOPF TRIFFT:
       · der einzige Handgriff ist der, der in die Leiste gezogen ist,
       · kein Erklaersatz (`.admin-page__hint`) steht darin,
       · in der Titelzeile steht nichts neben dem Titel (Chip, Zaehler). */
  body:has(.lx-unten) .lx-seitenkopf:has(> .lx-seitenkopf__akt > [data-neu-handgriff]:only-child):not(:has(.admin-page__hint)):not(:has(> .lx-seitenkopf__zeile > :not(h1))) {
    display: none;
  }
  /* HIER STAND EINE AUSNAHME — und sie ist mit ihrem Grund gefallen (18.08.):
     `.lx-seitenkopf--umfang h1 { display: block }` hielt den Titel «Alles von
     heute» am Handy sichtbar, weil er dort Inhalt war und nicht Beschriftung.
     Diese Zeile war der Beleg dafür, dass `views/manager-today.js` keinen
     SEITENkopf brauchte: sie zeichnet den Team-Umfang IN die Fläche «Heute»,
     und die trägt ihren Namen selbst. Der Umfang heisst jetzt in der Bauart
     «Kastenkopf» (`ck-titel` + `<h3>`), und ein `<h3>` fällt am Handy nie weg.
     Eine Ausnahme, die niemand mehr braucht, ist keine Ausnahme — sie ist ein
     Rest (Hausregel 7: ersetzen statt daneben). */
}


/* ===========================================================================
   DAS ERSTE BILD DES BERATERS — die Arbeit vor den Zahlen (22.08.2026)
   ---------------------------------------------------------------------------
   GEMESSEN, nicht vermutet: auf 390x620 (iPhone, Leisten abgezogen) lag die
   Unterkante des Knopfes «Anrufen» bei 690 px. Ueber ihm standen sechs
   Kennzahlen — beim ersten Oeffnen alle auf «—» — und die Werkzeugleiste. Der
   Berater oeffnete die App und sah Nullen; wen er anrufen soll, stand
   ausserhalb des Bildes.

   Die Bauart des Blattes bleibt, wie sie ist (views/advisor-leads.js schreibt
   dieselbe Reihenfolge in den DOM — die Leitung am grossen Bildschirm liest
   ihre Zahlen weiter zuerst). Am Telefon dreht dieser Block nur die ANZEIGE:

     1. die Werkzeugleiste (Heute/Liste/Kanban) — sie sagt, wo er ist
     2. die Arbeit selbst (data-slot="main", mit «Was jetzt» zuoberst)
     3. danach Kennzahlen, Ziel, Provision, Tagesverlauf

   Der Block steht ABSICHTLICH am Dateiende: ein @media-Block, der VOR der
   Basisregel steht, wird von ihr ueberschrieben (Iter-15-Lehre; die frueheren
   kpi-strip-Regeln stehen im Blatt grund.css:2004 und 2058).
   =========================================================================== */
@media (max-width: 720px) {
  #app-view[data-flaeche="berater-heute"] { display: flex; flex-direction: column; }
  #app-view[data-flaeche="berater-heute"] > .lx-seitenkopf { order: 0; }
  #app-view[data-flaeche="berater-heute"] > .filters-panel { order: 1; }
  #app-view[data-flaeche="berater-heute"] > [data-slot="main"] { order: 2; }
  #app-view[data-flaeche="berater-heute"] > .kpi-strip { order: 3; }
  #app-view[data-flaeche="berater-heute"] > [data-slot="goal-panel"] { order: 4; }
  #app-view[data-flaeche="berater-heute"] > [data-slot="provision-panel"] { order: 5; }
  #app-view[data-flaeche="berater-heute"] > [data-slot="activity-stream"] { order: 6; }
}
/* ============================================================
   Patch-Integration — Namensraum kk-karte__/kk-karteband/bs-punkt--griff (Karte am Finger); Quelle: docs/design/patch-karte-finger.css
   ============================================================ */
/* ============================================================
   DIE KARTE AM FINGER — Namensraum kk-karte__ · kk-karteband · bs-punkt--griff
   Quelle: components/schweiz-karte.js · views/kunde-portal.js
   Beweis: scripts/_handy_karte_test.mjs
   ============================================================

   OWNER-BEFUND 23.08.2026, wörtlich: «Alles auf dem Handy funktioniert … das
   ganze Verhalten auf dem Smartphone ist komisch. Die Karte ist statisch,
   komplett katastrophal auf dem Smartphone. Man checkt nicht, warum geht das
   nicht?»

   GEMESSEN (scripts/_handy_karte_test.mjs, 390 px, Finger-Emulation), nicht
   vermutet — drei Befunde, alle drei am selben Ort:

   1. `karteZoombar()` wurde im ganzen Kundenportal NIE gerufen. Das SVG trug
      trotzdem `data-karte-zoombar`, und style.css schaltete daran sogar
      `touch-action` um (`pan-x pan-y` ⇄ `none`). Ein Pinch änderte nichts:
      `data-zoom-an` blieb leer, die Bühnen-Gruppe bekam nie ein `transform`.
      Das Attribut war ein Versprechen ohne Motor.
   2. Die Karte sprach ausschliesslich durch `<title>`. Das erscheint nur unter
      einem MAUSZEIGER. Am Gerät des Owners gibt es keinen — dort hatte kein
      Punkt und kein Kanton eine Aussage.
   3. Ein Tipp auf einen Kanton setzte den Filter, aber die Liste, in der man
      es gesehen hätte, begann 225 px weiter unten. Die Wirkung war da, nur
      nicht im Bild. Genau das ist «man checkt nicht, warum geht das nicht».

   KEINE NEUE ERSCHEINUNG. Hier steht kein einziger neuer Farbwert: Flächen
   kommen aus `--surface-2`/`--surface-inset`, Linien aus `--border`, die Marke
   aus `--accent`/`--accent-rgb`, Schrift aus den drei `--text-*`. Die Bänder
   sind dieselbe Bauart wie `.kk-karte__legende` (patch-rechnungen.css:89) —
   eine ruhige Zeile unter der Karte, keine zweite Kachelsorte.

   KEINE FREMDE KARTENQUELLE. Die Flächen bleiben das eingebettete SVG aus
   `components/schweiz-karte.js` (swisstopo-Geometrie, einmal erzeugt). Zoom
   und Verschieben laufen über eine SVG-Transformation — kein Kachel-Dienst,
   kein zusätzlicher Host, keine CSP-Änderung, kein Egress.
   ============================================================ */

/* ---- Kein fremder Ring um die Karte ---------------------------------------- */
/* GEMESSEN (scripts/_handy_karte_test.mjs): `karteZoombar()` setzt `tabIndex=0`
   auf das SVG, damit +/-/0 auf der Tastatur wirken. Sobald ein FINGER die Karte
   berührt, bekommt sie damit den Fokus — und Chromium malte darum einen
   amberfarbenen Ring von 5 px («outline: auto 5px rgb(229,151,0)») um die
   ganze Karte. In dieser Palette sieht das aus wie eine Fehlermeldung.
   Der Ring der Tastatur bleibt: `:focus-visible` trägt weiter den Akzent
   (patch-konfigurator.css). Weg ist nur der Ring, den ein Finger auslöst. */
.bs-karte[data-karte-zoombar]:focus:not(:focus-visible) { outline: none; }

/* ---- Der Griff am Punkt ---------------------------------------------------- */
/* Alle Masse als RADIUS in Kartenpunkten und DURCHMESSER in echten Bildpunkten,
   gemessen am 390-px-Gerät, wo die Karte 360 px breit steht (Stand 26.08.2026,
   nachdem sie aus dem Panel-Polster getreten ist — Block darunter):
     Kern r=5 → 3,6 px · Ring r=9 → 6,5 px · Trefffläche r=30 → 22 px.
   Die Trefffläche ist damit ehrlich UNTER dem 44-px-Mass des Hauses: 44 px ohne
   Zoom wären hier r=61 Kartenpunkte und legten halbe Kantone unter EINEN Griff.
   Ab doppeltem Zoom hält der Griff 44 px, ab dreifachem 66 px — für Genauigkeit
   gibt es den Zoom, nicht einen Griff, der lügt. Gemessen in
   scripts/_handy_karte_test.mjs, nicht gerechnet. */
.bs-punkt__griff { fill: transparent; }
.bs-punkt--griff { cursor: pointer; }
.bs-punkt--griff:focus { outline: none; }
.bs-punkt--griff:focus-visible .bs-punkt__ring,
.bs-punkt--griff[aria-pressed="true"] .bs-punkt__ring {
  fill: rgba(var(--accent-rgb), .38);
  stroke: var(--accent); stroke-width: 2;
}
.bs-punkt--griff[aria-pressed="true"] .bs-punkt__kern { fill: var(--accent); }

/* ---- Am Handy ist die Karte der Inhalt, nicht ein Bild IM Inhalt ----------- */
/* Gemessen 26.08.2026, 390 px: die Karte stand nur noch 320 px breit da. Die
   Kette frisst sie von beiden Seiten — `main-shell` 14 px, das Panel 20 px,
   sein Rahmen 1 px, also 70 der 390 px allein für Rand (18 %). Der Wächter
   `_handy_karte_test.mjs` hat es gemeldet («Griff 19 px statt 22») und
   niemand hat ihn gerufen; die drei Stellen im Haus, die «351 px» sagten,
   waren seither still falsch.
   Der Titel und das Band darunter behalten ihr Polster — nur das Bild selbst
   tritt heraus. Es gewinnt 40 px zurück, der Griff damit die dokumentierten
   22 px, und die Kantone werden wieder so breit, wie sie beim Bau waren. */
/* Am Rechner ist sie die Karte im halben Panel: kleiner als in der
   Buchungsstrecke, sonst schöbe sie die Rechnungen daneben aus dem Bild.
   (Stand bis 27.08. in patch-rechnungen.css — siehe der Zeiger dort.) */
.kk-karte-panel .bs-karte { max-width: 520px; margin: 2px auto 0; }

@media (max-width: 720px) {
  .kk-karte-panel .bs-karte {
    width: calc(100% + 40px); max-width: none; margin-inline: -20px;
  }
}

/* ---- Das Band unter der Übersichtskarte ------------------------------------ */
.kk-karte__finger {
  margin: 8px 0 0;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  background: var(--surface-inset);
}
.kk-karte__hinweis {
  margin: 0; font-size: 12.5px; line-height: 1.5; color: var(--text-tertiary);
}
.kk-karte__wer {
  margin: 0; display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 10px;
  font-size: 13px; color: var(--text-secondary);
}
.kk-karte__wer b { font-size: 14px; color: var(--text-primary); }
.kk-karte__lage {
  font-size: 11px; font-weight: 700; letter-spacing: .04em;
  text-transform: uppercase; color: var(--accent-strong);
}
.kk-karte__tueren {
  margin: 8px 0 0; display: flex; flex-wrap: wrap; gap: 8px;
}
.kk-karte__tuer { max-width: 100%; }

/* ---- Das Band an der Kaufkarte --------------------------------------------- */
/* Es sagt, was der Tipp getan hat — und trägt den Weg zur Liste und zurück.
   Ohne Kanton steht es gar nicht da: ein leeres Band wäre reiner Platzverbrauch
   (EINHEIT 4.11). */
.kk-karteband {
  margin: 8px 0 0;
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: 8px 12px;
  padding: 9px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  background: var(--surface-2);
}
.kk-karteband__wer {
  margin: 0; display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 8px;
  font-size: 13px; color: var(--text-secondary);
}
.kk-karteband__wer b { font-size: 14px; color: var(--text-primary); }
.kk-karteband__tun { display: flex; flex-wrap: wrap; gap: 8px; }

/* ---- Warum die Karte am Handy ein Schlitz war ------------------------------
   GEMESSEN am echten Safari-Mass 390 x 620 (lib/geraete-masse.mjs), Fläche
   «Werbung buchen», VOR dieser Welle:

     Kopf der Werkbank        61 px
     Schrittband             166 px   ← drei Schritte UNTEREINANDER
     Bühne (Karte + Liste)   112 px   ← alles, was übrig blieb
     Fuss                    111 px

   Die Karte selbst ist 225 px hoch. Sie steckte damit in einem Fenster von
   112 px — man sah einen waagrechten Streifen der Schweiz und musste raten,
   wo man tippt. Genau das meint «komplett katastrophal auf dem Smartphone».

   DIE WURZEL STEHT NICHT HIER, SONDERN AN IHRER STELLE: das Band der Werkbank
   gehört `patch-kundenwege.css` (Namensraum `kk-schrittband`), und dort wollte
   seit dem 21.08. eine Regel genau dieses eine Zeile — sie griff nur nie
   (`flex-wrap` an einem Grid). Repariert ist sie DORT, nicht hier daneben:
   patch-kundenwege.css, Abschnitt 6. Ergebnis: Band 58 px, Bühne 220 px.
   Ein Selektor lebt in genau EINEM Blatt (`npm run test:stil:einmalig`). */

/* ---- Handy ----------------------------------------------------------------- */
/* Am Finger hält jeder Weg 44 px — das Mass des Hauses (WCAG 2.2 AA, bewacht in
   scripts/_handy_anatomie_test.mjs). Auf dem Tisch bleiben die Zeilen schmal,
   weil dort ein Zeiger trifft. */
@media (max-width: 720px) {
  .kk-karteband { justify-content: stretch; }
  .kk-karteband__tun { width: 100%; }
  .kk-karteband__weg,
  .kk-karte__tuer {
    min-height: 44px; flex: 1 1 auto;
    display: inline-flex; align-items: center; justify-content: center;
  }
}

/* ============================================================
   Patch-Integration — Namensraum lx-lesung (Die KI liest den Beleg); Quelle: docs/design/patch-beleg-lesung.css
   ============================================================ */
/* K6/Welle 2 · Die Lesungs-Durchsicht (components/beleg-lesung-dialog.js).
   Namensraum lx-lesung. Beleg links, Felder rechts; die Konfidenz je Feld ist
   ein Wort-Chip in Pillenform (EINHEIT 4.7: gerahmter Chip, nie ein farbiges
   Wort ohne Rahmen), Ampel aus den Haus-Tönen good/warn/bad. */

.lx-lesung { max-width: 1040px; width: min(1040px, calc(100vw - 24px)); }

.lx-lesung__leib { display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 6fr); gap: 18px; }

.lx-lesung__blatt { min-height: 320px; border: 1px solid var(--line);
  border-radius: var(--radius-card); background: var(--surface-inset);
  overflow: hidden; display: flex; align-items: flex-start; justify-content: center; }
.lx-lesung__blatt img { max-width: 100%; height: auto; display: block; }
.lx-lesung__blatt iframe { width: 100%; height: 100%; min-height: 480px; border: 0; }

.lx-lesung__felder { display: flex; flex-direction: column; gap: 10px; min-width: 0; }
.lx-lesung__felder .field > span { display: flex; align-items: center; gap: 8px;
  flex-wrap: wrap; }
.lx-lesung__paar { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }

/* Der Konfidenz-Chip: Wort + Prozent, gerahmt, Pille. */
.lx-lesung__chip { display: inline-flex; align-items: center;
  padding: 1px 8px; border-radius: var(--radius-badge); border: 1px solid var(--line);
  font-size: .72rem; line-height: 1.5; white-space: nowrap;
  color: var(--text-secondary); background: var(--surface-inset); }
.lx-lesung__chip.is-sicher { color: var(--good-strong);
  border-color: rgba(var(--good-rgb), .38); background: rgba(var(--good-rgb), .10); }
.lx-lesung__chip.is-unsicher { color: var(--warn-strong);
  border-color: rgba(var(--warn-rgb), .38); background: rgba(var(--warn-rgb), .10); }
.lx-lesung__chip.is-sehr_unsicher { color: var(--bad-strong);
  border-color: rgba(var(--bad-rgb), .38); background: rgba(var(--bad-rgb), .10); }
.lx-lesung__chip.is-nicht_gelesen { color: var(--text-tertiary); }

.lx-lesung__warnungen { border: 1px solid rgba(var(--warn-rgb), .38);
  border-radius: var(--radius-card); background: rgba(var(--warn-rgb), .08);
  padding: 8px 12px; }
.lx-lesung__warnungen p { margin: 2px 0; font-size: .82rem; line-height: 1.45;
  color: var(--warn-strong); }

.lx-lesung__quelle { margin: 2px 0 0; }

/* KEIN field--wide an den Aktionen: es trägt flex:1 und wächst im
   Spalten-Flex senkrecht (Falle aus Welle 1, am 390-px-Bild gemessen).
   UND KEIN .modal-actions: das ist ab 720 px `position: sticky; bottom: 0`
   mit deckendem Grund (grund.css, Block Handy) — der Balken legte sich auf
   dem Handy über MWST-Satz und MWST-Betrag (Prüfbefund 25.08., Angriff 12).
   Die Ausrichtung nach rechts kommt darum hier, nicht von dort. */
.lx-lesung__aktionen { display: flex; gap: 10px; flex-wrap: wrap;
  justify-content: flex-end; margin-top: 8px; padding-top: 10px;
  border-top: 1px solid var(--line); }
.lx-lesung__aktionen .ghost-btn { flex: 0 0 auto; }

/* Der Buchungs-Kasten: sichtbar abgesetzt — hier fällt die Entscheidung. */
.lx-lesung__buchen { margin-top: 6px; padding: 12px 14px;
  border: 1px solid var(--line); border-radius: var(--radius-card);
  background: var(--surface-inset); display: flex; flex-direction: column; gap: 10px; }
.lx-lesung__buchen-titel { margin: 0; font-weight: 600; font-size: .9rem; }
.lx-lesung__buchen .lx-neu-form__fehler:empty { display: none; }
/* Ein leerer Hinweis nimmt keinen Platz — sonst klaffte unter dem Empfänger
   eine Lücke, solange nichts zu sagen ist. */
.lx-lesung__buchen .so-hint:empty { display: none; }

/* WAS GEBUCHT WIRD, IN FRANKEN — direkt über dem Knopf. Ein Mensch sieht
   einen Tippfehler an «CHF 125'050.00», nie an einem Rohwert im Feld
   (Prüfbefund 25.08., Angriff 11: «1250,50» buchte das Hundertfache). */
.lx-lesung__summe { margin: 0; font-weight: 600; font-size: .92rem;
  color: var(--text-primary); }
/* Seit dem 25.08.2026 traegt diese Klasse dieselbe Zeile auf SECHS weiteren
   Geld-Masken (Was ich schulde · P&L · Journal · Verträge · Entscheide ·
   Guthaben) — dort steht sie in Formularen, die auch leer bedient werden.
   Ein leeres <p> nimmt sonst eine Zeilenhoehe ein und reisst eine Luecke
   ueber dem Knopf auf. Leer heisst hier: es ist noch nichts zu sagen. */
.lx-lesung__summe:empty { display: none; }

/* Brutto/Netto-Widerspruch: warnt, blockiert nie. Leer ist unsichtbar. */
.lx-lesung__achtung { margin: 0; font-size: .82rem; line-height: 1.45;
  color: var(--warn-strong); }
.lx-lesung__achtung:empty { display: none; }

@media (max-width: 860px) {
  .lx-lesung__leib { grid-template-columns: 1fr; }
  .lx-lesung__blatt { min-height: 200px; }
  .lx-lesung__blatt iframe { min-height: 280px; }
  .lx-lesung__paar { grid-template-columns: 1fr; }
}
/* ============================================================
   Patch-Integration — Namensraum lx-weg (Die Weg-Leiste: Lead > Kunde > Offerte > Rechnung); Quelle: docs/design/patch-weg-leiste.css
   Steht ZULETZT: sie wandelt .kpi-pill (grund.css) und den Aktiv-Zustand aus patch-kennzahl-kachel.css ab und muss darum nach beiden stehen.
   ============================================================ */
/* DIE WEG-LEISTE — Lead › Kunde › Offerte › Rechnung, auf allen vier Akten
   Bauteil: public/src/components/weg-leiste.js
   Owner-Entscheid 2026-08-30 nachts, Punkt 3 · gebaut 31.08.2026 (W3c)
   ---------------------------------------------------------------------------
   KEIN NEUES KLEID. Die Leiste IST der Kennzahl-Streifen des Hauses
   (`.panel.kpi-strip` + `.kpi-pill`, docs/design/grund.css:637-641). Alles
   darunter ist Abwandlung derselben Bauform — dieselbe Art, in der
   `.kpi-strip--modal` (grund.css:5036-5044) sie seit je abwandelt.

   WARUM ES DIESES BLATT UEBERHAUPT BRAUCHT — drei Dinge, mehr nicht:
     1. Der Wert einer Kennzahl ist eine ZAHL und darum 24 px gross. Der Wert
        eines Weg-Gliedes ist ein WORT («Angenommen», «Noch keine Rechnung»).
        24 px daraus zu machen sprengt jede Zelle: auf 390 px misst
        «Noch keine Rechnung» in 24 px gemessen 236 px in einer 150-px-Zelle.
     2. `.kpi-pill:first-child { border-left: 0 }` (grund.css:639) nimmt genau
        dem ERSTEN Glied die Linie — und der Aktiv-Zustand des Hauses faerbt
        eben diese Linie (patch-kennzahl-kachel.css:46). Steht man auf dem
        Lead, waere der Zustand unsichtbar gewesen.
     3. Ein Glied, das es noch nicht gibt, spricht leiser als eines, das steht.

   NICHTS DAVON ERFINDET FARBE ODER FORM: jede Angabe unten kommt aus dem
   Token-Block (grund.css `:root`).
   =========================================================================== */

/* 1 · Das Wort ist ein Wort, keine Zahl. */
.lx-wegleiste .kpi-pill strong {
  font-size: 15px;
  font-weight: 600;
  letter-spacing: -.1px;
  line-height: 1.25;
  /* Ein Glied-Zustand ist Text und bricht wie Text. `tabular-nums` der
     Kennzahl gilt Ziffern — hier stehen Woerter. */
  font-variant-numeric: normal;
}
.lx-wegleiste .kpi-pill { padding: 9px 16px; }
.lx-wegleiste .kpi-pill > span { font-size: 11.5px; }

/* 2 · Der Ort, an dem man steht. Dieselbe Aussage wie
   `patch-kennzahl-kachel.css` sie fuer `[aria-current="page"]` fuehrt — nur
   traegt die Weg-Leiste `step`, weil ihr aktuelles Glied bewusst KEIN Weg ist
   (components/weg-leiste.js). */
.lx-wegleiste .kpi-pill[aria-current="step"] {
  border-left-color: var(--accent);
}
.lx-wegleiste .kpi-pill[aria-current="step"] > span {
  color: var(--accent-strong);
}
/* Befund 2 aus dem Kopf: dem ersten Glied nimmt grund.css:639 die Linie.
   Steht man auf ihm, bekommt es sie zurueck — und nur dann. */
.lx-wegleiste .kpi-pill[aria-current="step"]:first-child {
  border-left: 1px solid var(--accent);
}

/* 3 · Ein Glied, das es noch nicht gibt. Es verschwindet NICHT — «Noch keine
   Rechnung» ist eine Auskunft (BEREICHE §7.5) — es spricht nur leiser,
   in derselben Farbe, die das Haus fuer Unterzeilen fuehrt. */
.lx-wegleiste .kpi-pill.lx-wegleiste--leer strong { color: var(--text-tertiary); }

/* 4 · Im Cockpit (Offerten-Rechner) steht die Leiste im Band unter dem Kopf
   (`spec.schritte`, components/cockpit.js). Dort zaehlt jede Zeile Hoehe: die
   Schale rechnet ihre Arbeitsflaeche aus dem, was uebrig bleibt. Darum eine
   Zeile ohne Panel-Polster und ohne Aussenabstand — dieselbe Verdichtung, die
   `.kpi-strip--modal` im Dialog vornimmt. */
.cp .lx-wegleiste {
  margin: 0;
  padding: 0;
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
  border-radius: 0;
  background: var(--surface);
  box-shadow: none;
  flex: 0 0 auto;
}
.cp .lx-wegleiste .kpi-pill { padding: 6px 14px; }
.cp .lx-wegleiste .kpi-pill strong { font-size: 13.5px; }

/* 5 · Schmale Schirme. Der Streifen bricht ohnehin von selbst um
   (`repeat(auto-fit, minmax(150px, 1fr))`), und ab 720 px setzt grund.css:2340
   seine eigene Verdichtung. Was hier fehlte, war die WAAGRECHTE Linie zwischen
   zwei Reihen: ohne sie standen vier Glieder in zwei Reihen ohne sichtbare
   Trennung uebereinander, und die Kette las sich als Liste.
   Owner-Gesetz 2026-08-25 (jede Bildschirmgroesse ist normal): gemessen wird
   die GROESSE, nicht die Anwesenheit — `scripts/_jede_breite_test.mjs`. */
@media (max-width: 720px) and (min-width: 641px) {
  .lx-wegleiste .kpi-pill { padding: 8px 12px; }
  .lx-wegleiste .kpi-pill strong { font-size: 14px; }
  /* Bei zwei Spalten hat jede zweite Zelle links keine Linie, und ab der
     dritten kommt eine oben dazu — Zeichen fuer Zeichen die Regel, die
     `.kpi-strip--modal` fuer denselben Umbruch fuehrt (grund.css:5042-5044). */
  .lx-wegleiste .kpi-pill:nth-child(2n+1) { border-left: 0; }
  .lx-wegleiste .kpi-pill:nth-child(n+3) { border-top: 1px solid var(--border); }
  /* Der Aktiv-Zustand schlaegt die Wegnahme oben — sonst verschwaende er in
     der linken Spalte. */
  .lx-wegleiste .kpi-pill[aria-current="step"]:nth-child(2n+1) {
    border-left: 1px solid var(--accent);
  }
}

/* 6 · Das Handy. GEMESSEN am 04.09.2026 auf der Kundenakte, 390x620, in der
   ECHTEN Huelle (`main-shell`: 14 px Seitenrand, 64 px Kopfreserve): die
   Leiste stand 129 px hoch in zwei Reihen — vier Woerter, die den halben
   Rest des ersten Bildschirms frassen. Die Reiter der Akte begannen dadurch
   bei 636 px und lagen unter der Falte.

   Die Antwort ist die Bauform, die `.stat-strip` (grund.css) und
   `.vk-kacheln` (patch-verkauf.css) am selben Tag bekommen haben: EINE
   flache Reihe, und was nicht hineinpasst, rollt. Ein Weg rollt ohnehin in
   seiner eigenen Richtung — Lead -> Kunde -> Offerte -> Rechnung; der
   aktuelle Schritt steht vorne und ist immer sichtbar.

   Das gilt fuer ALLE VIER Flaechen, die das Bauteil tragen (Kundenakte,
   Lead-Akte, Rechnungs-Akte, Konfigurator) — die Regel steht darum hier im
   Blatt des Bauteils und nicht in einem Flaechen-Blatt.

   Die Zwei-Spalten-Linien oben stehen ab 641 px; unterhalb gibt es keine
   zweite Reihe mehr, deren Fuge man zeichnen muesste. */
@media (max-width: 640px) {
  .lx-wegleiste {
    grid-auto-flow: column;
    grid-template-columns: none;
    /* `max-content` als UNTERE Grenze, nicht 112 px: eine Grid-Spalte klemmt
       ihren Inhalt nicht ab, sie laesst ihn ueberlaufen — und ein Wort wie
       «Zusammengefuehrt» legte sich damit sichtbar ueber die Nachbarzelle
       (gemessen 04.09. auf dem Wegweiser des stillgelegten Kunden, Bild 11).
       So ist jede Spalte mindestens so breit wie ihr laengstes Wort, dehnt
       sich bei Platz auf `1fr` — und was dann nicht mehr hineinpasst, rollt. */
    grid-auto-columns: minmax(max-content, 1fr);
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scrollbar-width: none;
  }
  .lx-wegleiste::-webkit-scrollbar { display: none; }
  .lx-wegleiste .kpi-pill { padding: 8px 12px; }
  .lx-wegleiste .kpi-pill strong { font-size: 14px; }
  .lx-wegleiste .kpi-pill:first-child { border-left: 0; }
}
/* ============================================================
   Patch-Integration — Namensraum lx-griff / ll-; Quelle: docs/design/patch-telefon-griffe.css
   Steht ZULETZT: die Telefon-Regeln muessen .pl-ansichten (patch-partnerliste.css)
   und .filters-toolbar (grund.css) ueberstimmen duerfen. Am Schreibtisch greift keine.
   ============================================================ */
/* ===========================================================================
   DIE TELEFON-GRIFFE — «Ansicht» und «Filter» statt einer Wand aus Reglern
   Namensraum: lx-griff / ll- (Leads-Liste)
   Bauteile: public/src/views/advisor-leads.js · public/src/components/ansicht-wahl.js
   ---------------------------------------------------------------------------
   DER BEFUND (Owner, 05.09.2026, am eigenen Gerät): «in jedem Bereich auf dem
   Handy … alles überlappend … keine Einheitlichkeit, keine Symmetrie.»

   GEMESSEN auf der Fläche «Heute/Leads» (#/m/my-leads?view=kanban&scope=team),
   Bühne wie der Breiten-Wächter, 390 x 620:
       Werkzeug-Fläche 367 px hoch · 18 Bedienteile · 6 Bedienzeilen
   Bei 620 px Fensterhöhe frass die Bedienung 59 % des Bildes, bevor der erste
   Lead kam. Sichtbar waren acht Streifen: Ansichtswechsel · Umfang · zwei
   Handlungen · Zeitraum (rechts abgeschnitten) · Berater/Status · Ansicht ·
   Sichern/Mehr · Trefferzahl.

   DIE REFERENZ (docs/design/referenzen/Portaluikomplett/
   «ChatGPT Image 29. Juli 2026, 13_25_27.png», das iPhone links) beantwortet
   das nicht mit einem Bauteil, sondern mit drei Qualitäten:
     1. LUFT — Kopf, dann sofort Inhalt. Kein Regler steht dauerhaft im Bild.
     2. ORDNUNG wichtig → nebensächlich: das Häufige liegt offen, das Seltene
        hinter einem Griff.
     3. NICHTS ANGESCHNITTEN — jede Beschriftung ist ganz zu lesen.

   DIE ANTWORT: eine Zeile bleibt oben stehen — der Ansichtswechsel («wo bin
   ich») — und daneben zwei Griffe, die je ein Blatt öffnen. Am Schreibtisch
   (ab 721 px) ändert sich kein Pixel: dort ist Platz, dort stehen alle Regler
   an ihrem Ort, und keine einzige Regel dieses Blattes greift.
   =========================================================================== */

/* ---------------------------------------------------------------------------
   DER WIRT — wo ein Blatt hängt, wenn sein Behälter zu klein dafür ist
   ---------------------------------------------------------------------------
   Das Blatt oben liegt IM Behälter (`position: absolute` gegen ihn). Das ist
   richtig, wo der Behälter fast die ganze Fläche einnimmt — im Rechner tut er
   das. Es ist falsch, wo der Griff in einer 60 px hohen Werkzeugleiste sitzt:
   `max-height: 84%` von 60 px sind 50 px, und das Blatt wäre ein Spalt.

   Der Wirt löst das, ohne ein zweites Blatt-Bauteil zu erfinden: eine leere
   Hülle, die am Telefon über die Seite gespannt wird — bis genau zur
   Daumenleiste (`--boden-h`), damit man jederzeit hinauskommt. Sie fängt
   selbst keine Tipper (`pointer-events: none`); nur das Blatt darin tut es.
   Am grossen Bildschirm ist sie gar nicht da, und ihr Inhalt steht an seinem
   normalen Platz.

   Herkunft: diese Regel stand seit dem 08.08. wortgleich als
   `body.lx-pool .pool-werkzeuge` in patch-pool.css — an EINE Fläche gebunden.
   Die Berater-Fläche und die Ansichten-Leiste brauchen dasselbe; drei
   Abschriften derselben Geometrie wären die Doppelspurigkeit, gegen die das
   Blatt überhaupt herausgelöst wurde.
   --------------------------------------------------------------------------- */
.lx-blatt-wirt { display: none; }
/* DER ZUSTAND STEHT AN DER KLASSE, NICHT AN EINER ZWEITEN ZAHL (05.09.2026,
   Runde 2). Das Bedienelement der Ansichten entscheidet selbst, ab wann statt
   der offenen Leiste der Griff steht (`griffAbfrage`, ansicht-wahl.js) — die
   Offertenliste gibt dort 1080 px mit, weil sie ab 1080 px keine Werkzeugzeile
   mehr zeichnet (Owner-Entscheid 08.08.). Stuende die Zahl hier ein zweites
   Mal als Medienabfrage, waere sie zwischen 721 und 1080 px falsch: der Griff
   stuende im Baum und waere unsichtbar — «sichtbar ist nicht bedienbar» in der
   Gegenrichtung. Darum setzt `ordne()` die Klasse `is-griff`, und diese Regeln
   lesen sie. */
.aw.is-griff > .lx-blatt-wirt {
  display: block;
  position: fixed; inset: 0 0 var(--boden-h); z-index: 95;
  pointer-events: none;
}
.aw.is-griff > .lx-blatt-wirt > .lx-blatt { pointer-events: auto; }
.aw.is-griff > .lx-blatt-wirt > .lx-blatt > .lx-blatt__karte { max-height: 88%; }
.aw.is-griff > .aw-griff {
  display: inline-flex; min-height: 44px; min-width: 44px; max-width: 100%;
  padding-inline: 10px; justify-content: flex-start; overflow: hidden;
  flex: 0 1 auto; white-space: nowrap;
}
.aw.is-griff { min-width: 0; }
.aw.is-griff > .aw-griff.is-gesetzt {
  border-color: var(--accent-line, var(--line-strong));
  color: var(--text-primary);
}
@media (max-width: 720px) {
  .lx-blatt-wirt {
    display: block;
    /* ÜBER dem schwebenden «+» (`.qc`, z-index 90 — gemessen am offenen Blatt
       auf 390 px: der Knopf sass bei 320,488 auf 52 x 52 px und lag damit auf
       der Zeile «··· Mehr» des Blattes, die von 14 bis 376 px reicht;
       `elementFromPoint` am rechten Ende der Zeile traf den Knopf, nicht die
       Zeile). Ein Dialog, auf dem ein Knopf schwebt, verschluckt Tipper —
       genau das Überlappen, das der Owner am 05.09. meldete. Geschlossen
       ändert die Zahl nichts: dann ist das Blatt `hidden` und die Hülle
       nimmt ohnehin keine Tipper an. */
    position: fixed; inset: 0 0 var(--boden-h); z-index: 95;
    pointer-events: none;
  }
  .lx-blatt-wirt > .lx-blatt { pointer-events: auto; }
  /* Das Blatt darf hier höher werden als die üblichen 84 %: es spannt sich
     über die ganze Seite, nicht über einen Kasten. 88 % lässt oben genug
     dunklen Streifen, um zum Schliessen getippt zu werden. */
  .lx-blatt-wirt > .lx-blatt > .lx-blatt__karte { max-height: 88%; }
}

/* Die Griffe gibt es nur am Telefon. Am Schreibtisch wären sie ein zweiter Ort
   für Regler, die daneben schon offen stehen — genau die Doppelspurigkeit,
   gegen die «ein Knopf hat einen Ort» geschrieben ist. */
.lx-griffe { display: none; }
/* Die Etiketten der Blöcke gibt es nur im Blatt — in der Werkzeugleiste am
   Schreibtisch stehen die Blöcke nebeneinander und erklären sich. */
.ll-blatt-etikett { display: none; }
/* Der Griff, den das Bedienelement der Ansichten selbst stellt
   (components/ansicht-wahl.js). Am Schreibtisch ist er nicht da — dort steht
   die Leiste selbst an ihrem Platz. */
.aw-griff { display: none; }

/* Das Wort auf einem Griff steht in einem eigenen Träger. Ohne ihn klemmte
   der Knopf sein Wort MITTIG ab — aus «Nur erreichbare» wurde «erreich», weder
   Anfang noch Ende (im eigenen Bild gesehen, 05.09.). `text-overflow` wirkt
   nur auf einen Block mit Text, nicht auf einen Flex-Knopf. */
.lx-griff__wort {
  display: block; min-width: 0; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; text-align: left;
}
.lx-griff__zahl {
  flex: 0 0 auto; display: inline-block; margin-left: 6px; padding: 0 6px;
  border-radius: 999px;
  background: var(--accent-soft, var(--surface-3, var(--surface-2)));
  color: var(--text-primary);
  font-variant-numeric: tabular-nums; font-weight: 650;
}

@media (max-width: 720px) {
  .lx-griffe { display: flex; flex: 0 0 auto; gap: 8px; align-items: center; }
  /* AUF DEN ZWOELF UEBRIGEN LISTEN steht statt der zweizeiligen Leiste dieser
     eine Griff. Er nimmt den Platz ein, an dem die Leiste am Schreibtisch
     steht — die Flaeche muss nichts dafuer tun. */
  .aw-griff {
    display: inline-flex; min-height: 44px; min-width: 44px; max-width: 100%;
    padding-inline: 10px; justify-content: flex-start; overflow: hidden;
  }
  .aw { min-width: 0; }
  .lx-griff {
    flex: 0 0 auto; min-height: 44px; min-width: 44px;
    padding-inline: 10px; white-space: nowrap;
  }
  /* «Hier bin ich» — ein gesetzter Filter oder eine gewählte Ansicht färbt
     ihren Griff, sonst wäre bei geschlossenem Blatt nicht zu sehen, dass die
     Liste geschnitten ist. Dieselbe Sprache wie `.is-active` am
     Ansichtswechsel daneben (grund.css, «Segmented Control»). */
  .lx-griff.is-gesetzt {
    border-color: var(--accent-line, var(--line-strong));
    color: var(--text-primary);
  }

  /* ---- Die eine Zeile, die oben stehen bleibt -------------------------- */
  /* GEMESSEN auf 390 px (Bühne des Breiten-Wächters): die Leiste hat 340 px
     Innenbreite. Der Ansichtswechsel braucht 146 px in seiner natürlichen
     Breite (44 + 44 + 51 px Knöpfe plus Rahmen), die zwei Griffe zusammen
     158 px, dazwischen 8 px Fuge — 312 von 340 px. Es passt, ABER nur wenn
     der Wechsel seine eigene Breite behalten darf: mit `flex: 1 1 0` wurde
     er auf 86 px gequetscht und «Kanban» stand halb da (erste Fassung,
     im Bild gesehen). Darum `flex: 0 1 auto` und Knöpfe, die nicht
     schrumpfen. */
  /* NOWRAP, und die Handlungszeile zieht dafür aus der Leiste aus
     (views/advisor-leads.js, `ordne`). Mit `wrap` schob der Browser die
     Griffe in die nächste Zeile, STATT sie schrumpfen zu lassen — Umbruch
     kommt vor Schrumpfen, und drei Streifen waren wieder da (gemessen:
     Wechsel 178 + Griffe 244 = 430 auf 340 px Platz). */
  .filters-panel .ll-leiste {
    display: flex; flex-direction: row; flex-wrap: nowrap;
    align-items: center; gap: 5px; min-width: 0;
  }
  /* «Wo bin ich» schrumpft NIE: der Wechsel behält seine Breite, und was
     knapp wird, wird beim Griff «Ansicht» knapp (dessen Wort steht ohnehin
     ganz im Blatt). */
  .filters-panel .ll-leiste .view-toggle {
    flex: 0 0 auto; width: auto; min-width: 0; margin-bottom: 0;
    padding: 2px; gap: 2px;
  }
  /* Das Zeichen vor dem Wort kostet 16 px je Knopf und sagt nichts, was das
     Wort nicht sagt. Am Schreibtisch bleibt es. */
  .filters-panel .ll-leiste .view-toggle__btn .vt-ico { display: none; }
  /* DIE RECHNUNG, DIE DIESE ZEILE TRAEGT — gemessen auf 390 px, natürliche
     Breiten bei umbrechendem Behälter (nicht geschätzt):
         Innenbreite der Leiste                          340 px
         Ansichtswechsel (3 Versalien-Wörter)            174 → 168 px
         Griff «Ansicht»                                  84 →  72 px
         Griff «Filter» + Zähler                          67 →  76 px
         zwei Fugen                                       16 →  12 px
     Vorher 356 px auf 340 — darum stand «Kanban» halb da und die Trefferzahl
     29 px ausserhalb des Bildes. Die Sperrung der Versalien bleibt (sie ist
     die Schrift der Referenz), nur enger; das Polster trägt den Rest. */
  .filters-panel .ll-leiste .view-toggle__btn {
    flex: 0 0 auto; min-width: 44px; padding-inline: 4px; justify-content: center;
    font-size: 12px; letter-spacing: .03em;
  }
  /* Die Griffe sitzen rechts aussen — dort, wo der Daumen ohnehin liegt, und
     immer an derselben Stelle, egal wie breit der Wechsel gerade ist. */
  .filters-panel .ll-leiste .lx-griffe {
    margin-left: auto; min-width: 0; flex: 0 1 auto;
  }
  .filters-panel .ll-leiste .lx-griff {
    font-size: 12px; padding-inline: 6px; letter-spacing: .04em;
  }
  .filters-panel .ll-leiste .lx-griff__zahl {
    min-width: 14px; padding: 0 1px; margin-left: 3px; text-align: center;
  }
  /* «Filter» steht immer ganz da — es trägt die Zahl, die sagt, ob die Liste
     geschnitten ist. Der Name der Ansicht darf kürzen: er steht vollständig
     im Blatt, das dieser Griff öffnet. */
  .filters-panel .ll-leiste [data-filter-auf] { flex: 0 0 auto; }
  .filters-panel .ll-leiste [data-ansicht-auf] {
    flex: 0 1 auto; min-width: 44px; overflow: hidden; justify-content: flex-start;
  }
  /* Ab dem grossen Telefon ist Platz für den Namen der gewählten Ansicht.
     Ob er wirklich passt, entscheidet die Fläche am gemessenen Träger
     (advisor-leads.js, `griffeNachziehen`) — nicht diese Breite. */
  @media (min-width: 420px) {
    .filters-panel .ll-leiste [data-ansicht-auf] { max-width: 46vw; }
  }

  /* ---- Zeile zwei: die Hauptaktion und der Zustand daneben -------------- */
  /* «+ Neuer Lead» ist die Handlung dieser Fläche und behält ihren Platz.
     «763 Leads» ist ein ZUSTAND, kein Regler — er zieht in dieselbe Zeile,
     also ohne einen eigenen Streifen. `flex: 1 0 100%` bricht die Zeile
     um; ohne das stand die Handlung neben den Griffen und die Trefferzahl
     29 px ausserhalb des Bildes (gemessen, erste Fassung). */
  .filters-panel .ll-aktionen {
    display: flex; width: 100%; flex-wrap: nowrap; align-items: center; gap: 8px;
  }
  .filters-panel .ll-aktionen .results-pill { margin-left: auto; flex: 0 0 auto; }

  /* ---- Was im Blatt liegt ---------------------------------------------- */
  /* Zwei Felder je Reihe: untereinander bräuchten Umfang, Zeitraum, Berater,
     Status, Region, Verteillauf und Suche mehr Höhe, als das Blatt hat — man
     müsste in einem Blatt rollen, das nicht sagt, dass es weitergeht. */
  .lx-blatt__fach .ll-blatt-filter {
    display: grid; grid-template-columns: 1fr 1fr; gap: 10px; align-items: end;
  }
  .lx-blatt__fach .ll-blatt-filter > * { min-width: 0; }
  /* DIE FÜNF FELDER SIND SELBST DIE RASTERKINDER (Befund 05.09.2026, im
     eigenen Bild gesehen): ohne diese Zeile blieb die Gruppe EIN Rasterkind
     mit 69 px Höhe, und von fünf Feldern war nur «Berater» zu sehen — Status,
     Region, Verteillauf und Suche waren still weg. `display: contents` löst
     die Hülle auf, die Felder ordnen sich zu zweit ein. */
  .lx-blatt__fach .ll-blatt-filter .filters-group { display: contents; }
  .lx-blatt__fach .ll-blatt-filter .field { min-width: 0; width: auto; }
  /* Umfang, Zeitraum und Suche nehmen die ganze Reihe: der Umfang ist die
     gröbste Frage («wessen Leads»), der Zeitraum trägt vier Wörter, und ein
     Suchfeld halber Breite fasst keinen Firmennamen. */
  /* Ohne `>`: seit die Feldgruppe `display: contents` trägt, sind die Felder
     zwar Rasterkinder, aber KEINE DOM-Kinder von `.ll-blatt-filter` — ein
     Kind-Kombinator träfe sie nicht mehr. */
  .lx-blatt__fach .ll-blatt-filter .view-toggle--scope,
  .lx-blatt__fach .ll-blatt-filter .time-range-slot,
  .lx-blatt__fach .ll-blatt-filter .field--search,
  .lx-blatt__fach .ll-blatt-filter [data-slot="hochladen"] { grid-column: 1 / -1; }
  .lx-blatt__fach .ll-blatt-filter .view-toggle--scope { width: 100%; margin: 0; }
  .lx-blatt__fach .ll-blatt-filter .view-toggle--scope .view-toggle__btn { flex: 1 1 0; }
  /* Der Zeitraum lief am Handy rechts aus dem Bild («NÄCHST…»). Im Blatt
     bricht er um, statt zu verschwinden — und er bricht KOMPAKT: mit den
     Polstern der Werkzeugleiste nahm er 144 px von 418 px Fachhöhe, ein
     Drittel des Blattes für sechs Wörter (gemessen 390 px). */
  .lx-blatt__fach .ll-blatt-filter .time-range-tabs { flex-wrap: wrap; gap: 6px; }
  .lx-blatt__fach .ll-blatt-filter .time-pill {
    min-height: 44px; padding-inline: 8px; font-size: 11.5px; letter-spacing: .02em;
  }
  .lx-blatt__fach .ll-blatt-filter .field > span { display: block; }
  /* Das Etikett eines Blocks im Blatt — dieselbe Schrift wie die Etiketten
     der Felder daneben (`.field > span`), damit «Umfang» und «Zeitraum» nicht
     lauter sprechen als «Berater» und «Status». */
  .lx-blatt__fach .ll-blatt-filter .ll-blatt-etikett {
    /* `display` MUSS hier stehen: die Grundregel weiter oben blendet das
       Etikett aus, und die Kaskade entscheidet je EIGENSCHAFT — ein
       spezifischerer Selektor, der `display` nicht nennt, hebt das Ausblenden
       nicht auf (gemessen: Etikett im Baum, Hoehe 0). */
    display: block;
    grid-column: 1 / -1; margin-bottom: -4px;
    font-size: 12px; color: var(--text-secondary);
  }
  .lx-blatt__fach .ll-blatt-filter .ll-blatt-etikett[hidden] { display: none; }

  /* Der Fuss des Blattes: die zwei Wege hinaus. Er steht immer am Boden der
     Karte, damit «Zurücksetzen» auch dann erreichbar ist, wenn das Fach rollt.
     Der Boden des Filter-Blatts steht NEBEN dem rollenden Fach, nicht darin
     (advisor-leads.js, `ordne()`): so rollt der Inhalt hinter ihm durch,
     statt dass er ueber einem halben Feld klebt. Er zeigt sich nur, wenn das
     Filter-Fach offen ist — das ist derselbe Zustand, den das Bauteil schon
     fuehrt (`[hidden]` am Fach), darum liest CSS ihn, statt ihn zu kopieren. */
  .lx-blatt__karte > .ll-blatt-fuss { display: none; }
  .lx-blatt__karte:has(> [data-blatt-fach="filter"]:not([hidden])) > .ll-blatt-fuss {
    display: grid; grid-template-columns: 1fr 1fr; gap: 8px;
    flex: 0 0 auto;
    padding: 12px 14px calc(12px + var(--sab, 0px));
    border-top: 1px solid var(--border); background: var(--surface);
  }
  .lx-blatt__karte > .ll-blatt-fuss > * { min-height: 44px; }
  /* Das Fach traegt seinen eigenen Bodenrand nicht mehr doppelt. */
  .lx-blatt__karte:has(> [data-blatt-fach="filter"]:not([hidden])) > .lx-blatt__fach {
    padding-bottom: 4px;
  }

}

/* ---------------------------------------------------------------------------
   DIE ANSICHTEN-LEISTE IM BLATT — untereinander, jede Zeile ganz lesbar
   ---------------------------------------------------------------------------
   Am Schreibtisch bleibt sie die waagrechte Leiste aus patch-partnerliste.
   ZWEI WEGE, EIN AUSSEHEN: «Heute/Leads» schiebt die ganze Hülle ins Blatt,
   das Bedienelement der übrigen Listen nur seinen Leib. Die Regeln hängen
   darum am Fach, nicht am Weg — und seit dem 05.09. (Runde 2) auch nicht mehr
   an einer Breite: ein Leib liegt genau dann in einem Fach, wenn das Bauteil
   ihn dorthin gelegt hat. Die Offertenliste tut das schon ab 1080 px.
   --------------------------------------------------------------------------- */
.lx-blatt__fach .aw, .lx-blatt__fach .aw__leib { display: block; }
.lx-blatt__fach .pl-ansichten {
  display: grid; grid-template-columns: 1fr 1fr; gap: 8px;
}
/* DIE ZUSTAENDE EINER LISTE IM BLATT (05.09.2026, Runde 2) — dasselbe Raster
   wie die Ansichten darueber. Es ist DASSELBE Bauteil, das am Schreibtisch in
   der Werkzeugleiste steht (`.vk-filterreihe` mit `.vk-filter`, patch-verkauf
   .css:314); dort ist es eine Reihe, hier zwei Spalten. Gleiche Dinge sehen
   ueberall gleich aus — nur der Ort ist ein anderer.
   WARUM ZWEI SPALTEN UND NICHT EINE REIHE: sechs Zustaende messen
   nebeneinander 526 px (gemessen auf 390 px). Untereinander waeren es sechs
   Streifen zu 44 px; zu zweit sind es drei Zeilen, und jedes Wort steht ganz
   da. Erster Nutzer: die Rechnungsliste (views/sales-invoices.js). */
.lx-blatt__fach .vk-filterreihe {
  display: grid; grid-template-columns: 1fr 1fr; gap: 8px;
  flex-wrap: unset;
}
.lx-blatt__fach .vk-filterreihe > .vk-filter {
  min-height: 44px; width: 100%; justify-content: center;
}
.lx-blatt__fach .pl-ansichten + .pl-ansichten { margin-top: 8px; }
.lx-blatt__fach .pl-ansichten > .pl-chip,
.lx-blatt__fach .pl-ansichten > .aw-name { grid-column: 1 / -1; }
.lx-blatt__fach .pl-ansichten .ghost-btn,
.lx-blatt__fach .pl-ansichten .primary-btn { min-height: 44px; }
/* Die zweite Reihe («Weitere Handlungen») trägt am Schreibtisch ein
   Auf-und-Zu. Im Blatt ist ohnehin Platz — sie steht auf ganzer Breite. */
.lx-blatt__fach .pl-ansichten > .lx-zweite-reihe { grid-column: 1 / -1; }
/* ============================================================
   Patch-Integration — Namensraum dz- (Debitoren-Zeile: ein Kunde, seine Rechnungen eingerueckt); Quelle: docs/design/patch-debitoren.css
   Steht ZULETZT: das Blatt wandelt .panel-row__sub (grund.css) und den Zeilengrund der .team-table ab und muss beide ueberstimmen duerfen.
   ============================================================ */
/* =========================================================================
   Debitoren (#/v/offene-posten) — eine Zeile je Kunde, seine Rechnungen
   eingerückt darunter.

   ANLASS (Owner-Bild 05.09.2026 abends): «Offertenkunden sind doppelt,
   dreifach drin, anstatt dass es einmal einen gibt und davon eine
   Profilkarte.» Die Fläche trug zwei Blöcke — «Wer ist heute dran» je
   RECHNUNG und «Nach Alter» je KUNDE —, also denselben Namen zweimal.

   Namensraum: `dz-` (Debitoren-Zeile). Genutzt aus dem Bestand, NICHT neu
   definiert: .team-table/.sl-table (grund.css:1009), .panel-row__sub,
   .table-wrap, .entity-link, .ghost-btn.

   ZWEI REGELN, MEHR NICHT:
   1. Die Kundenzeile trägt die Trennlinie nach oben und etwas mehr Luft —
      sie ist der Kopf ihrer Gruppe, kein Zwischentitel.
   2. Die Rechnungszeile rückt ein und trägt keine eigene Trennlinie: sie
      gehört sichtbar zu dem Kunden über ihr.

   AM TELEFON (< 720 px) ist die Tabelle Kartenform (patch-konfigurator.css:
   1388: tr { display: grid }; die Zellenregel steht in :1411). Eine Einrückung per Zellen-Padding griffe
   dort nicht — darum steht sie als Rahmen links an der ZEILE, der in beiden
   Formen wirkt.

   EINBAU: diesen Block unverändert ans Ende von public/style.css hängen.
   ========================================================================= */

.team-table tr.dz-kunde > td { border-top: 1px solid var(--border-strong, rgba(255,255,255,.14)); padding-top: 12px; }
.team-table tbody tr.dz-kunde:first-child > td { border-top: 0; }
.team-table tr.dz-rechnung { border-left: 2px solid var(--border, rgba(255,255,255,.08)); }
.team-table tr.dz-rechnung > td { border-top: 0; }
.team-table tr.dz-rechnung > td:first-child { padding-left: 18px; }

/* ══ FUENF GELDKACHELN BRAUCHEN MEHR PLATZ ALS FUENF ZAEHLKACHELN ══════════
   GEMESSEN am 05.09.2026 auf 768 px (der Tablet-Bruchzone, die dieses Haus
   schon einmal gekostet hat): `.stat-strip--auto` (grund.css:5173) legt fuenf
   Kacheln bis 720 px in zwei Reihen und darueber in EINE. Bei 768 px blieben
   je Kachel 142 px, davon 38 px Innenabstand und Rahmen — und «CHF 12'000.00»
   misst darin 6 px mehr, als da ist. `body.scrollWidth` 774 bei 768 px
   Fenster, OHNE Rollbalken: genau der Ueberlauf, den niemand sieht.
   Ein Betrag wird nicht abgeschnitten und nicht kleiner gesetzt — er bekommt
   Platz. Unter 900 px stehen die fuenf Altersfenster in zwei Reihen (drei und
   zwei); darueber bleibt alles, wie es ist. Und weil auch eine sechsstellige
   Summe nie
   hinauslaufen darf, bricht der Wert im Notfall um, statt seine Kachel zu
   sprengen — das ist das Netz, nicht die Gestaltung.
   NUR AUF DIESER FLAECHE (`dz-kacheln`, offene-posten.js): sie ist die einzige
   mit fuenf CHF-Kacheln. Die Haus-Regel bleibt unberuehrt — eine Aenderung an
   `.stat-strip--auto` selbst waere eine Aenderung an jeder Flaeche, die sie
   traegt. Beweis: `_mahnwesen_ui_test.mjs` Block L8, neun Geraetebreiten. */
.stat-strip--auto.dz-kacheln .stat__value { overflow-wrap: anywhere; }

/* DIE SPALTENZAHL FOLGT DEM PLATZ, NICHT EINER GERATENEN BREITE. Vorher stand
   hier «unter 900 px drei Spalten» — auf 1024 px liess das fuenf Kacheln zu
   je 194 px stehen, und der Betrag darin brach MITTEN IN DER ZAHL um (gemessen
   06.09.: Bedarf 188 px, Platz 156 px; sichtbar als «CHF 1'000.0» ueber «0»,
   weil `overflow-wrap: anywhere` als letzte Stufe greift).
   Das Mass ist gemessen, nicht gewaehlt: der laengste Betrag der Flaeche
   braucht 188 px in der 26-px-Wertschrift, dazu 2 × 18 px Kachelpolster —
   224 px je Kachel. Fuenf Kacheln brauchen also 5 × 224 + 4 × 14 px Fuge =
   1176 px; darunter sind DREI die richtige Zahl.
   VIER SIND ES NIE. `auto-fit` waere der bequeme Weg, aber es liess auf
   1024 px vier volle Kacheln stehen und die fuenfte allein darunter — eine
   Reihe, die aussieht, als waere sie abgerissen (gesehen 06.09. am Bild).
   Fuenf Dinge verteilen sich auf fuenf Spalten oder auf drei (3+2); dazwischen
   gibt es keine gute Zahl. Faellt ein Betrag laenger aus als in den Testdaten,
   bleibt `overflow-wrap: anywhere` die letzte Stufe — der Notausgang, nicht
   der Normalfall. */
@media (min-width: 641px) and (max-width: 1175px) {
  .stat-strip--auto.dz-kacheln { grid-auto-flow: row; grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

/* AUF DER TABLET-BRUCHZONE ZAHLT DIE TYPOGRAFIE IHREN PREIS. Solange «CHF»
   von seiner Zahl getrennt werden durfte, passte die Tabelle auf 768 px in
   ihren Kasten; mit dem geschuetzten Leerzeichen brauchte sie 749 px bei
   726 px Platz (gemessen 06.09.). Der Platz kommt aus dem waagerechten
   Zellenpolster — 12 px je Seite mal fuenf Spalten sind 120 px, von denen
   23 fehlten. Senkrecht bleibt es unangetastet: dort haengt der 44-px-Griff. */
@media (max-width: 900px) and (min-width: 721px) {
  .table-wrap .team-table.dz-tabelle > * > tr > td,
  .table-wrap .team-table.dz-tabelle > * > tr > th { padding-left: 6px; padding-right: 6px; }
}

@media (max-width: 720px) {
  /* `margin-left` OHNE Breitenausgleich war ein Ueberlauf: die Zeile ist am
     Telefon ein Grid-Kind, das die volle Spur fuellt (gemessen 05.09.:
     offsetWidth 348 in einem 348-px-Kasten) — der Rand kam oben drauf, und die
     Karte lief 12 px hinter ihren Elternkasten. Am Fensterrand war davon
     nichts zu sehen, weil ein Vorfahr klemmt; sichtbar wird es erst, wenn man
     gegen den ELTERNKASTEN misst statt gegen das Fenster. */
  .team-table tr.dz-rechnung { margin-left: 12px; width: calc(100% - 12px); }
  .team-table tr.dz-rechnung > td:first-child { padding-left: 0; }
  /* IST DER KUNDE EXAKT SEINE EINE RECHNUNG, wiederholt seine Zeile Verzug und
     Stufe nicht (offene-posten.js `einzeln`) — die Zellen bleiben leer, damit
     die Tabelle am Rechner ihre Spalten behält. Am Telefon ist jede Zelle
     dagegen eine eigene Rasterzelle mit Beschriftung (patch-konfigurator.css:
     1388/1426): eine leere Zelle stünde dort als leeres Feld im Raster und
     schöbe den Betrag daneben allein an den rechten Rand. Was nichts sagt,
     nimmt am Telefon keinen Platz.
     `.table-wrap` STEHT MIT IM SELEKTOR, und das ist kein Zierrat: die
     Kartenform setzt `display: flex` mit
     `.table-wrap table:has(td[data-label]):not(.sl-table--kern) td` — vier
     Klassen-Gewichte. Ohne `.table-wrap` hier waeren es drei, und die Regel
     waere still ohne Wirkung gewesen (gemessen 05.09.: die leeren Zellen
     standen weiter als `display: flex` im Raster).
     ZWEITES GEWICHT AM 06.09.: die Ueberschrifts-Regeln unten setzen
     `display: block` an DIESELBEN Zellen und wiegen gleich schwer — bei
     Gleichstand gewinnt die spaetere. Darum traegt diese Regel jetzt
     `dz-tabelle` mit und steht am ENDE des Telefon-Kleids (gemessen: ohne
     das las die Probe «7 leere Zellen: block»). */

  /* ═══════════════════════════════════════════════════════════════════════
     AM TELEFON SIND ES ZWEI ZEILENARTEN, NICHT EINE (Befund 05.09.2026 am
     Bild, 390 px). Die Kartenform des Hauses gibt JEDER Zeile denselben
     Kasten — Rahmen, Grund, Etikett links, Wert rechts. Fuer eine DATENZEILE
     ist das richtig; die Kundenzeile ist aber die UEBERSCHRIFT ihrer Gruppe.
     Gemessen stand bei «Barbershop Zentral GmbH» im Kundenkasten «Betrag
     CHF 4'800.00» und direkt darunter im Rechnungskasten noch einmal «Betrag
     CHF 4'800.00»: zwei fast gleiche Kaesten mit demselben Inhalt. Auf dem
     Rechner ist es eine Einrueckung, am Telefon ein zweiter Kasten.

     DAS GEWICHT KOMMT AUS `dz-tabelle` (offene-posten.js). Die Kartenform
     wiegt vier Klassen (`.table-wrap table:has(td[data-label])
     :not(.sl-table--kern) tr` = 3 Klassen + 3 Elemente); ohne die eigene
     Klasse an der TABELLE haetten die Regeln hier weniger Elementgewicht und
     waeren still ohne Wirkung — derselbe Fehler, den die `td:empty`-Regel
     darueber schon einmal gemacht hat.
     ═══════════════════════════════════════════════════════════════════════ */

  /* 1 · Der Kunde ist eine Ueberschrift: kein Rahmen, kein Grund, kein
        Etikett. Zwei Spalten, zwei Zeilen, jede Zelle ausdruecklich gesetzt —
        so kann keine Zelle irgendwohin rutschen, wenn eine andere wegfaellt. */
  .table-wrap .team-table.dz-tabelle tr.dz-kunde {
    display: grid; grid-template-columns: minmax(0, 1fr) auto;
    align-items: baseline; column-gap: 12px;
    margin: 18px 0 8px; padding: 0 2px;
    border: 0; border-radius: 0; background: none;
  }
  .table-wrap .team-table.dz-tabelle tbody tr.dz-kunde:first-child { margin-top: 0; }
  .table-wrap .team-table.dz-tabelle tr.dz-kunde > td {
    display: block; margin: 0; padding: 0; border: 0;
    text-align: left !important;
  }
  /* `[data-label]` STEHT MIT IM SELEKTOR, sonst fehlt ein Attributgewicht:
     die Kartenform setzt das Etikett mit
     `… :not(.sl-table--kern) td[data-label]::before` — vier Klassen-Gewichte
     (`.table-wrap`, das Attribut im `:has`, das `:not`, das Attribut selbst).
     Ohne das Attribut hier waeren es vier gegen vier bei weniger Elementen,
     und die Etiketten klebten am Wert: gemessen 06.09. am Bild auf 390 px
     stand «BetragCHF 3'500.00», «Fällig13 Tg», «StufeNicht gemahnt». */
  .table-wrap .team-table.dz-tabelle tr.dz-kunde > td[data-label]::before { content: none; }
  /* DAS ALTERSFENSTER BEKOMMT DIE VOLLE BREITE. Als Teil der linken Spalte
     blieben ihm 155 px, waehrend sein erstes Paar allein 151 px misst
     (gemessen 06.09.) — dort passt nicht einmal mehr der Trenner hin, und der
     Punkt zwischen den beiden Fenstern stand allein auf einer Zeile. Zweimal
     habe ich versucht, das mit Klebstoff zu loesen (geschuetztes Leerzeichen,
     dann Trenner am Stueck davor); beide Male blieb es stehen, weil nicht die
     Bindung fehlte, sondern der PLATZ.
     Die Zelle gibt darum ihre eigene Box auf. Ihre beiden Kinder — Name und
     Altersfenster, mehr sind es nicht — sitzen dann direkt im Raster der
     Zeile: der Name neben dem Betrag, das Fenster darunter ueber die ganze
     Breite (348 statt 155 px, beide Paare nebeneinander auf einer Zeile).
     Schriftgrad und -gewicht stehen weiter an der Zelle und vererben sich
     durch `display: contents` hindurch. */
  .table-wrap .team-table.dz-tabelle tr.dz-kunde > td:first-child {
    display: contents; font-size: 14px;
  }
  .table-wrap .team-table.dz-tabelle tr.dz-kunde > td:first-child > .entity-link {
    grid-column: 1; grid-row: 1; min-width: 0;
  }
  .table-wrap .team-table.dz-tabelle tr.dz-kunde > td:first-child > .panel-row__sub {
    grid-column: 1 / -1; grid-row: 2; margin-top: 2px;
  }
  .table-wrap .team-table.dz-tabelle tr.dz-kunde > td[data-label="Betrag"] {
    grid-column: 2; grid-row: 1; text-align: right !important;
  }
  /* Die Kopfzeile traegt NAME, ALTERSFENSTER und SUMME — mehr nicht.
     Aeltester Verzug und hoechste erreichte Stufe sind Zusammenfassungen fuer
     die Spalten am Rechner; ohne Spaltenkopf stand am Telefon «13 Tg» und
     «Nicht gemahnt» ohne jeden Bezug in der Ueberschrift (gemessen 06.09. am
     Bild). Was sie sagen, sagt darunter jede Rechnung selbst — mit Datum —
     und in Geld das Altersfenster unter dem Namen. */
  .table-wrap .team-table.dz-tabelle tr.dz-kunde > td[data-label="Fällig"],
  .table-wrap .team-table.dz-tabelle tr.dz-kunde > td[data-label="Stufe"] { display: none; }

  /* 2 · Hat der Kunde genau EINE Rechnung, steht sein Betrag im Kasten
        darunter — die Ueberschrift traegt dann nur Name und Altersfenster.
        Nur die ANZEIGE; die Zahl bleibt an der Zeile (offene-posten.js). */
  .table-wrap .team-table.dz-tabelle tr.dz-kunde.is-allein > td[data-label="Betrag"] { display: none; }

  /* 3 · EINE ANGABE, EINE ZEILE. Die Kartenform stellt zwei Zellen
        nebeneinander (`1fr 1fr`); in einer halben Spalte (155 px bei 390)
        brach jeder laengere Zusatz RECHTSBUENDIG um — gemessen 05.09.:
        «2 Rechnungen · 1 im Mahnlauf», «zahlbar bis 02.09.2026 (10 Tage)»,
        «zahlbar bis 07.09.2026 (15 Tage)» und «Dreimal gemahnt — hier hilft
        kein Brief mehr.» standen je auf zwei Zeilen. Ein rechtsbuendig
        umbrechender Fliesstext liest sich als Fehler.
        Diese Zeilen tragen Datum + Verzug, Betrag + Gebuehrensatz, Stufe +
        Frist und zwei Knoepfe — dafuer ist eine halbe Spalte zu wenig. Mit
        EINER Spalte hat jede Angabe die volle Breite, und der Knopf
        «Mahnung senden» passt wieder in eine Zeile (er brach bei 149 px
        Breite auf zwei — ein umbrechender Knopf ist nie Absicht). */
  .table-wrap .team-table.dz-tabelle tr.dz-rechnung { grid-template-columns: minmax(0, 1fr); }

  /* 4 · DIE KNOPFREIHE BEGINNT AM LINKEN KARTENRAND. Die Kartenform stellt
        Etikett und Wert mit `space-between` an die beiden Raender. Die
        Knopfzelle traegt ein LEERES Etikett (`data-label=""`), das 0 px breit
        ist — `space-between` verteilte den Rest also auf ZWEI Luecken, und die
        Knoepfe klebten rechts mit einem Loch davor: gemessen 06.09. lag die
        Zelle bei 46 px, der erste Knopf bei 64 px, auf 430 px klaffte es
        deutlich weiter. Ein Griff steht dort, wo die Angaben stehen. */
  .table-wrap .team-table.dz-tabelle tr.dz-rechnung > td[data-label=""] {
    justify-content: flex-start;
  }
  /* `justify-content` allein reichte NICHT: das leere Etikett ist zwar 0 px
     breit, bleibt aber ein Flex-Kind — und erbt die `gap` von 8 px. Gemessen
     nach dem ersten Versuch: Zelle bei 46 px, erster Knopf bei 54 px. Ein
     Kind, das nichts sagt, wird entfernt statt verschoben. */
  .table-wrap .team-table.dz-tabelle tr.dz-rechnung > td[data-label=""]::before { content: none; }

  /* 5 · Was nichts sagt, nimmt keinen Platz — siehe die Begruendung oben.
        Steht ZULETZT und traegt `dz-tabelle`, damit es die Regeln 1-3
        ueberwiegt, die an denselben Zellen `display: block` setzen. */
  .table-wrap .team-table.dz-tabelle tr.dz-kunde > td:empty { display: none; }
}

/* Heute verworfen: dieselbe Zeile, gedämpft — sie bleibt bedienbar und steht
   bei ihrem Kunden, statt in einem zweiten Block unten (Owner 05.09.). */
.team-table tr.dz-rechnung.is-weg > td { opacity: .72; }

/* Ein Paar ist ein Stueck: «1–30 Tage CHF 2'500.00», «(10 Tage)»,
   «1 im Mahnlauf». Gebrochen wird zwischen den Paaren, nie in ihnen. */
.dz-paar { white-space: nowrap; }

/* Untertexte in dieser Tabelle sind eigene Zeilen — im Zellenfluss klebten sie
   sonst an den Wert («Coiffure Aebi AGNicht fällig CHF 1'000.00»). */
.team-table tr.dz-kunde .panel-row__sub,
.team-table tr.dz-rechnung .panel-row__sub { display: block; }

/* Der Kunde traegt das Gewicht seiner Gruppe, die Rechnung ordnet sich unter. */
.team-table tr.dz-kunde > td:first-child { font-weight: 600; }

/* Die Rechnungszeile ist EINGESENKT, nicht hervorgehoben: sie gehoert dem
   Kunden ueber ihr. Vorher trug sie den helleren Zeilengrund und stach damit
   staerker hervor als ihr eigener Kunde. */
.team-table tr.dz-rechnung > td { background: rgba(0, 0, 0, .16); }
.team-table tr.dz-rechnung { border-left-color: var(--accent-soft, rgba(120, 170, 200, .35)); }

/* ============================================================
   Patch-Integration — Namensraum kd- (Doppelte Kunden); Quelle: docs/design/patch-kundendoppel.css
   ============================================================ */
/* =========================================================================
   DOPPELTE KUNDEN — #/v/kunden-doppel (views/kunden-doppel.js), 06.09.2026
   Namensraum: kd-

   WAS HIER NEU IST, UND WARUM SO WENIG.
   Die Flaeche steht in der Verkaufs-Huelle (`.admin-page.vk`) und benutzt,
   was das Haus schon hat: den EINEN Seitenkopf (`page-head lx-seitenkopf`),
   das Symbol-Quadrat mit Initialen (`.gz-ic.vk-ini`, patch-verkauf.css:80),
   den Wort-Chip (`.vk-chip`), den Zustands-Chip (`.sl-badge`) und die
   Knopf-Stufen (`.ghost-btn`). Neu ist NUR die Anatomie, die es noch nicht
   gab: eine GRUPPE, in der zwei oder mehr Kunden NEBENEINANDER stehen und
   verglichen werden.

   DIE FARBEN TRAGEN JE EINE BEDEUTUNG (Owner 03.09.: «verschiedene Farben
   fuer verschiedene Bedeutungen»):
     · gruen  (`--good`)  = der bleibt. Haarlinie und Chip, nie Flaeche.
     · gold   (`--warn`)  = daran haengt etwas, das wandert (`.vk-chip--warn`,
                            patch-verkauf.css:361 — hier nur benutzt).
     · neutral            = alles Uebrige.
   Grund, Kante, Ecken und Etiketten kommen aus den Tokens der Referenz
   (`--surface`, `--surface-1`, `--border`, `--radius-card`) — hier steht
   kein einziger roher Farbwert.
   ========================================================================= */

/* --- 1. Der Kopf --------------------------------------------------------- */
/* Der Zaehler steht NEBEN dem Titel (seitenKopf `neben`) und nicht darunter:
   er gehoert zum Namen der Flaeche, nicht zu einer Handlung. Gesperrte
   Versalien wie jedes Etikett der Referenz. */
.kd-zaehler {
  font-size: 11px; font-weight: 650; letter-spacing: .12em;
  text-transform: uppercase; color: var(--text-secondary);
  font-variant-numeric: tabular-nums;
  padding: 3px 9px; border: 1px solid var(--border);
  border-radius: var(--radius-badge); white-space: nowrap;
}
/* EIN LEERER ZAEHLER IST EIN LEERER KASTEN (Befund 07.09.2026 im Bild
   kunden-doppel-rueckweg-1440.png). `zeichnen()` leert ihn in jedem Zweig ohne
   Zahl — Ladefehler, «noch nicht eingerichtet», kein Doppel — aber Haarlinie
   und Polsterung blieben stehen: ein leeres Etikett neben dem Titel. Die
   Wortprobe des Pruefstands sah das nicht, sie liest den TEXT; sichtbar war
   der Rahmen. */
.kd-zaehler:empty { display: none; }

/* --- 1b. Der Weg zurueck ------------------------------------------------- */
/* Er steht ZWISCHEN Kopf und Liste und traegt das Gehaeuse der Akte
   (`.ku-gleiche--weiter`, grund.css + patch-verkauf.css) — dieselbe Sache darf
   an zwei Orten nicht zweierlei aussehen. Darum steht hier fast nichts: nur
   der Fall «kein Zug getan», in dem der leere Halter keine Hoehe nehmen darf.
   Die Kaesten selbst tragen ihren Abstand schon (`.ku-gleiche`,
   margin-bottom 16px). */
.lx-kunden-doppel .kd-rueckwege:empty { display: none; }

/* --- 2. Die Liste der Gruppen ------------------------------------------- */
.lx-kunden-doppel .kd-liste { display: grid; gap: 14px; }

/* Die Gruppe ist ein eigener Kasten mit Haarlinien-Rahmen — sie ist die
   Einheit, ueber die entschieden wird. Ihr Grund liegt TIEFER als die
   Karten darin (`--surface-1` unter `--surface`): so tritt hervor, was
   verglichen wird, und der Rahmen sagt, was zusammengehoert. */
.lx-kunden-doppel .kd-gruppe {
  background: var(--surface-1);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  padding: 12px 14px 14px;
  min-width: 0;
}
.lx-kunden-doppel .kd-gruppe__kopf {
  display: flex; align-items: baseline; flex-wrap: wrap;
  gap: 4px 10px; margin-bottom: 10px; min-width: 0;
}
/* Das Etikett — gesperrte Versalien, wie der Abschnittskopf der Referenz. */
.lx-kunden-doppel .kd-gruppe__wort {
  margin: 0; font-size: 11px; font-weight: 650; letter-spacing: .12em;
  text-transform: uppercase; color: var(--text-secondary); flex: 0 0 auto;
}
/* Der Wert, um den es geht (der Name oder die Nummer). Er darf schrumpfen —
   ohne `min-width: 0` kann ein Flex-Kind nicht unter seine Inhaltsbreite,
   und ein langer Firmenname sprengte die Zeile (Befund 31.08., «Ein
   Ueberlauf ohne Scrollbalken ist der gefaehrlichste»). */
.lx-kunden-doppel .kd-gruppe__wert {
  font-size: 13px; font-weight: 600; color: var(--text-primary);
  min-width: 0; flex: 1 1 auto;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.lx-kunden-doppel .kd-gruppe__zahl {
  margin-left: auto; flex: 0 0 auto;
  font-size: 11.5px; color: var(--text-tertiary);
  font-variant-numeric: tabular-nums;
}

/* --- 3. Die Karten nebeneinander ---------------------------------------- */
/* `auto-fit` und nicht `auto-fill`: leere Spuren fallen zusammen, damit ZWEI
   Kunden wirklich je die halbe Breite bekommen und nicht ein Viertel neben
   zwei leeren Spalten. Unter ~500 px Kastenbreite steht einer unter dem
   anderen — am Telefon ist das die einzige lesbare Form. */
.lx-kunden-doppel .kd-paar {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(auto-fit, minmax(238px, 1fr));
  gap: 10px; align-items: stretch;
}
.lx-kunden-doppel .kd-karte {
  display: grid; grid-template-rows: auto auto 1fr auto; gap: 8px;
  min-width: 0; padding: 12px 13px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
}
/* GRUEN HEISST: DER BLEIBT. Kante und Chip, nie eine gefaerbte Flaeche —
   eine eingefaerbte Karte waere ein zweiter Akzent (EINHEIT.md 1.3). Die
   ganz leichte Toenung ist dieselbe Bauform wie «gewaehlt» in der Referenz,
   nur in der Bedeutungsfarbe dieser Flaeche. */
.lx-kunden-doppel .kd-karte--bleibt {
  border-color: rgba(var(--good-rgb), .38);
  background:
    linear-gradient(rgba(var(--good-rgb), .05), rgba(var(--good-rgb), .05)),
    var(--surface);
}

.lx-kunden-doppel .kd-karte__kopf {
  display: flex; align-items: center; gap: 6px 10px; min-width: 0; flex-wrap: wrap;
}
.lx-kunden-doppel .kd-karte__kopf .gz-ic { --gz-ic-gr: 28px; }
.lx-kunden-doppel .kd-karte__wer { display: grid; gap: 1px; min-width: 0; flex: 1 1 max-content; }
.lx-kunden-doppel .kd-karte__titel {
  font-size: 13px; font-weight: 600; color: var(--text-primary);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.lx-kunden-doppel .kd-karte__titel a { color: inherit; text-decoration: none; }
.lx-kunden-doppel .kd-karte__titel a:hover { text-decoration: underline; }
.lx-kunden-doppel .kd-karte__titel a:focus-visible {
  outline: 2px solid var(--accent); outline-offset: 2px; border-radius: var(--radius-button);
}
.lx-kunden-doppel .kd-karte__sub {
  font-size: 11.5px; color: var(--text-secondary);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  /* Zaehlt nicht zur Kopfbreite — nur der Name entscheidet ueber den Umbruch
     (dieselbe Eindaemmung wie `.vk-karte__sub`, patch-verkauf.css:328). */
  contain: inline-size;
}
/* Der Zustands-Chip bleibt rechts — in der Namenszeile, wenn Platz ist,
   sonst darunter. */
.lx-kunden-doppel .kd-karte__kopf .sl-badge { flex: 0 0 auto; margin-left: auto; }

.lx-kunden-doppel .kd-karte__zahlen {
  display: flex; flex-wrap: wrap; gap: 5px; align-content: start; min-width: 0;
}
/* «Keine Offerte» ist eine Tatsache, aber die leiseste auf der Karte. */
.lx-kunden-doppel .kd-chip--nichts { color: var(--text-tertiary); background: transparent; border: 1px solid var(--border); }

.lx-kunden-doppel .kd-karte__fuss {
  display: flex; flex-wrap: wrap; gap: 3px 8px; font-size: 11px;
  color: var(--text-tertiary); font-variant-numeric: tabular-nums;
  padding-top: 8px; border-top: 1px solid var(--border);
}
.lx-kunden-doppel .kd-karte__fuss > span + span::before { content: '· '; color: var(--text-secondary); }

/* --- 4. Der eine Griff je Karte ----------------------------------------- */
/* WARUM DIE KARTE DES BLEIBERS UNTEN LEER ENDET — das ist Absicht, kein Rest.
   Die Karten einer Gruppe sind gleich hoch (`align-items: stretch`), damit die
   Zeile «Angelegt …» bei allen auf DERSELBEN Hoehe steht: das ist die Zeile,
   an der man «wer ist aelter?» beantwortet, und dafuer muss man nicht die
   Augen wandern lassen. Der Bleiber hat als einziger keinen Griff — an seiner
   Stelle bleibt der Platz des Griffs frei. Wer das «aufraeumt» (etwa mit
   `align-items: start` oder indem der freie Platz nach oben rutscht), gewinnt
   eine buendige Unterkante und verliert die buendigen Datumszeilen. Das waere
   der schlechtere Tausch. */
/* 44 px auf JEDER Breite, nicht erst unter dem Touch-Boden: das ist die
   Handlung dieser Flaeche, und sie steht in einer Karte, die auf 390 px die
   volle Breite hat. `.vk-karte__akt .ghost-btn` schlaegt daneben 30 px vor —
   diese Klasse heisst darum bewusst anders (Memory
   project_griffboden_lebt_in_der_messliste). */
.lx-kunden-doppel .kd-karte__akt {
  display: flex; justify-content: flex-end;
  /* ueber der Fangflaeche des Namens (§5) — sonst schluckt sie den einen
     Griff dieser Karte, genau wie in der Kundenliste (patch-verkauf.css:375). */
  position: relative; z-index: 1;
}
.lx-kunden-doppel .kd-griff {
  min-height: 44px; padding: 6px 14px; font-size: 12px;
}

/* --- 5. Der Name traegt den Daumen, ohne die Zeile zu sprengen ----------- */
/* GEMESSEN, NICHT GEMEINT: `a.kd-karte__tuer` mass auf allen vier Breiten
   84.3 x 16 px (scripts/_kunden_doppel_ui_test.mjs, Block I, Lauf 06.09.).
   Der Griff-Boden dieses Hauses ist 44 px.

   NICHT «MACH DEN NAMEN 44 PX HOCH»: das risse den Kartenkopf auseinander.
   Der Name bekommt eine FANGFLAECHE — dasselbe Mittel, das die Messung
   ausdruecklich kennt (scripts/lib/breiten-mass.mjs, «DIE FANGFLAECHE KANN
   GROESSER SEIN ALS DAS KAESTCHEN»).

   UND ZWAR DIE SCHMALE FORM (patch-pool.css, «DIE TAPFLAECHE OHNE DIE
   HOEHE»), NICHT die ganze Karte wie in der Kundenliste
   (patch-kundenkarte-griff.css §3). Dort IST die Karte die Tuer. Hier ist
   sie das Gegenteil: der Gegenstand, ueber den entschieden wird. Wer zwei
   Kunden vergleicht, faehrt mit dem Finger ueber Zahlen und Datum — waere
   die ganze Karte ein Link, riefe jedes Lesen einen Seitenwechsel hervor.
   Das Band ist so breit wie der Name und liegt mittig ueber ihm; es deckt
   die Ortszeile darunter mit ab, und die ist reiner Text.

   `position: relative` am Anker selbst: ohne ihn bezieht sich `left/right`
   auf die Karte statt auf das Wort. */
.lx-kunden-doppel .kd-karte__titel a { position: relative; }
.lx-kunden-doppel .kd-karte__titel a::after {
  content: ''; position: absolute;
  left: 0; right: 0; top: 50%;
  height: 44px; transform: translateY(-50%);
}

/* =========================================================================
   Handy (Projekt-Cascade-Regel: eigener Block NACH den Basis-Regeln oben,
   Memory project_css_cascade_mobile).
   ========================================================================= */
@media (max-width: 720px) {
  .lx-kunden-doppel .kd-gruppe { padding: 10px 11px 12px; }
  .lx-kunden-doppel .kd-paar { grid-template-columns: 1fr; }
  /* Am Telefon nimmt der Griff die ganze Breite der Karte — auf 390 px ist
     ein rechtsbuendiger Knopf mit 100 px Rand daneben verschenkte Flaeche. */
  .lx-kunden-doppel .kd-karte__akt { justify-content: stretch; }
  .lx-kunden-doppel .kd-griff { width: 100%; }
}
/* ============================================================
   Patch-Integration — Namensraum tk- (Tätigkeiten); Quelle: docs/design/patch-taetigkeiten.css
   ============================================================ */
/* =========================================================================
   TÄTIGKEITEN — #/m/taetigkeiten (07.09.2026)
   «Wann war wer aktiv, und was hat er getan» je Person, nur für den Inhaber.

   ES WIRD NICHTS ERFUNDEN. Die Fläche trägt `.panel`, `.table-wrap` und
   `.team-table` — dieselbe Tabellenform wie «Wer hält was» daneben
   (views/manager-overview.js). Was hier steht, ist ausschliesslich das, was
   diese vier Spalten brauchen und `grund.css` nicht kennt:
   die Rolle unter dem Namen, die Zahlenspalte rechtsbündig, das gedämpfte
   Wort für «noch nie», und der Weg ins Detail.

   FARBEN: keine einzige Roh-Farbe. Alles kommt aus den Tokens der Referenz
   vom 10.08. (grund.css: --text-secondary, --text-tertiary, --border,
   --accent). Wer hier einen Hex-Wert einträgt, steht ausserhalb der
   Farbwahrheit — dafür gibt es die Skip-Zone im Token-Block, sonst nirgends.

   NEUN BREITEN (Owner-Gesetz 25.08.): Die Tabelle trägt `team-table sl-table`
   und `data-label` an jeder Zelle — damit greifen unter 720 px bzw. 640 px
   die zwei Handy-Bauteile des Hauses (Block ganz unten), und die 640 px
   Mindestbreite aus `.team-table` (grund.css `min-width: 640px`) nimmt die
   sl-Fassung selbst zurück. Gemessen mit
   `node scripts/_jede_breite_test.mjs --nur=taetigkeiten`: 21/21 auf
   390 · 430 · 768 · 1024 · 1280 · 1366 · 1440 · 1680 · 1920 — kein Querlauf,
   keine Deckung, kein Griff unter dem Boden.
   ========================================================================= */

/* Die Filterzeile: der Zeitraum links, die Person daneben, der Zähler rechts.
   Eine Reihe, die umbricht statt zu drücken. */
.tk-filter {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
}
/* Der Zähler steht rechts, egal wie viel links steht — `margin-left: auto`
   statt `space-between`: mit drei Kindern schöbe `space-between` die Person
   in die Mitte und risse die Reihe auseinander. */
.tk-filter .results-pill { margin-left: auto; }
/* Die Personen-Auswahl bleibt schmal genug, dass Zeitraum und Zähler auf einer
   Laptop-Breite daneben Platz haben, und wächst am Handy auf die volle Zeile —
   dort steht sie ohnehin allein. */
.tk-person { min-width: 190px; }
@media (max-width: 720px) {
  .tk-person { flex: 1 1 100%; min-width: 0; }
  .tk-filter .results-pill { margin-left: 0; }
}
/* Die Zeitraum-Reiter nehmen nur, was sie brauchen. `.time-range-slot` traegt
   `width: 100%` (grund.css, `.time-range-slot`) — dort ist er das einzige
   Kind seiner Zeile,
   hier stehen zwei weitere daneben, und die volle Breite schob die
   Personen-Auswahl auf eine eigene Zeile, den Zähler allein daneben (am Bild
   gesehen, 1440 px, 07.09.). `width: auto` nimmt ihm die Breite, `flex: 0 0
   auto` das Wachsen; unter 720 px bekommt er sie zurück (Block unten). */
.tk-filter > .time-range-slot { flex: 0 0 auto; width: auto; }
@media (max-width: 720px) {
  .tk-filter > .time-range-slot { flex: 1 1 100%; width: 100%; }
}

/* Die Rolle steht UNTER dem Namen, nicht daneben: der Name ist die Antwort
   auf «wer», die Rolle nur ihre Einordnung. Versalien gesperrt — das
   Etikett-Idiom der Referenz (grund.css, EINHEIT 1.5). */
.tk-rolle {
  display: block;
  margin-top: 3px;
  font-size: 11px;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--text-tertiary);
}

/* Zahlen rechtsbündig und in Tabellenziffern: nur so stehen die Stellen
   untereinander und man sieht ohne Lesen, wer mehr getan hat. */
.tk-zahl {
  text-align: right;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* «Noch nie» und «Kein Vorgang in diesem Zeitraum» sind Aussagen, keine
   Fehler — gedämpft, nie in der Warnfarbe. Ein Mensch ohne Vorgang ist die
   wichtigste Zeile dieser Fläche; sie soll auffallen, ohne anzuklagen. */
.tk-still { color: var(--text-tertiary); }

/* Der Weg in den Ereignis-Strom, gefiltert auf diese Person. Er steht am
   Ende der Zeile und tritt erst hervor, wenn die Zeile gemeint ist —
   dieselbe Zurückhaltung wie `.ck-mehr` in der Zentrale. */
/* DER GRIFF-BODEN GILT AUCH FUER EIN KLEINES WORT (Owner-Gesetz 25.08.:
   «Bildschirmgroessen duerfen nie ein Hindernis sein»; Memory
   `project_griffboden_lebt_in_der_messliste`). Gemessen 07.09. mit
   `node scripts/_jede_breite_test.mjs --nur=taetigkeiten`: der Link mass
   92.4 x 19 px am Finger und 92.4 x 16 px an der Maus — auf ALLEN NEUN
   Breiten unter dem Boden (44 px Finger, 24 px Maus). Die Breite reichte
   laengst; nur die Hoehe fehlte. `inline-flex` mit `min-height` gibt sie ihm,
   ohne ihn aus der Zeile zu heben — eine unsichtbare Fangflaeche
   (`::after`) waere hier falsch: am Handy stehen die Zeilen dicht
   uebereinander, und ein 44 px hohes Kaestchen legte sich ueber den Namen
   der Nachbarzeile. */
.tk-detail {
  display: inline-flex;
  align-items: center;
  min-height: 24px;
  margin-left: 8px;
  white-space: nowrap;
  font-size: 12px;
  color: var(--text-tertiary);
  text-decoration: none;
  border-bottom: 1px solid transparent;
}
@media (max-width: 1024px), (pointer: coarse) {
  .tk-detail { min-height: 44px; }
  /* DER HOEHERE GRIFF BRAUCHT SEINE EIGENE REIHE. Mit 44 px ist der Link
     hoeher als die Textzeile neben ihm; als Inline-Kasten legt er sich ueber
     sie (gemessen 07.09. mit `node scripts/_jede_breite_test.mjs
     --nur=taetigkeiten`: «ueberlappung span.tk-liste~a.tk-detail — decken
     einander 92.4 x 28.5 px» auf 768 und 1024). Aus der Zelle wird darum eine
     umbrechende Reihe: Text und Griff sind Geschwister, nicht Nachbarn in
     einer Zeile — und der Griff behaelt seine volle Hoehe, ohne die Zeile
     darueber zu verdecken. */
  .tk-tabelle td[data-label="Tätigkeiten"] {
    display: flex; flex-wrap: wrap; align-items: center; gap: 2px 8px;
  }
  .tk-tabelle .tk-detail { margin-left: 0; }
}
.tk-zeile:hover .tk-detail,
.tk-detail:focus-visible { color: var(--accent); border-bottom-color: var(--border); }

/* Der gesperrte Zugang ist eine Tatsache über den Menschen, nicht über seine
   Arbeit — er steht beim Namen, klein, und nimmt der Zeile nichts weg. */
.tk-gesperrt { margin-left: 8px; vertical-align: middle; }

/* --- Schmale Geräte ------------------------------------------------------
   ES WIRD KEINE ZWEITE HANDY-FASSUNG GEBAUT. Die Tabelle trägt `.sl-table`
   UND `data-label` an jeder Zelle — damit greifen die zwei Bauteile, die das
   Haus dafür hat, und keines davon wird nachgebaut:
     · `@media (max-width: 720px)` in grund.css stapelt `.sl-table`
       (Etikett links, Wert rechts) und nimmt `min-width: 640px` zurück,
     · `@media (max-width: 640px)` in patch-konfigurator.css macht daraus
       die Karte: `tbody` als Raster, jede Zeile ein Rahmen, zwei Spalten
       `minmax(0, 1fr)`, die erste Zelle über beide.

   Der erste Entwurf hatte beides nachgebaut. Am Bild gemessen (390 px,
   07.09.): «Vorgänge» stand doppelt in der Zeile (eigenes `::after` PLUS
   Etikett), `min-width: 640px` blieb stehen, und die Tätigkeiten-Zeile stand
   in einer 141-px-Spalte mitten in der Karte. Was hier bleibt, ist die EINE
   Stelle, an der diese Fläche wirklich anders ist als eine Liste. */
@media (max-width: 640px) {
  /* Die Tätigkeiten sind der längste Wert der Karte — in einer der zwei
     Rasterspalten (gemessen 141 px) bricht «38 Leads übernommen · 3 ×
     Systemvorgang» in vier Zeilen. Sie bekommt darum beide Spalten und liest
     sich von links, wie der Name darüber. */
  .tk-tabelle td[data-label="Tätigkeiten"] {
    grid-column: 1 / -1;
    justify-content: flex-start;
  }
  /* Die Ausrichtung wird am KIND gesetzt, nicht an der Zelle: die Kartenregel
     (patch-konfigurator.css, Block «max-width: 640px», Regel für `td`)
     trägt `text-align: right !important` mit
     höherer Spezifität — ein zweites `!important` von hier verlöre den
     Vergleich und wäre eine Regel, die aussieht, als wirke sie. Der Wert
     liest sich von links wie der Name darüber; das Etikett bleibt, wo die
     Karte es hat. */
  .tk-tabelle .tk-liste { width: 100%; text-align: left; }
  /* Der Weg ins Detail steht dann auf seiner eigenen Zeile und trägt dort
     seinen vollen Griff (44 px, siehe oben) — hinter einem umbrechenden Satz
     wäre er nicht zu treffen. */
  .tk-tabelle td[data-label="Tätigkeiten"] .tk-detail {
    display: flex; margin-left: 0; width: 100%; justify-content: flex-start;
  }
}


.appointment-plan fieldset { min-width:0; padding:0; border:0; }
.appointment-plan .field { min-width:0; }
.appointment-plan__outcome { background:var(--surface-2); padding:12px; }
.usage-explanation { max-width:85ch; padding:0 16px; line-height:1.6; color:var(--text-secondary); }
.usage-panel td { vertical-align:top; }
.usage-panel td small { display:block; color:var(--text-secondary); margin-top:4px; }
.usage-state.is-active { color:var(--good); font-weight:600; }
.usage-history { display:grid; gap:6px; max-height:280px; overflow:auto; padding:12px 0; }
.usage-history > div { display:grid; grid-template-columns:90px minmax(60px,1fr) 58px; gap:8px; align-items:center; font-variant-numeric:tabular-nums; font-size:11px; }
.usage-history meter { width:100%; height:16px; accent-color:var(--accent); }

.people-list { min-width:0; table-layout:auto; }
.people-list th,.people-list td { padding:12px; }
.people-list .people-list__contact,.people-list .people-list__since { display:block; font-size:12px; color:var(--text-secondary); line-height:1.5; overflow-wrap:anywhere; }
.people-list .people-list__edit { display:block; margin-top:6px; min-height:36px; padding:5px 8px; font-size:11px; text-transform:none; letter-spacing:normal; }
@media(max-width:700px) {
 .people-list .people-list__edit { min-height:44px; }
 .usage-panel .sl-table { min-width:0; }
 .usage-panel td { overflow-wrap:anywhere; }
 .usage-history > div { grid-template-columns:minmax(80px,1fr) minmax(50px,1fr) 48px; }
}

.usage-method { margin:0 16px 12px; color:var(--text-secondary); font-size:13px; line-height:1.5; }
.usage-method > summary { cursor:pointer; min-height:32px; padding:5px 0; }
.usage-panel .usage-table details,.usage-panel .usage-table summary { white-space:normal; max-width:100%; }
@media(max-width:720px) {
 .usage-panel .table-wrap table.usage-table tbody tr { display:grid; grid-template-columns:minmax(0,1fr) minmax(0,1fr); gap:12px; }
 .usage-panel .table-wrap table.usage-table tbody td[data-label] { display:block; text-align:left; width:auto; min-width:0; padding:0; white-space:normal; }
 .usage-panel .table-wrap table.usage-table tbody td:first-child,
 .usage-panel .table-wrap table.usage-table tbody td[data-label="Beobachtete Nutzung"] { grid-column:1/-1; }
 .usage-panel .table-wrap table.usage-table tbody td[data-label]::before { display:block; position:static; width:auto; margin:0 0 4px; text-align:left; }
 .usage-panel .usage-history { width:100%; }
 .usage-method > summary { min-height:44px; }
}
/* ============================================================
   Patch-Integration — Namensraum st- (Statistik: die Kette Anruf→Abschluss); Quelle: docs/design/patch-statistik.css
   Steht ZULETZT: das Blatt haengt sich an `.stat` und `.sl-table` aus grund.css und muss beide ueberstimmen duerfen.
   ============================================================ */
/* =========================================================================
   STATISTIK — #/m/goals (07.09.2026)
   «Wie viele wurden erreicht, wie viele davon terminiert, wie viele davon
   abgeschlossen» — die Kette an EINEM Lead, mit Quote dazwischen, Delta
   darunter und einem Rueckweg an jeder Zahl.

   ES WIRD NICHTS ERFUNDEN. Die Kacheln sind das Bauteil des Hauses
   (`kennzahlKachel` -> `.stat`, grund.css), die Tabelle ist `team-table
   sl-table` wie «Wer haelt was» daneben, die Filterzeile ist der Zuschnitt,
   den `patch-taetigkeiten.css` fuer dieselbe Reihe schon gefunden hat. Neu
   ist hier ausschliesslich das, was eine KETTE braucht und eine Kachelreihe
   nicht kennt: der Verbinder mit der Quote, das Feld der Stufe «verloren»,
   und die zwei Verhaeltnis-Spalten der Tabelle.

   WARUM DIE QUOTE ZWISCHEN DEN KACHELN STEHT UND NICHT DARIN: EINHEIT 4.1
   erlaubt der Kachel GENAU EINE Zusatzzeile, und die gehoert dem Delta mit
   seinem Bezug («+18 zum Vormonat»). Die Quote ist ohnehin keine Eigenschaft
   einer Kachel, sondern die Beziehung ZWEIER — sie steht darum dort, wo sie
   hingehoert: dazwischen.

   FARBEN: keine einzige Roh-Farbe. Alles aus den Tokens der Referenz vom
   10.08. (--text-secondary, --text-tertiary, --border, --accent, --bad-rgb).

   NEUN BREITEN (Owner-Gesetz 25.08.): die Kette bricht um, statt zu draengen;
   die Tabelle traegt `sl-table` + `data-label` an jeder Zelle und faellt
   damit in die zwei Handy-Bauteile des Hauses. Gemessen mit
   `node scripts/_jede_breite_test.mjs --nur=statistik`.
   ========================================================================= */

/* Die Filterzeile: Zeitraum links, «Wessen» daneben, das gezaehlte Fenster
   rechts. Eine Reihe, die umbricht statt zu druecken — derselbe Zuschnitt
   wie `.tk-filter`, nur mit anderem Inhalt. */
.st-filter {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
}
.st-filter .results-pill { margin-left: auto; }
/* `.time-range-slot` traegt `width: 100%` (grund.css) — dort ist er das
   einzige Kind seiner Zeile. Hier stehen zwei weitere daneben, und die volle
   Breite schoebe sie auf eigene Zeilen. */
.st-filter > .time-range-slot { flex: 0 0 auto; width: auto; }
@media (max-width: 720px) {
  .st-filter > .time-range-slot { flex: 1 1 100%; width: 100%; }
  .st-filter .results-pill { margin-left: 0; }
}

/* --- Die Kette ----------------------------------------------------------
   SIEBEN STUFEN, ZWEI BEWUSSTE REIHEN — NIE EIN ZUFAELLIGER UMBRUCH
   (07.09.2026, Sazans Blick, Fund 17).

   Bis heute war die Kette eine umbrechende Flex-Reihe mit fester Kachelbreite.
   Wo der Umbruch fiel, entschied allein die Restbreite: auf 1440 px standen
   5 + 2 Glieder, auf 768 px 3 + 2 + 2 — und «davon Abschluss» stand verwaist
   allein in der zweiten Zeile. Eine Kette, die man von links nach rechts liest,
   darf nicht an einer Stelle brechen, die niemand gewaehlt hat.

   Seit heute ist es ein RASTER mit vier erklaerten Zustaenden:
     · ab 1680 px    sieben Spalten — die ganze Kette in EINER Reihe, die
       Quote NEBEN ihrer Kachel.
     · 721-1679 px   vier Spalten, die Quote UEBER ihrer Kachel — genau ZWEI
       Reihen, 4 + 3. Der Schnitt faellt hinter «davon offen»; die Reihe
       darunter beginnt mit «davon Termin» und traegt die drei Stufen, in denen
       sich verkauft.
       BIS HEUTE ABEND stand die Quote schon ab 1280 px daneben — und die
       zwei Stufen ohne Quote rueckten um ihre Breite ein: auf 1440 px lag
       zwischen «Anrufe» und «Leads angerufen» ein Loch, und «44 % Termin-
       Quote» begann die zweite Reihe allein am linken Rand (Sazans Blick
       07.09. abends, Fund 4). Ueber der Kachel gibt es keinen Einzug und
       keinen Waisen; nebeneinander steht sie erst, wenn alle sieben in einer
       Reihe stehen.
     · bis 720 px    eine Spalte — eine Reihe je Stufe, Quote darueber (am
       Telefon liest sich die Kette ohnehin von oben nach unten).
   Gemessen auf allen neun Geraetebreiten des Hauses
   (`node scripts/_statistik_ui_test.mjs`, Probe 5c).

   DIE GRENZEN SIND GEMESSEN, NICHT GEWAEHLT. Die Kachel braucht fuer ihren
   eigenen Inhalt 99 px (Textspalte 61 px fuer «angerufen», dazu 38 px fuer
   Zeichen und Innenabstand); der Verbinder daneben 72 px plus 8 px Abstand.
   Zur Verfuegung steht (Hausbuehne, `.st-kette` innen): 768 px Geraet -> 670,
   1024 -> 690, 1280 -> 938, 1440 -> 1089, 1680 -> 1320, 1920 -> 1544.
     · Sieben Spalten nebeneinander brauchen 7 x 179 + 60 = 1313 px — das
       passt ab 1680, auf 1440 (1089) nicht. Erzwungen blieben der Kachel dort
       63 px und ihr Inhalt liefe um 60 px hinaus, ohne Rollbalken: genau der
       Ueberlauf, den niemand sieht (BELEGE 31.08.).
     · Vier Spalten nebeneinander brauchen 4 x 179 + 30 = 746 px — das passt ab
       1280, auf 1024 (690) nicht.
     · Steht die Quote ueber der Kachel, braucht eine Spalte nur 99 px; vier
       davon 426 px. So tragen auch 768 und 1024 px die zwei Reihen 4 + 3. */
.st-kette {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  align-items: stretch;
  gap: 10px;
}
@media (min-width: 721px) {
  .st-kette { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}
@media (min-width: 1680px) {
  .st-kette { grid-template-columns: repeat(7, minmax(0, 1fr)); }
}
/* Das Glied: die Quote und die Kachel, zu der sie gehoert — EIN Rasterkind.
   Ohne diese Klammer entschied die Restbreite, ob eine Quote noch neben ihre
   Kachel passt; auf fuenf von neun Breiten stand sie am Ende der Zeile davor
   und las sich als Quote der falschen Stufe (gemessen 07.09., Pruefer). */
.st-glied {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 6px;
  min-width: 0;
}
/* Ab hier steht der Verbinder NEBEN seiner Kachel. Die zwei Stufen ohne Quote
   («Anrufe», «Leads angerufen») ruecken dann um genau seine Breite ein: so
   stehen alle sieben Kacheln gleich breit und in derselben Spur — ohne ein
   leeres Element im Baum, das eine Vorlesehilfe ansagen muesste.
   DIESE REGELN STEHEN HINTER DER GRUNDREGEL, NICHT DAVOR: ein `@media`-Block
   hebt die Gewichtung nicht an; stand er weiter oben, gewann die spaetere
   Grundregel und die Kachel sprengte ihre Spalte um 80 px (gemessen 07.09.). */
@media (min-width: 1680px) {
  .st-glied { flex-direction: row; gap: 8px; }
  .st-glied--start { padding-inline-start: 80px; }
}
/* Die Kachel fuellt, was das Glied uebrig laesst. Sie hat KEINE feste Breite
   mehr (bis heute 145 px): im Raster bestimmt die Spalte die Breite, und alle
   sieben Spalten sind gleich — genau das, was die feste Breite erreichen
   wollte und bei jedem Umbruch verlor. */
.st-kette .st-kachel { flex: 1 1 auto; min-width: 0; }

/* Der Verbinder. Er ist KEINE Kachel: kein Rahmen, keine Flaeche, keine Tuer
   — er sagt nur, in welchem Verhaeltnis die beiden Nachbarn stehen. */
.st-quote {
  flex: 0 0 auto;
  /* Volle Breite, solange die Quote UEBER ihrer Kachel steht; 72 px, sobald
     sie daneben steht (ab 1680 px, unten). Schmaler als 72 ging es nicht —
     bei 62 px sprengte «ABSCHLUSS-QUOTE» den Kasten auf sieben von neun
     Breiten um je 3 px (Messung 07.09.), und ein Ueberlauf ohne Rollbalken
     ist der, den niemand sieht. */
  width: auto;
  /* Ein langes Wort darf nie wieder ueber den Rand: hier bricht es. */
  overflow-wrap: anywhere;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1px;
  text-align: center;
  line-height: 1.15;
}
/* Ueber der Kachel liest sich der Verbinder als Zeile, nicht als Saeule. */
@media (max-width: 1679px) {
  .st-quote {
    flex-direction: row;
    flex-wrap: wrap;
    justify-content: flex-start;
    align-items: baseline;
    text-align: left;
    gap: 2px 6px;
  }
}
@media (min-width: 1680px) {
  .st-quote { flex: 0 0 72px; width: 72px; }
}
.st-quote > b {
  font-size: 15px;
  font-weight: 650;
  font-variant-numeric: tabular-nums;
  color: var(--text-primary);
}
/* NAME UND BEZUG, ZWEI ZEILEN (07.09.2026, Fund 19). Der Name im Etikett-Idiom
   der Referenz (klein, gesperrt, Versalien — grund.css, EINHEIT 1.5), der
   Nenner darunter in normaler Schreibung: «44 % / TERMIN-QUOTE / der
   erreichten». Ohne die zweite Zeile stand «44 %» zwischen zwei Zahlen und
   niemand konnte sagen, von welcher.
   11 px, NICHT weniger: der Schrift-Boden des Hauses ist 11 px (DESIGN.md §2),
   und `scripts/_schrift_boden_test.mjs` laeuft im Auslieferpfad. */
.st-quote__wort {
  font-size: 11px;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--text-tertiary);
}
.st-quote__bezug {
  font-size: 11px;
  color: var(--text-tertiary);
  opacity: .8;
}

/* Die Zusatzzeile der Kachel traegt das Delta und BLEIBT am Telefon stehen.
   Der Geraete-Block in grund.css blendet `.stat__sub` aus — aber nur
   innerhalb von `.stat-strip`; hier ist der Container `.st-kette`, und die
   Zeile ist keine Verzierung: ohne sie steht die Zahl ohne ihren Vergleich
   da, und genau der Vergleich ist die Frage der Leitung.

   SIE DARF UMBRECHEN (07.09.2026). Hier stand `white-space: nowrap` — und
   «+27 zum Vormonat» misst 105 px. In der Kachel blieben davon auf 1920 px
   90 px sichtbar, auf 1024 px 43 px: die Zeile lief auf SIEBEN von neun
   Breiten ueber ihren Kasten hinaus, ohne Rollbalken. Zwei Zeilen sind kein
   Schaden; ein abgeschnittener Vergleich ist einer. */
.st-kette .stat__sub { white-space: normal; }

/* Die Stufe «verloren» bekommt ihr eigenes Feld. Die Bereichs-Toene des
   Hauses (patch-zentrale.css, `.gz-ic--*`) kennen kein «verloren» — und die
   Farbe ist hier keine Verzierung, sondern die Antwort auf «wo endet es».
   Der Ton kommt aus dem Token, nie aus einem Hex-Wert. */
.gz-ic--verloren { --gz-feld: var(--bad-rgb); }

/* --- Je Berater ----------------------------------------------------------
   Die Tabelle ist die des Hauses. Was hier steht, ist nur, was ihre neun
   Spalten brauchen. */

/* Die Rolle unter dem Namen — dieselbe Bauart wie `.tk-rolle` daneben. */
.st-rolle {
  display: block;
  margin-top: 3px;
  font-size: 11px;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--text-tertiary);
}

/* Zahlen rechtsbuendig, in Tabellenziffern: nur so stehen die Stellen
   untereinander und man sieht ohne Lesen, wer wie viel getan hat.
   MIT DER TABELLE IM SELEKTOR (07.09.2026 abends): `.sl-table td` in grund.css
   setzt `text-align` mit zwei Klassen; `.st-zahl` allein verlor — die Zahl MIT
   Weg stand trotzdem rechts (ihr Griff ist 24 bzw. 44 px breit und schiebt
   die Ziffer an sein Ende), die Null OHNE Weg blieb links: Marcos «0» stand
   11 px (1440) bzw. 35 px (768) neben Sazans «8». */
.st-tabelle td.st-zahl,
.st-zahl {
  text-align: right;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
/* «Anrufe je Termin» ist kein Bestand, sondern ein Verhaeltnis — gedaempft,
   damit die gezaehlten Spalten daneben die Zeile fuehren. */
.st-je { color: var(--text-secondary); }
/* «—» heisst «dafuer fehlt die Grundmenge», nicht «null». Es steht gedaempft
   da, nie in der Warnfarbe: ein Berater ohne Termine ist kein Fehler. */
.st-still { color: var(--text-tertiary); }

/* DIE ZEILE OHNE ANRUF (07.09.2026, Fund 2). Sie ist kein Fehler und keine
   Warnung — sie ist die Auskunft, nach der die Leitung sucht. Darum steht sie
   gedaempft und ohne Farbe, aber ueber die ganze Breite: EIN Satz statt fuenf
   Nullen und drei Gedankenstrichen. */
.st-ohne { color: var(--text-tertiary); }

/* JEDE ZAHL IST EIN WEG (Soll 7) — und ein Weg braucht seinen Griff, auch
   wenn er nur drei Zeichen breit ist (Owner-Gesetz 25.08., Memory
   `project_griffboden_lebt_in_der_messliste`). Die Zahl allein maesse rund
   12 x 19 px; das ist auf keiner der neun Breiten zu treffen. `inline-flex`
   mit `min-height` und einer Mindestbreite gibt ihr die Flaeche, ohne sie
   aus der Zeile zu heben. */
.st-zahl > a {
  display: inline-flex;
  align-items: center;
  justify-content: flex-end;
  min-height: 24px;
  min-width: 24px;
  color: inherit;
  text-decoration: none;
  border-bottom: 1px solid transparent;
}
.st-zeile:hover .st-zahl > a,
.st-zahl > a:focus-visible { color: var(--accent); border-bottom-color: var(--border); }
@media (max-width: 1024px), (pointer: coarse) {
  .st-zahl > a { min-height: 44px; min-width: 44px; }
}

/* DIE TABELLE AUF DEM TABLET (07.09.2026 abends, Sazans Blick, Fund 6).
   Auf 768 und 1024 px mass die Tabelle 900 px in einem Kasten von 670 bzw.
   690 px: sie rollte seitlich, «Leads je Abschluss» war halb zu sehen und
   «Es hakt bei» gar nicht — genau die Spalte, die die Frage der Leitung
   beantwortet («aber dann scheitert es beim Abschluss»), lag ausserhalb des
   Bilds. Die Koepfe durften nicht umbrechen, jede Zelle trug 12 px Rand.
   Umbrechende Koepfe und 5 px Rand bringen sie auf 670 px (gemessen auf
   der Hausbuehne, 768 -> 672 mit 6 px, darum 5). Nichts wird versteckt. */
@media (min-width: 721px) and (max-width: 1279px) {
  .st-tabelle th { white-space: normal; }
  .st-tabelle th, .st-tabelle td { padding-inline: 5px; }
  .st-tabelle td:first-child { white-space: normal; }
}

/* --- Schmale Geraete -----------------------------------------------------
   ES WIRD KEINE ZWEITE HANDY-FASSUNG GEBAUT. Die Tabelle traegt `.sl-table`
   UND `data-label` an jeder Zelle; damit greifen die zwei Bauteile, die das
   Haus dafuer hat (grund.css `@media (max-width: 720px)` stapelt und nimmt
   `min-width: 640px` zurueck; patch-konfigurator.css `@media (max-width:
   640px)` macht daraus die Karte). Hier steht nur, was diese Flaeche wirklich
   anders macht. */
@media (max-width: 720px) {
  /* EINE STUFE JE REIHE. Nebeneinander frisst der Verbinder
     («67 % ERREICHT-QUOTE der angerufenen») die Breite der Kachel: gemessen
     320 px Kachel bei «Anrufe» gegen 72 px bei «davon erreicht», und der
     Inhalt lief um 49 px hinaus. Uebereinander bekommt jede Kachel die volle
     Breite, und alle sieben sind wieder gleich gross. */
  .st-quote > span { white-space: nowrap; }
}
@media (max-width: 640px) {
  /* In der Kartenform steht der Name des Beraters ueber beiden Spalten; die
     Zahlen darunter lesen sich von rechts, wie in jeder anderen Karte des
     Hauses. Nur die letzte Spalte traegt ein Wort statt einer Zahl und
     bekommt darum die volle Breite. */
  .st-tabelle td[data-label="Es hakt bei"] {
    grid-column: 1 / -1;
    justify-content: space-between;
  }
  /* In der Kartenform traegt die Zeile ohne Anruf ihren Satz ueber beide
     Spalten — und KEIN `data-label`, sonst stuende ein leeres Etikett davor. */
  .st-tabelle td.st-ohne { grid-column: 1 / -1; }
  .st-tabelle td.st-ohne::before { content: none; }
}

/* --- Der Rueckweg in der Lead-Liste --------------------------------------
   #/m/my-leads, wenn die Adresse einen Schnitt aus der Statistik traegt.
   Ohne diese Zeile stuende die Liste geschnitten da und niemand wuesste,
   warum — und ohne den Knopf gaebe es keinen Weg zurueck ins Ganze
   (BEREICHE §11.6: keine Absage ohne Ausweg). */
.ll-statschnitt {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 10px;
  margin-bottom: 12px;
}
.ll-statschnitt__wort { color: var(--text-secondary); font-size: 13px; }
/* ============================================================
   Patch-Integration — Namensraum ec- (Persönliche Auslagen und Originale); Quelle: docs/design/patch-employee-claims.css
   ============================================================ */
/* Personal expenses use the existing house surfaces, rows, controls and type. */
.employee-claims { width:100%; min-width:0; }
.employee-claims .lx-seitenkopf { margin-bottom:24px; }
.employee-claims button, .employee-claims input:not([type="checkbox"]),
.employee-claims select, .employee-claims .ec-file-pick { min-height:44px; }
.employee-claims textarea { min-height:92px; resize:vertical; }
.employee-claims button svg, .ec-file-pick svg { width:18px; height:18px; flex:none; }
.employee-claims button:focus-visible, .employee-claims a:focus-visible,
.ec-file-pick:focus-within { outline:2px solid var(--accent); outline-offset:3px; }
.ec-tabs { display:flex; align-items:center; gap:8px; margin-bottom:24px; border-bottom:1px solid var(--border); }
.ec-tabs button { color:var(--text-secondary); background:transparent; border:0; padding:12px 16px; font-size:14px; cursor:pointer; }
.ec-tabs button.is-active { color:var(--accent-strong); box-shadow:inset 0 -2px var(--accent); }
.ec-tabs [data-action="reload"] { margin-left:auto; }
.ec-workspace { display:grid; grid-template-columns:minmax(270px,.72fr) minmax(0,1.6fr); gap:24px; align-items:start; }
.ec-list, .ec-detail-slot, .ec-read-grid>* { min-width:0; }
.ec-list>.field { margin-bottom:16px; }
.ec-list-rows { padding:0; }
.employee-claims .ec-row { width:100%; border:0; border-bottom:1px solid var(--border); border-radius:0; background:transparent; color:var(--text); display:flex; gap:16px; padding:20px; align-items:start; text-align:left; cursor:pointer; }
.employee-claims .ec-row:last-child { border-bottom:0; }
.employee-claims .ec-row:hover { background:var(--surface-hover); }
.employee-claims .ec-row.is-active { background:var(--accent-soft); box-shadow:inset 2px 0 var(--accent); }
.employee-claims .ec-row__select { display:flex; width:100%; min-width:0; gap:16px; align-items:start; padding:0; border:0; border-radius:0; background:transparent; color:inherit; text-align:left; font:inherit; text-transform:none; letter-spacing:normal; white-space:normal; }
.ec-row__main { display:grid; gap:6px; min-width:0; flex:1; }
.ec-row__main strong { font-size:15px; line-height:1.4; overflow-wrap:anywhere; }
.ec-row__main>span { font-size:13px; color:var(--text-secondary); overflow-wrap:anywhere; }
.ec-row__main small { color:var(--text-tertiary); font-size:12px; }
.ec-row__end { display:grid; gap:12px; justify-items:end; font-size:13px; font-variant-numeric:tabular-nums; flex:none; }
.ec-state--returned, .ec-state--submitted { color:var(--warn); border-color:var(--warn); }
.ec-state--rejected { color:var(--bad); border-color:var(--bad); }
.ec-detail { padding:28px; }
.ec-detail-empty { padding:40px 20px; }
.ec-detail-head { display:flex; gap:16px; align-items:start; margin-bottom:28px; }
.ec-detail-head>div { flex:1; min-width:0; }
.ec-detail-head h2 { font-size:24px; font-weight:550; margin:0 0 8px; overflow-wrap:anywhere; }
.ec-detail [data-action="back"] { display:none; }
.ec-hint { color:var(--text-secondary); font-size:13px; line-height:1.6; max-width:72ch; margin:8px 0 16px; }
.employee-claims h3 { font-size:15px; font-weight:600; margin:0 0 16px; }
.ec-form, .ec-read-grid { display:grid; grid-template-columns:minmax(0,1.15fr) minmax(230px,.85fr); gap:32px; }
.ec-form-fields { min-width:0; }
.ec-form .field { margin-bottom:18px; }
.ec-form-pair { display:grid; grid-template-columns:1fr 1fr; gap:16px; }
.ec-form .field span, .ec-assignment .field span { line-height:1.5; }
.ec-payment { border:0; border-top:1px solid var(--border); padding:20px 0 0; margin:12px 0 20px; }
.ec-payment legend { font-size:15px; font-weight:600; padding:0 8px 0 0; }
.ec-check { display:flex; gap:12px; align-items:center; min-height:44px; cursor:pointer; font-size:14px; }
.ec-check input { width:20px; height:20px; flex:none; }
.ec-actions { display:flex; gap:12px; align-items:center; flex-wrap:wrap; margin-top:20px; }
.ec-save-note { font-size:12px; color:var(--text-secondary); }
.ec-section-head { display:flex; gap:12px; justify-content:space-between; align-items:center; }
.ec-section-head h3 { margin:0; }
.ec-original { min-width:0; border-left:1px solid var(--border); padding-left:28px; }
.ec-file { display:flex; gap:12px; margin:20px 0; overflow-wrap:anywhere; }
.ec-file svg { width:22px; height:22px; flex:none; color:var(--text-secondary); }
.ec-file>span { display:grid; gap:8px; min-width:0; }
.ec-file strong { font-size:14px; font-weight:500; }
.ec-file small { font-size:12px; color:var(--text-secondary); }
.ec-file-pick { display:flex; gap:8px; align-items:center; justify-content:center; position:relative; cursor:pointer; overflow:hidden; }
.ec-file-pick input { position:absolute; inset:0; opacity:0; cursor:pointer; width:100%; }
.ec-preview { margin:20px 0; }
.ec-preview img { display:block; max-width:100%; max-height:650px; object-fit:contain; background:var(--surface-inset); }
.ec-facts { margin:0; }
.ec-facts>div { display:grid; grid-template-columns:minmax(120px,.8fr) minmax(0,1.2fr); gap:16px; padding:14px 0; border-bottom:1px solid var(--border); }
.ec-facts dt { color:var(--text-secondary); font-size:13px; }
.ec-facts dd { margin:0; overflow-wrap:anywhere; font-size:14px; line-height:1.5; white-space:pre-wrap; }
.ec-facts .ec-amount { font-size:20px; font-variant-numeric:tabular-nums; }
.ec-notice { background:var(--surface-inset); padding:18px 20px; margin:0 0 24px; border:1px solid var(--line-strong); font-size:14px; }
.ec-notice p { margin:8px 0 12px; color:var(--text-secondary); line-height:1.6; max-width:72ch; }
.ec-notice--error strong { color:var(--bad); }
.ec-review-reason { padding:0 0 20px; margin-bottom:24px; border-bottom:1px solid var(--border); }
.ec-review-reason strong { color:var(--warn); font-weight:500; }
.ec-review-reason p { white-space:pre-wrap; line-height:1.6; margin-bottom:0; }
.ec-review-form, .ec-assignment, .ec-history { border-top:1px solid var(--border); padding-top:28px; margin-top:32px; }
.ec-review-form textarea { width:100%; }
.ec-assignment form { display:flex; gap:16px; align-items:end; }
.ec-assignment .field { flex:1; margin:0; }
.ec-history-revisions, .ec-history-events { padding:0; margin:0; }
.ec-history-entry { display:block; padding:12px 0; }
.ec-history-line { display:flex; align-items:center; flex-wrap:wrap; gap:12px; }
.ec-history-line>span:last-child { margin-left:auto; font-variant-numeric:tabular-nums; }
.ec-history [aria-current="true"] { color:var(--accent); }
.ec-history-events { color:var(--text-secondary); font-size:13px; line-height:1.6; }
.ec-history-events>.panel-row { display:block; padding:8px 0; border:0; }
.ec-history-events p { white-space:pre-wrap; color:var(--text); margin:4px 0; }
@media (max-width:1550px) {
  .ec-workspace { grid-template-columns:minmax(250px,.7fr) minmax(0,1.5fr); }
  .ec-form, .ec-read-grid { grid-template-columns:minmax(0,1fr); gap:24px; }
  .ec-original { border-left:0; border-top:1px solid var(--border); padding:24px 0 0; }
  .ec-row__select { flex-wrap:wrap; }
  .ec-row__end { display:flex; width:100%; align-items:center; justify-content:space-between; }
}
@media (max-width:900px) {
  .ec-workspace { grid-template-columns:minmax(0,1fr); }
  .employee-claims.has-selection .ec-list { display:none; }
  .employee-claims:not(.has-selection) .ec-detail-slot { display:none; }
  .ec-detail [data-action="back"] { display:block; }
  .ec-detail-head { flex-wrap:wrap; }
  .ec-detail-head>div { flex-basis:70%; }
  .ec-detail-head [data-action="back"] { flex-basis:100%; text-align:left; padding-left:0; }
  .ec-detail { padding:24px; }
  .ec-tabs { flex-wrap:wrap; }
  .ec-tabs button { padding:12px; }
}
@media (max-width:480px) {
  .ec-detail { padding:20px 16px; }
  .ec-detail-head h2 { font-size:20px; }
  .ec-form-pair { grid-template-columns:1fr; gap:0; }
  .ec-facts>div { grid-template-columns:1fr; gap:6px; }
  .ec-assignment form { flex-direction:column; align-items:stretch; }
  .ec-actions { align-items:stretch; flex-direction:column; }
  .ec-actions button { width:100%; }
  .ec-history-line>span:last-child { margin-left:0; }
  .ec-tabs [data-action="reload"] { margin-left:0; }
}
@media (prefers-reduced-motion:reduce) {
  .employee-claims *, .employee-claims *::before, .employee-claims *::after { animation:none !important; transition:none !important; }
}

/* The financial path stays beside the original, on the same claim. */
.ec-finance { border-top:1px solid var(--border); padding-top:28px; margin-top:32px; }
.ec-finance p { line-height:1.6; overflow-wrap:anywhere; }
.ec-finance-check { margin-bottom:24px; }
.ec-finance-check strong { color:var(--accent); font-weight:500; }
.ec-finance-form { margin-top:24px; padding-top:24px; border-top:1px solid var(--border); }
.ec-finance-form .field { display:grid; gap:8px; margin-bottom:18px; }
.ec-finance-form textarea { width:100%; }
.ec-finance-form>button { margin-top:16px; }
.ec-finance-form summary { min-height:44px; cursor:pointer; display:flex; align-items:center; color:var(--accent); }
.ec-finance-form summary:focus-visible { outline:2px solid var(--accent); outline-offset:3px; }
.ec-finance-location { display:grid; grid-template-columns:1fr 1fr; gap:16px; margin:20px 0; }
.ec-finance-location label { display:grid; gap:8px; font-size:13px; }
.ec-finance-location input,.ec-finance-location select { width:100%; min-width:0; }
.ec-finance-totals { display:grid; grid-template-columns:1fr 1fr; gap:16px; margin:24px 0; }
.ec-finance-totals>div { padding:16px 0; border-bottom:1px solid var(--border); }
.ec-finance-totals dt { color:var(--text-secondary); font-size:13px; margin-bottom:10px; }
.ec-finance-totals dd { margin:0; font-size:22px; font-variant-numeric:tabular-nums; }
.ec-payments { margin:0; padding:0; list-style:none; }
.ec-payments li { padding:16px 0; border-bottom:1px solid var(--border); }
.ec-payments li>div { display:flex; justify-content:space-between; gap:16px; flex-wrap:wrap; }
.ec-payments strong { font-weight:500; font-variant-numeric:tabular-nums; }
.ec-payments span,.ec-payments small { color:var(--text-secondary); font-size:13px; }
.ec-payments small { display:block; margin-top:8px; }
@media(max-width:480px) { .ec-finance-location,.ec-finance-totals { grid-template-columns:1fr; } }

/* Keep the current result above the original and the detailed audit trails. */
.ec-finance-status { margin:0 0 28px; padding:24px 0; border-block:1px solid var(--border); }
.ec-finance-status p { line-height:1.6; overflow-wrap:anywhere; }
.ec-finance-status .ec-finance-check { margin:0; }
.ec-finance-status summary { min-height:44px; display:list-item; cursor:pointer; padding:12px 0; font-size:14px; color:var(--accent); }
.ec-finance-status summary:focus-visible { outline:2px solid var(--accent); outline-offset:3px; }
.ec-finance-decision[open] { padding-bottom:16px; }
.ec-finance-decision>div { padding:16px 0; }
.ec-finance-decision strong { font-weight:500; }
.ec-overpaid dd { color:var(--warn); }
@media(max-width:480px) {
  .ec-finance-totals { grid-template-columns:1fr 1fr; gap:12px; }
  .ec-finance-totals dd { font-size:20px; }
  .ec-finance-status { padding:20px 0; }
}

.ec-notice--confirmed { border:0; background:transparent; padding:0; color:var(--text-secondary); font-size:13px; }
.ec-finance>:first-child { margin-top:0; padding-top:0; border-top:0; }
.ec-finance-totals { grid-template-columns:repeat(auto-fit,minmax(140px,1fr)); }
.ec-history>summary { min-height:44px; padding:12px 0; font-size:15px; font-weight:600; cursor:pointer; color:var(--accent); }
.ec-history>summary:focus-visible { outline:2px solid var(--accent); outline-offset:3px; }
@media(max-width:480px) { .ec-finance-totals { grid-template-columns:1fr 1fr; } }

/* ============================================================
   Patch-Integration — Namensraum fn- (Finanzierungen); Quelle: docs/design/patch-financing.css
   ============================================================ */
/* Financing uses the existing house head, account record, rows and controls. */
.financings { min-width:0; }
.financings>.lx-seitenkopf { margin-bottom:20px; }
.financings>.view-toggle { display:flex; gap:8px; flex-wrap:wrap; margin-bottom:28px; }
.financings>.admin-page { padding:0; }
.financings button,.financings input,.financings select { min-height:44px; }
.financings :is(button,a,input,select,textarea,summary):focus-visible { outline:2px solid var(--accent); outline-offset:3px; }
.financings :is(h1,h2,h3,p,dd,b,small) { overflow-wrap:anywhere; }
.fn-kpis { display:grid; grid-template-columns:repeat(4,minmax(0,1fr)); gap:16px; margin:28px 0; }
.fn-kpis .stat__value { font-size:clamp(21px,2vw,30px); font-variant-numeric:tabular-nums; }
.fn-panel { padding:28px; margin:0 0 24px; min-width:0; }
.fn-panel h2 { font-size:20px; font-weight:550; margin:0 0 20px; }
.fn-panel h3 { font-size:15px; font-weight:600; margin:0 0 12px; }
.fn-section-head { display:flex; flex-wrap:wrap; align-items:center; justify-content:space-between; gap:16px; margin-bottom:20px; }
.fn-section-head :is(h2,h3) { margin:0; }
.fn-panel>summary { min-height:44px; padding:4px 0 16px; font-size:16px; font-weight:550; cursor:pointer; color:var(--accent-strong); }
.fn-list-head { max-width:580px; margin:24px 0; }
.fn-list { padding:0; }
.fn-list>.panel-row { min-height:94px; }
.financings .panel-row { gap:18px; white-space:normal; }
.financings .panel-row__main { min-width:0; }
.financings .panel-row__val { font-variant-numeric:tabular-nums; }
.fn-facts { margin:0; display:grid; grid-template-columns:1fr 1fr; column-gap:40px; }
.fn-facts>.panel-row { align-content:start; align-items:start; }
.fn-facts dt { flex-basis:100%; font-size:13px; }
.fn-facts dd { flex-basis:100%; margin:0; font-size:15px; line-height:1.6; }
.fn-form { margin:24px 0 0; max-width:1100px; }
.fn-form fieldset { border:0; padding:0; min-width:0; margin:0; }
.fn-form>fieldset>legend { font-size:17px; font-weight:550; padding:0; margin-bottom:20px; }
.fn-form .field { min-width:0; display:grid; align-content:start; gap:8px; font-size:14px; }
.fn-form :is(input,select,textarea) { width:100%; min-width:0; }
.fn-form textarea { min-height:90px; resize:vertical; }
.fn-form small { font-size:12px; line-height:1.5; color:var(--text-secondary); }
.fn-form-grid { display:grid; grid-template-columns:1fr 1fr; gap:20px; }
.fn-wide { grid-column:1/-1; }
.fn-form-actions,.fn-links { display:flex; align-items:center; flex-wrap:wrap; gap:12px; margin:24px 0 0; }
.fn-save-note { font-size:12px; line-height:1.5; color:var(--text-secondary); }
.fn-file { padding:16px 0; font-size:14px; line-height:1.6; overflow-wrap:anywhere; }
.fn-due-history { margin:12px 0; }
.fn-due-history summary { min-height:44px; padding:12px 0; cursor:pointer; color:var(--accent-strong); }
.fn-due-history p { line-height:1.6; }
.fn-hint { font-size:13px; line-height:1.7; color:var(--text-secondary); max-width:76ch; }
.fn-form .fn-subsection { padding-top:24px; border-top:1px solid var(--border); margin-top:8px; }
.fn-subsection>legend { font-size:15px; font-weight:550; margin:0; padding:0 12px 0 0; }
.fn-check { display:flex; align-items:center; gap:12px; min-height:44px; font-size:14px; }
.fn-check input { width:19px; height:19px; min-height:19px; flex:none; }
.fn-accounting>summary { display:list-item; min-height:44px; cursor:pointer; color:var(--accent-strong); padding:12px 0; }
.fn-accounting .fn-form-grid { padding:12px 0; }
.fn-form .fn-due-editor { display:grid; grid-template-columns:minmax(0,1fr) minmax(0,1fr) minmax(0,1fr) auto; gap:16px; align-items:end; padding:20px 0; border-bottom:1px solid var(--border); }
.fn-due-editor>legend { font-size:13px; color:var(--text-secondary); margin-top:20px; }
.fn-due-editor[disabled] { opacity:.8; }
.fn-form .fn-due-editor button { align-self:center; }
.fn-allocation { padding:20px 0; border-bottom:1px solid var(--border); margin-bottom:20px; }
.fn-allocation>.ghost-btn { margin-top:16px; }
.fn-notice { padding:20px 24px; margin:20px 0 24px; background:var(--surface-inset); border:1px solid var(--border); font-size:14px; line-height:1.6; }
.fn-notice :is(p,[role="list"]) { margin:8px 0 12px; max-width:84ch; }
.fn-notice h2 { font-size:16px; margin:0; }
.fn-notice--error { border-left:3px solid var(--bad); }
.fn-notice--error strong { color:var(--bad); }
.fn-notice--quiet { background:transparent; border:0; padding:0; color:var(--text-secondary); }
.fn-notice button { margin:4px 10px 0 0; }
.fn-history-item>.panel-row__main>p { line-height:1.6; }
.fn-history-item details { margin:20px 0; }
.fn-history-item summary { min-height:44px; padding:12px 0; cursor:pointer; color:var(--accent-strong); }
.fn-preview { padding:24px 0; border-block:1px solid var(--border); margin:24px 0; }
.fn-preview img { display:block; max-width:100%; max-height:75vh; object-fit:contain; margin:20px 0; }
.fn-period fieldset { display:flex; gap:20px; align-items:end; border:0; margin:0 0 24px; padding:0; flex-wrap:wrap; }
.fn-period legend { font-size:14px; margin-bottom:16px; }
.fn-period .field { display:grid; gap:8px; font-size:13px; }
.fn-bank-search { display:flex; gap:16px; align-items:end; flex-wrap:wrap; margin:24px 0; }
.fn-bank-search .field { display:grid; gap:8px; flex:1; min-width:160px; }
@media(max-width:1100px) {
  .fn-kpis { grid-template-columns:repeat(2,minmax(0,1fr)); }
  .fn-form .fn-due-editor { grid-template-columns:1fr 1fr; }
}
@media(max-width:650px) {
  .financings>.view-toggle { gap:4px; flex-wrap:nowrap; overflow-x:auto; }
  .financings>.view-toggle a { flex:none; }
  .fn-panel { padding:20px 16px; margin-bottom:20px; }
  .fn-facts,.fn-form-grid { grid-template-columns:minmax(0,1fr); gap:0; }
  .fn-form-grid { gap:20px; }
  .fn-kpis { gap:12px; margin:24px 0; }
  .fn-kpis .stat { padding:16px 12px; }
  .fn-kpis .stat__value { font-size:20px; }
  .fn-notice { padding:16px; }
  .fn-form-actions { align-items:stretch; }
  .fn-form-actions button { width:100%; }
  .fn-section-head { align-items:start; }
  .fn-list .panel-row { flex-wrap:wrap; padding:18px 16px; }
  .fn-list .panel-row__main { flex-basis:100%; }
  .fn-period .field { flex:1; min-width:130px; }
}
@media(prefers-reduced-motion:no-preference) {
  .financings .panel-row { transition:background-color 140ms ease; }
}

/* Connected workspaces: inherited colour/type world, one visible task. */
.sidebar__nav .nav-group {
  display:block; padding:18px 12px 7px; font-size:12px; font-weight:600;
  color:var(--text-secondary); line-height:1.3;
}
.sidebar__nav .nav-group:first-child { padding-top:4px; }
body.sidebar-collapsed .sidebar__nav .nav-group { display:none; }
.work-head { display:flex; justify-content:space-between; align-items:center; gap:20px; margin-bottom:20px; }
.work-head h1 { font-size:26px; line-height:1.2; margin:0; font-weight:650; letter-spacing:-.02em; }
.work-month { display:flex; align-items:flex-end; gap:8px; margin:0; }
.work-month label { display:flex; flex-direction:column; gap:5px; font-size:12px; color:var(--text-secondary); }
.work-month input { min-height:40px; padding:8px 10px; min-width:165px; background:var(--surface-inset); color:var(--text-primary); border:1px solid var(--line); border-radius:3px; font:inherit; font-size:14px; color-scheme:inherit; }
.work-month button { min-height:40px; }
.work-tabs { display:flex; gap:4px; border-bottom:1px solid var(--line); margin:0 0 24px; overflow-x:auto; scrollbar-width:thin; }
.work-tabs>[role="tab"] { flex:0 0 auto; padding:12px 16px; min-height:44px; border:0; border-bottom:2px solid transparent; background:transparent; color:var(--text-secondary); font:inherit; font-size:14px; font-weight:550; cursor:pointer; white-space:nowrap; transition:none; }
.work-tabs>[role="tab"]:hover { background:var(--bg-elevated); color:var(--text-primary); }
.work-tabs>[aria-selected="true"] { color:var(--accent); border-bottom-color:var(--accent); }
.work-tabs>[role="tab"]:focus-visible,.work-month input:focus-visible { outline:2px solid var(--accent); outline-offset:-2px; }
.work-panel[hidden] { display:none!important; }
.work-panel:focus { outline:none; }
.work-panel:focus-visible { outline:2px solid var(--accent); outline-offset:4px; }
.work-panel .panel { margin-bottom:20px; }
.work-links h2,.work-focus h2 { font-size:17px; line-height:1.4; margin:0; font-weight:600; }
.work-links .panel__header { padding:18px 20px; }
.finance-workspace .work-links .panel__header h2 { text-transform:none; letter-spacing:normal; color:var(--text-primary); font-size:17px; }
.work-link { min-height:64px; padding:14px 20px; }
.work-link .panel-row__main { min-width:0; }
.work-link .panel-row__sub { margin-top:4px; line-height:1.5; color:var(--text-secondary); }
.work-focus { display:flex; align-items:center; justify-content:space-between; gap:24px; padding:24px; }
.work-focus>div { min-width:0; }
.work-focus p { color:var(--text-secondary); line-height:1.6; max-width:65ch; margin:8px 0 0; }
.work-focus>.primary-btn { flex-shrink:0; }
.work-facts { display:flex; flex-wrap:wrap; gap:20px 40px; margin:20px 0 0; }
.work-facts dt { font-size:12px; color:var(--text-secondary); margin-bottom:6px; }
.work-facts dd { font-size:22px; margin:0; font-weight:600; font-variant-numeric:tabular-nums; }
.work-next { display:flex; flex-wrap:wrap; gap:10px 24px; padding:8px 0 16px; }
.work-next a { color:var(--accent); font-size:14px; min-height:44px; display:inline-flex; align-items:center; text-decoration:underline; text-underline-offset:4px; }
.bs-work-grid { display:grid; grid-template-columns:minmax(0,1.15fr) minmax(280px,1fr); gap:24px; align-items:start; }
.bs-work-grid>.bs-wartet { margin:0; }
.bs-work-grid>.bs-wege { min-width:0; }
.work-route-group { padding:0 0 24px; }
.work-route-group h2 { margin:0 0 8px; padding:0 0 12px; border-bottom:1px solid var(--line); font-size:15px; line-height:1.4; font-weight:600; }
.work-route-group .bs-weg { padding:12px 0; min-height:52px; }
.work-route-group .bs-weg__satz { line-height:1.5; }
.bs-work-grid:not(:has(.bs-wartet)) { grid-template-columns:1fr; }
.bs-work-grid:not(:has(.bs-wartet)) .bs-wege__liste { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:8px 32px; }
.finance-workspace .stat-strip,.payroll-workspace .stat-strip { margin-bottom:20px; }
@media(max-width:900px) {
  .bs-work-grid { grid-template-columns:1fr; gap:20px; }
  .bs-work-grid .bs-wege__liste { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:8px 24px; }
}
@media(max-width:600px) {
  .work-head { flex-wrap:wrap; gap:16px; margin-bottom:16px; }
  .work-head h1 { font-size:22px; }
  .work-month { flex:1 1 100%; }
  .work-month label { flex:1; min-width:0; }
  .work-month input { width:100%; min-width:0; min-height:44px; }
  .work-month button { min-height:44px; }
  .work-tabs { gap:0; margin-bottom:20px; }
  .work-tabs>[role="tab"] { padding:12px; }
  .work-focus { flex-direction:column; align-items:stretch; gap:16px; padding:18px; }
  .work-focus>.primary-btn { justify-content:center; }
  .work-links .panel__header { padding:16px; }
  .work-link { padding:14px 16px; }
  .work-facts { gap:18px; }
  .work-facts dd { font-size:20px; }
  .bs-work-grid .bs-wege__liste,.bs-work-grid:not(:has(.bs-wartet)) .bs-wege__liste { grid-template-columns:1fr; gap:0; }
  .payroll-workspace .stat-strip { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); }
  .payroll-workspace .stat { min-width:0; padding:14px; }
  .payroll-workspace .stat__value { font-size:20px; overflow-wrap:anywhere; }
}

/* The creditor's current task, with the same panels as finance and payroll. */
.payables-related { display:flex; flex-wrap:wrap; gap:8px; margin-bottom:16px; }
.payables-filter { display:flex; flex-wrap:wrap; gap:16px; align-items:end; margin:20px 0 12px; }
.payables-filter label { display:flex; flex-direction:column; gap:6px; font-size:13px; color:var(--text-secondary); }
.payables-filter label:first-child { flex:1 1 240px; }
.payables-filter input,.payables-filter select { box-sizing:border-box; min-height:44px; padding:10px 12px; border:1px solid var(--line); border-radius:8px; background:var(--bg-elevated); color:var(--text-primary); font:inherit; width:100%; }
.payables-filter [role="status"] { padding-bottom:12px; color:var(--text-secondary); font-size:13px; }
[data-payable-item][hidden],[data-payables-empty][hidden] { display:none!important; }
.payable-workspace .work-focus h2 { font-size:17px; margin:0; text-transform:none; letter-spacing:normal; }
@media(max-width:600px) { .payables-filter { gap:12px; } .payables-filter label { flex:1 1 100%; } .payables-filter [role="status"] { padding:0; } }

/* Recorded payroll: one readable month and its original obligations. */
.payroll-recorded h2,.payroll-obligations h2{font-size:1.2rem;margin:0}
.payroll-kicker{font-size:.72rem;text-transform:uppercase;letter-spacing:.08em;color:var(--text-secondary);margin:0 0 .35rem}
.payroll-person-area:empty{display:none}.payroll-person-area{padding:20px}
.payroll-slip{max-width:640px;margin:auto;border:1px solid var(--border);padding:24px;border-radius:12px;background:var(--surface)}
.payroll-slip h2{font-size:1.6rem}.payroll-slip h3{font-size:.94rem;margin:20px 0 8px}
.payroll-slip-facts{display:flex;flex-wrap:wrap;gap:8px 20px;padding:14px 0;border-block:1px solid var(--border);margin:16px 0;color:var(--text-secondary);font-size:.8rem}
.payroll-amount{display:flex;justify-content:space-between;gap:20px;padding:6px 0;font-variant-numeric:tabular-nums}.payroll-amount b{white-space:nowrap}
.payroll-total{border-top:1px solid var(--border);margin-top:6px;padding-top:12px}
.payroll-net{background:var(--accent-soft,rgba(134,194,235,.12));padding:16px;border-radius:8px;margin:20px 0;font-size:1.2rem;color:var(--text-primary)}
.payroll-employer summary{cursor:pointer;font-weight:600;font-size:.9rem}
.payroll-statement-note,.payroll-statement-reference{font-size:.76rem;color:var(--text-secondary);margin:16px 0 0;overflow-wrap:anywhere}
.payroll-obligations .panel-row{flex-wrap:wrap;gap:12px}.payroll-obligations .panel-row__meta{min-width:170px}
.payroll-print-frame{position:fixed;width:1px;height:1px;left:-10000px;top:0;border:0}
@media(max-width:600px){.payroll-person-area{padding:12px}.payroll-slip{padding:16px}.payroll-net{font-size:1rem;padding:12px}.payroll-obligations .panel-row__meta{text-align:left}.payroll-recorded .panel__header{flex-wrap:wrap;gap:12px}}

.payroll-obligations .panel-row__meta .panel-row__sub{display:block;margin-top:4px}

.payroll-recorded .panel__header h2,.payroll-obligations .panel__header h2{text-transform:none;letter-spacing:normal}
@media(max-width:600px){.payroll-recorded .sl-table td{background:transparent}}

/* Accounting close: one statement per task, with its own date/period. */
.closing-heading { margin:0 0 20px; }
.closing-heading h2 { margin:0 0 6px; font-size:22px; letter-spacing:-.025em; }
.closing-heading p { margin:0; color:var(--text-secondary); line-height:1.5; }
.closing-workspace:has(#closing-tab-mwst[aria-selected="true"]) [data-close-range],
.closing-workspace:has(#closing-tab-buchungsabschluss[aria-selected="true"]) [data-close-range] { display:none; }
.closing-workspace .panel__header { flex-wrap:wrap; gap:10px; }
.closing-workspace .panel-row__sub { white-space:normal; overflow-wrap:anywhere; }
.closing-workspace .panel-row__main { min-width:0; }
.closing-notice { padding:14px 16px; border-left:3px solid var(--accent); background:var(--bg-elevated); margin-bottom:18px; line-height:1.5; }
@media(max-width:600px) {
  .closing-workspace .panel-row { flex-wrap:wrap; gap:10px; }
  .closing-workspace .panel-row__meta { white-space:normal; }
  .closing-workspace [data-mwst-eingereicht],.closing-workspace [data-mwst-zurueck] { min-height:44px; }
}
@media print {
  .closing-workspace .work-tabs,.closing-workspace button,.closing-workspace form { display:none!important; }
  .closing-workspace .panel-row,.closing-heading { break-inside:avoid; }
  .closing-workspace details:not([open]) > *:not(summary) { display:block!important; }
}

@media print {
  html:has(.closing-workspace),body:has(.closing-workspace) { background:#fff!important; color:#111!important; color-scheme:light; }
  body:has(.closing-workspace) * { background:transparent!important; color:#111!important; box-shadow:none!important; text-shadow:none!important; }
  .closing-workspace .panel__header { break-after:avoid; }
  .closing-workspace .panel-row,.closing-workspace summary { border-color:#bbb!important; }
}

.closing-tax-total { display:flex; align-items:center; justify-content:space-between; gap:18px; padding:20px; margin:0 0 20px; border:1px solid var(--line); background:var(--surface); }
.closing-tax-total span { font-size:13px; color:var(--text-secondary); }
.closing-tax-total h3 { margin:6px 0 0; font-size:15px; }
.closing-tax-total strong { font-size:32px; letter-spacing:-.035em; white-space:nowrap; font-variant-numeric:tabular-nums; }
@media(max-width:600px) { .closing-tax-total { align-items:flex-start; flex-direction:column; gap:12px; } }
@media print {
  body:has(.closing-workspace)::before,body:has(.closing-workspace)::after { display:none!important; }
  .closing-workspace .lx-belege { break-before:page; }
  .closing-tax-total { break-inside:avoid; }
}

/* The saved supplier invoice and its current original payment balance. */
.payable-amount { display:flex; flex-direction:column; gap:3px; }
.payable-amount .panel-row__sub { font-weight:400; }
.invoice-receipt .panel__header { flex-wrap:wrap; gap:12px; }
.invoice-receipt .panel__header h2 { margin:4px 0 0; font-size:20px; text-transform:none; letter-spacing:normal; color:var(--text-primary); }
.invoice-receipt__body { padding:0 24px 20px; }
.invoice-receipt__body p { margin:8px 0 16px; overflow-wrap:anywhere; }
.invoice-receipt dl { display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:18px 24px; margin:18px 0; }
.invoice-receipt dt { color:var(--text-secondary); font-size:12.5px; }
.invoice-receipt dd { margin:5px 0 0; font-weight:600; font-variant-numeric:tabular-nums; overflow-wrap:anywhere; }
@media(max-width:600px) { .invoice-receipt__body { padding:0 16px 16px; } .invoice-receipt dl { grid-template-columns:repeat(2,minmax(0,1fr)); gap:18px 12px; } }

/* Existing contracts and original documents: one focused record at a time. */
.contract-work__row{gap:16px;flex-wrap:wrap;align-items:center}
.contract-work__row .panel-row__main{min-width:200px;flex:1}
.contract-work__amount,.contract-work__version>div,.contract-work__due>span{display:flex;flex-direction:column;gap:5px}
.contract-work__amount>span,.contract-work__version span,.contract-work__due span span{font-size:13px;color:var(--muted,#64717a)}
.contract-work__actions{display:flex;gap:8px;flex-basis:100%;flex-wrap:wrap;border-top:1px solid var(--border,#dfe4e8);padding-top:16px}
.contract-work__detail,.contract-work__pending{padding:22px;margin-top:18px}
.contract-work__detail h3,.contract-work__detail h4{margin:0 0 12px}
.contract-work__detail>p{color:var(--muted,#64717a);line-height:1.6}
.contract-work__version,.contract-work__due{display:flex;gap:20px;align-items:center;justify-content:space-between;padding:17px 0;border-bottom:1px solid var(--border,#dfe4e8);flex-wrap:wrap}
.contract-work__due{color:inherit;text-decoration:none}
.contract-work__due:hover{background:var(--hover,#f3f6f8)}
.contract-work__due>span:last-child{font-size:13px;text-decoration:underline}
.contract-work__entrance{margin-top:22px}
.document-work{padding:18px;margin:16px 0;border:1px solid var(--border,#dfe4e8);border-radius:12px;background:var(--surface,#fff);min-width:0}
.document-work__heading,.document-work__actions{display:flex;align-items:center;flex-wrap:wrap;gap:10px}
.document-work__heading{justify-content:space-between}
.document-work p{font-size:14px;line-height:1.55;overflow-wrap:anywhere}
.document-work__file{font-weight:600}
.document-work__choose{position:relative;overflow:hidden;cursor:pointer}
.document-work__choose input{position:absolute;inset:0;width:100%;height:100%;opacity:0;cursor:pointer}
.document-work__choose:focus-within{outline:2px solid var(--accent,#166d57);outline-offset:2px}
.document-work__error{color:var(--danger,#b3261e)}
.document-work__notice{padding:10px;background:var(--hover,#f5f3ea);border-radius:8px}
.document-work__choose.is-disabled{opacity:.55;cursor:wait}
@media(max-width:620px){
 .contract-work__detail,.contract-work__pending{padding:16px}
 .contract-work__row .panel-row__main{flex-basis:100%;min-width:0}
 .contract-work__version,.contract-work__due{gap:12px}
 .contract-work__actions>button{flex:1 1 160px}
 .document-work{padding:14px}
 .document-work__actions>*{max-width:100%;white-space:normal}
}

.contract-work__tabs{margin-top:20px}.contract-work__detail[hidden]{display:none}.contract-work__tabs+.contract-work__detail{margin-top:12px}

@media(max-width:620px){.contract-work__actions>.primary-btn{flex-basis:100%}.contract-work__actions>.ghost-btn{flex:1 1 130px}}

.contract-work__filters{display:grid;grid-template-columns:minmax(0,1fr) minmax(150px,230px);gap:14px;margin:18px 0}.contract-work__filters .field{min-width:0}.contract-work__empty{padding:20px}@media(max-width:620px){.contract-work__filters{grid-template-columns:1fr}.contract-work__filters input{min-width:0;width:100%}}

/* Bank work: one original entry and one decision at a time. */
.bank-work__intro{max-width:76ch;color:var(--text-secondary);line-height:1.6;margin:0 0 20px}
.bank-work__filters{display:flex;align-items:end;gap:12px;flex-wrap:wrap;margin:20px 0}
.bank-work__filters label,.bank-work__search,.bank-work__file{display:flex;flex-direction:column;gap:7px;font-size:13px;font-weight:600;min-width:0}
.bank-work__filters label:first-child{flex:1 1 220px}
.bank-work__filters input,.bank-work__filters select,.bank-work__search input{width:100%;min-width:0;box-sizing:border-box;min-height:42px;border:1px solid var(--border);border-radius:8px;background:var(--surface);color:var(--text);padding:9px 11px;font:inherit}
.bank-work__totals{display:flex;flex-wrap:wrap;gap:10px 24px;align-items:baseline;margin:12px 0 18px;font-size:13px}
.bank-work__layout{display:grid;grid-template-columns:minmax(240px,0.9fr) minmax(320px,1.1fr);gap:20px;align-items:start}
.bank-work__list{overflow:hidden;padding:0}
.bank-work__entry{appearance:none;display:flex;gap:14px;align-items:start;justify-content:space-between;width:100%;padding:17px 18px;text-align:left;border:0;border-bottom:1px solid var(--border);background:transparent;color:var(--text);font:inherit;min-width:0}
button.bank-work__entry{cursor:pointer;min-height:72px}
button.bank-work__entry:hover{background:var(--surface-hover,var(--surface-2))}
.bank-work__entry.is-selected{box-shadow:inset 3px 0 var(--accent);background:var(--surface-2)}
.bank-work__entry span{min-width:0;flex:1}.bank-work__entry b{font-size:14px;line-height:1.4}
.bank-work__entry small{display:block;font-size:12px;font-weight:400;line-height:1.5;color:var(--text-secondary);margin-top:5px;overflow-wrap:anywhere}
.bank-work__entry strong{font-size:13px;line-height:1.5;flex-shrink:0;font-variant-numeric:tabular-nums}
.bank-work__more{margin:14px 18px;max-width:calc(100% - 36px)}
.bank-work__detail{padding:22px;min-width:0}.bank-work__detail-head{display:flex;justify-content:space-between;align-items:center;gap:12px;margin-bottom:18px}
.bank-work__detail h2,.bank-work__import h2{font-size:22px;line-height:1.35;overflow-wrap:anywhere;margin:0 0 12px}
.bank-work__amount{font-size:28px;font-weight:700;line-height:1.3;margin:0 0 24px;font-variant-numeric:tabular-nums}
.bank-work__facts{display:grid;grid-template-columns:1fr 1fr;gap:16px;margin:0 0 24px}
.bank-work__facts div{min-width:0}.bank-work__facts dt{font-size:12px;color:var(--text-secondary);margin-bottom:5px}.bank-work__facts dd{font-size:14px;line-height:1.5;margin:0;overflow-wrap:anywhere}
.bank-work__facts div:nth-child(n+3){grid-column:1/-1}
.bank-work__actions{display:flex;flex-wrap:wrap;gap:10px;margin:20px 0}.bank-work__actions button{max-width:100%;white-space:normal;text-align:left}
.bank-work__links{display:flex;gap:16px;align-items:center;flex-wrap:wrap;margin-top:24px;font-size:13px}
.bank-work__hint{font-size:13px;line-height:1.65;color:var(--text-secondary);overflow-wrap:anywhere;margin:12px 0}
.bank-work__list>.bank-work__hint{padding:12px 18px}
.bank-work__pending{padding:16px;border:1px solid var(--border);border-radius:10px;background:var(--surface-2);margin:18px 0;overflow-wrap:anywhere;font-size:14px}
.bank-work__pending button{max-width:100%;white-space:normal}.bank-work__confirmed{padding:14px;border-left:3px solid var(--accent);font-size:14px;line-height:1.6}
.bank-work__detail h3{font-size:18px;line-height:1.4;margin:24px 0 12px}.bank-work__detail h4{font-size:14px;margin-top:24px}
.bank-work__payment{display:flex;flex-wrap:wrap;gap:12px;align-items:center;border-bottom:1px solid var(--border);padding:16px 0;font-size:13px;line-height:1.6}.bank-work__payment span{flex:1 1 170px;min-width:0;overflow-wrap:anywhere}.bank-work__payment small{display:block}.bank-work__payment button{max-width:100%;white-space:normal;text-align:left}
.bank-work__new-payment{margin-top:24px;border-top:1px solid var(--border);padding-top:18px}.bank-work .check-label{display:flex;gap:10px;align-items:start;font-size:13px;line-height:1.6;margin-bottom:14px}.bank-work .check-label input{margin-top:4px;flex:0 0 auto;width:18px;height:18px}
.bank-work__detail .panel-row{display:flex;flex-wrap:wrap;gap:10px;padding:18px 0}.bank-work__detail .panel-row__main{flex:1 1 220px;min-width:0}.bank-work__detail .panel-row button{white-space:normal;max-width:100%}
.bank-work__import{padding:24px;margin-top:20px;max-width:900px}.bank-work__file{margin:24px 0;max-width:100%}.bank-work__file input{max-width:100%;font:inherit;padding:12px 0}.bank-work__preview-rows{border:1px solid var(--border);border-radius:10px;overflow:hidden}
.bank-work [data-bank-controls]>.panel{padding:20px;margin:20px 0}
@media(max-width:850px){.bank-work__layout{grid-template-columns:1fr}.bank-work__layout.has-selection .bank-work__list{display:none}.bank-work__layout:not(.has-selection) .bank-work__detail{display:none}.bank-work__detail,.bank-work__import{padding:18px}.bank-work__filters label{flex:1 1 130px}.bank-work__filters label:first-child{flex-basis:100%}.bank-work__filters>button{flex:1 1 auto}.bank-work__amount{font-size:26px}.bank-work__entry{padding:15px 14px}}

@media(min-width:851px){.bank-work__list{max-height:min(72vh,840px);overflow-y:auto;overscroll-behavior:contain}}
.bank-work__search select{width:100%;min-width:0;min-height:44px;padding:10px;border:1px solid var(--border);border-radius:8px;background:var(--surface);color:var(--text);font:inherit}

/* Original payment files, one task and one document at a time. */
.payment-file-work { display:grid; gap:18px; }
.payment-file-work__rows { margin:18px 0; }
.payment-file-work__rows[open] { max-height:55vh; overflow:auto; }
.payment-file-work summary { padding:12px 0; cursor:pointer; font-weight:600; }
.payment-file-work__open { width:100%; text-align:left; color:inherit; border:0; background:transparent; cursor:pointer; }
.payment-file-work__open:focus-visible { outline:2px solid currentColor; outline-offset:-3px; }
.payment-file-work__missing { padding:16px 0; border-bottom:1px solid var(--border); }
.payment-file-work__amount { display:block; font-size:clamp(24px,4vw,36px); margin:16px 0; }
.payment-file-work [data-file-history]>.panel { max-height:65vh; overflow:auto; }
.payment-file-work .lx-pay-form { flex-wrap:wrap; gap:12px; }
@media(max-width:600px) { .payment-file-work .lx-pay-form>label { flex:1 1 100%; min-width:0; } .payment-file-work .panel-row { flex-wrap:wrap; } }

.payment-file-work button,.payment-file-work summary { min-height:44px; }

/* Customer invoice work: primary money facts first, original context remains available. */
.invoice-exposure,.invoice-origin-details{margin:12px 0}.invoice-exposure>summary,.invoice-origin-details>summary{min-height:44px;display:flex;align-items:center;gap:8px;cursor:pointer;color:var(--text-secondary);font-weight:600}.invoice-exposure>summary::before,.invoice-origin-details>summary::before{content:"+"}.invoice-exposure[open]>summary::before,.invoice-origin-details[open]>summary::before{content:"-"}.invoice-direct-origin{margin:12px 0;color:var(--text-secondary);font-size:13px}.invoice-origin-details .panel{margin-top:8px}

/* Keep the chosen invoice task focused; original alternatives remain one step back. */
.bank-work__detail.is-invoice-choice > .bank-work__actions,
.bank-work__detail.is-invoice-choice > .bank-work__links {display:none;}
.bank-work__detail.is-invoice-choice [data-bank-choice] {padding-top:18px;border-top:1px solid var(--border);}

.bank-work__detail.is-invoice-choice > [data-bank-invoice-evidence] {display:none;}
.invoice-bank-unlinked a {display:block;margin-top:10px;}

/* Sand mode follows the shared colour roles even in older fixed-colour shells. */
:root[data-theme="light"] .app-lock { background: rgba(238, 231, 219, .97); }
:root[data-theme="light"] :is(.gz-karte, .kk-karte) .gz-ic { color: var(--on-accent); }
:root[data-theme="light"] .gz-karte__kopf :is(.gz-chip--gut, .gz-chip--warn, .gz-chip--bad) { color: var(--on-accent); }
:root[data-theme="light"] :is(.ma-schritt.is-dran .ma-schritt__nr, .ma-schritt__tuer) { color: var(--on-accent); }
:root[data-theme="light"] :is(.be-frage__satz, .be-merker__satz) { color: var(--text); }
:root[data-theme="light"] .be-balken { background: var(--border); }
:root[data-theme="light"] .lx-demo { color: var(--accent-strong); }
:root[data-theme="light"] .lx-vorschau { color: var(--warn-strong); }
.profile-appearance { margin: 18px 0; padding: 14px 0; border-block: 1px solid var(--border); }
.profile-appearance .field { margin: 0; }
.profile-appearance select { width: 100%; min-height: 44px; }

:root[data-theme="light"] :is(.frage-kopf__wort, .kf-blattkopf > .kf-kopf) { color: var(--text-secondary); }
.gz-kz__fuss:has(> .gz-kz__spalte:only-child) { grid-template-columns: minmax(0, 1fr); }

:root[data-theme="light"] :is(input:not([type="checkbox"]):not([type="radio"]), select, textarea) { border-color: var(--control-border); }

/* Native operator groups share the current appearance and dialog controls. */
.operator-groups .modal { padding:0; max-height:calc(100dvh - 32px); }
.operator-groups .modal__header { display:flex; gap:16px; align-items:center; justify-content:space-between; padding:20px; border-bottom:1px solid var(--border); }
.operator-groups .modal__header h2 { margin:0; font-size:21px; }
.operator-groups .modal__body { display:block; overflow-y:auto; min-height:0; }
.operator-groups .field { display:flex; flex-direction:column; gap:7px; margin:12px 0; min-width:0; }
.operator-groups .field > span { font-size:13px; font-weight:600; }
.operator-groups .field :is(input,textarea,select) { padding:10px 12px; width:100%; min-width:0; min-height:44px; color:var(--text); background:var(--surface); border:1px solid var(--border); border-radius:8px; font:inherit; }
.operator-groups input[type=checkbox],.operator-groups input[type=radio] { width:18px; height:18px; vertical-align:middle; flex-shrink:0; accent-color:var(--accent); }
.operator-groups button { text-transform:none; letter-spacing:normal; font-size:13px; min-height:42px; max-width:100%; white-space:normal; }
.operator-groups :is(p,li) { font-size:14px; line-height:1.65; overflow-wrap:anywhere; }
.operator-groups h3 { margin:12px 0 4px; font-size:19px; overflow-wrap:anywhere; }
.operator-groups summary { padding:12px 0; cursor:pointer; font-size:14px; font-weight:600; }
.operator-groups__selection { padding:0 16px; background:var(--surface-2); border:1px solid var(--border); border-radius:8px; }
.operator-groups__selection ul { list-style:none; margin:0; padding:0 0 12px; max-height:240px; overflow:auto; }
.operator-groups__selection li { padding:8px 0; }
.operator-groups__selection span { display:block; color:var(--text-secondary); font-size:13px; }
.operator-groups__search { display:flex; gap:10px; align-items:center; margin-top:14px; }
.operator-groups__search .field { flex:1; }
.operator-groups__search button { margin-top:24px; }
.operator-groups__selection-mode { display:flex; flex-wrap:wrap; gap:10px 24px; margin:12px 0; font-size:13px; }
.operator-groups__selection-mode label { display:flex; align-items:center; gap:8px; min-height:36px; }
.operator-groups .table-wrap { overflow-x:auto; border:1px solid var(--border); border-radius:8px; }
.operator-groups table { width:100%; font-size:14px; border-collapse:collapse; }
.operator-groups th,.operator-groups td { text-align:left; padding:12px; border-bottom:1px solid var(--border); }
.operator-groups th { font-size:12px; color:var(--text-secondary); background:var(--surface-2); }
.operator-groups td:first-child { width:40px; }
.operator-groups td a { overflow-wrap:anywhere; }
.operator-groups [data-group-message]:not(:empty) { padding:12px 0; line-height:1.6; }
@media(max-width:600px) {
 .operator-groups .modal__header { padding:16px; }
 .operator-groups .modal__body { padding:16px!important; }
 .operator-groups .modal { max-height:calc(100dvh - 16px); }
 .operator-groups th,.operator-groups td { padding:10px 8px; }
 .operator-groups [data-group-actions] button { flex:1 1 150px; }
}

/* Bank evidence stays in the original operator account. */
.operator-bank { min-width:0; }
.operator-bank__header { display:flex; align-items:start; justify-content:space-between; gap:20px; flex-wrap:wrap; margin:20px 0; }
.operator-bank__header h2 { margin:0 0 8px; font-size:20px; }
.operator-bank__header > div:first-child { flex:1; min-width:min(100%,280px); }
.operator-bank__header p,.operator-bank__explanation { max-width:80ch; color:var(--text-secondary); line-height:1.6; }
.operator-bank__actions { display:flex; gap:8px; flex-wrap:wrap; }
.operator-bank__accounts { display:grid; grid-template-columns:repeat(auto-fit,minmax(min(100%,300px),1fr)); gap:12px; margin-bottom:20px; }
.operator-bank__accounts .panel { padding:16px; }
.operator-bank__accounts h3 { font-size:14px; margin:0 0 10px; }
.operator-bank__iban { font-family:var(--font-mono,monospace); overflow-wrap:anywhere; }
.operator-bank__filters { display:flex; flex-wrap:wrap; align-items:end; gap:12px; padding:16px; background:var(--surface-raised,var(--surface)); border:1px solid var(--hairline); border-radius:8px; }
.operator-bank__filters .field { flex:1; min-width:min(100%,160px); }
.operator-bank__filters .field:first-child { flex:2; min-width:min(100%,260px); }
.operator-bank__filters [hidden] { display:none; }
.operator-bank__filters input,.operator-bank__filters select { width:100%; min-width:0; }
.operator-bank__summary { display:flex; gap:8px 24px; flex-wrap:wrap; margin-top:24px; font-variant-numeric:tabular-nums; }
.operator-bank__summary > :first-child { width:100%; }
.operator-bank__rows { display:grid; gap:12px; }
.operator-bank__row { padding:18px; overflow-wrap:anywhere; }
.operator-bank__row-head { display:flex; justify-content:space-between; align-items:start; gap:16px; font-variant-numeric:tabular-nums; }
.operator-bank__row-head p { margin:4px 0 0; color:var(--text-secondary); }
.operator-bank__row details { margin:12px 0; }
.operator-bank__row dl { display:grid; grid-template-columns:minmax(60px,100px) 1fr; gap:8px; }
.operator-bank__row dd { margin:0; min-width:0; }
.operator-bank__evidence { color:var(--text-secondary); }
@media(max-width:600px) { .operator-bank__row-head { flex-wrap:wrap; } .operator-bank__filters { padding:12px; } .operator-bank__filters .field { flex-basis:100%; } }

.operator-bank__row { padding:0; }
.operator-bank__row > summary { cursor:pointer; padding:14px 16px; list-style:none; }
.operator-bank__row > summary::-webkit-details-marker { display:none; }
.operator-bank__row > summary > p { margin:6px 0; }
.operator-bank__row > summary > p:first-of-type { white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.operator-bank__row .operator-bank__evidence { font-size:12px; }
.operator-bank__expand { display:block; font-size:12px; color:var(--text-secondary); }
.operator-bank__expand::before { content:'＋ '; }
.operator-bank__row[open] .operator-bank__expand::before { content:'− '; }
.operator-bank__original { padding:0 16px 16px; border-top:1px solid var(--hairline); }

.work-tabs [data-account-task][aria-pressed="true"] { color:var(--accent); border-bottom:3px solid var(--accent); }

/* Originals remain inside the operator agreement workspace. */
.operator-documents { display:grid; gap:16px; padding-top:20px; }
.operator-case { display:grid; gap:20px; padding-top:20px; min-width:0; }
.operator-case__work { padding:20px; min-width:0; }
.operator-case__heading { display:flex; align-items:start; justify-content:space-between; gap:16px; margin-bottom:12px; flex-wrap:wrap; }
.operator-case__heading h2 { margin:0 0 8px; font-size:20px; }
.operator-case__heading p { margin:0; color:var(--text-secondary); max-width:64ch; line-height:1.6; }
.operator-case__actions,.operator-case__next { display:flex; align-items:center; flex-wrap:wrap; gap:8px; }
.operator-case__actions h4 { margin:0 auto 0 0; }
.operator-case__work .pd2-row__title { white-space:normal; overflow-wrap:anywhere; }
.operator-case__work .pd2-row__meta { line-height:1.5; }
.operator-case__sources { display:grid; gap:16px; min-width:0; }
.operator-case__section { min-width:0; padding:0; }
.operator-case__section > summary { padding:18px 20px; display:flex; align-items:center; justify-content:space-between; gap:16px; cursor:pointer; list-style:none; }
.operator-case__section > summary::-webkit-details-marker { display:none; }
.operator-case__section > summary > span { display:grid; gap:6px; min-width:0; }
.operator-case__section > summary strong { font-size:17px; }
.operator-case__section > summary span span { color:var(--text-secondary); font-size:13px; line-height:1.5; }
.operator-case__section > summary > svg { width:20px; height:20px; flex:none; }
.operator-case__section[open] > summary > svg { transform:rotate(180deg); }
.operator-case__content { padding:0 20px 20px; min-width:0; border-top:1px solid var(--hairline); }
.operator-case__next { padding:0 4px; }
.operator-case__next > span { color:var(--text-secondary); margin-right:8px; font-size:13px; }
@media(min-width:1100px) {
  .operator-case__sources:has([data-case-section="originale"][open]):has([data-case-section="bank"][open]) { grid-template-columns:repeat(2,minmax(0,1fr)); align-items:start; }
  .operator-case__sources:has([data-case-section="bank"][open]) .operator-documents__row { flex-direction:column; }
}
@media(max-width:600px) {
  .operator-case__work,.operator-case__section > summary { padding:16px; }
  .operator-case__content { padding:0 12px 16px; }
  .operator-case__work .pd2-row { align-items:start; }
  .operator-case__work .pd2-row > .gz-ic { display:none; }
  .operator-case__next { align-items:stretch; }
  .operator-case__next > span { width:100%; }
  .operator-case__next button { flex:1 1 100%; text-align:left; }
}
.operator-documents__header,.operator-documents__actions,.operator-documents__filter { display:flex; align-items:center; gap:12px; flex-wrap:wrap; }
.operator-documents__header { justify-content:space-between; }
.operator-documents h2,.operator-documents h3,.operator-documents p { margin:0; }
.operator-documents h2 { font-size:20px; }
.operator-documents h3 { font-size:15px; overflow-wrap:anywhere; }
.operator-documents__filter { align-items:end; }
.operator-documents__filter .field { flex:1; min-width:200px; }
.operator-documents__row { padding:18px; display:flex; align-items:start; justify-content:space-between; gap:16px; margin-bottom:12px; }
.operator-documents__row>div:first-child { min-width:0; display:grid; gap:8px; }
.operator-documents__row p,.operator-documents__context { color:var(--text-secondary); line-height:1.6; font-size:13px; }
.operator-documents__note { white-space:pre-wrap; overflow-wrap:anywhere; }
.operator-documents__notice,.operator-documents__selection { padding:18px; }
.operator-documents__selection { display:grid; gap:14px; }
.operator-documents__notice p { margin:8px 0; }
.operator-documents__selection textarea { width:100%; resize:vertical; }
.operator-documents [data-source-message][role=alert] { color:var(--danger); }
.operator-documents [aria-pressed=true],[data-agreement-work][aria-pressed=true] { border-bottom:3px solid var(--brand); color:var(--brand); }
@media(max-width:680px) {
 .operator-documents__row { display:grid; }
 .operator-documents__actions { align-items:stretch; }
 .operator-documents__actions button { flex:1; white-space:normal; }
 .operator-documents__header { align-items:start; }
}

.operator-documents [data-source-pending]:empty,.operator-documents [data-source-message]:empty,.operator-documents [data-source-selection]:empty,.operator-documents [data-source-more]:empty { display:none; }

/* Operator work starts with sections and open tasks; detailed metrics stay accessible. */
.pd2-metrics { margin: 0 0 16px; border: 1px solid var(--line); border-radius: 12px; background: var(--panel); }
.pd2-metrics > summary { cursor: pointer; padding: 14px 16px; font-weight: 600; }
.pd2-metrics > .pd2-kpis { margin: 0; padding: 0 16px 16px; }
.pd2-task-link { cursor: pointer; font: inherit; font-size: 12px; vertical-align: middle; }
.pd2-metrics > summary:focus-visible, .pd2-task-link:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
[data-ov="aufgaben"] { scroll-margin-top: 24px; }

/* Operator work uses the existing register, original groups and task list. */
.pl-work{border:1px solid var(--line);background:var(--surface);padding:16px;margin:18px 0;border-radius:var(--radius,8px)}
.pl-work__controls{display:flex;align-items:end;flex-wrap:wrap;gap:12px}
.pl-work__controls .field{flex:1;min-width:180px;margin:0}
.pl-work__controls select{width:100%;min-height:44px}
#pl-refresh-work{display:inline-flex;align-items:center;justify-content:center;gap:8px}
#pl-refresh-work .ico{width:18px;height:18px;flex:none}
.pl-work [data-work-summary]{margin:12px 0 0;font-weight:600}
.pl-work__notes,.operator-groups__notes{margin:12px 0}
.pl-work__notes p,.operator-groups__notes p{white-space:pre-wrap;overflow-wrap:anywhere}
.operator-groups__entry{display:flex;flex-wrap:wrap;gap:8px;margin:12px 0}
.pl-summary{margin-bottom:18px}
@media(max-width:600px){.pl-work__controls .field{min-width:0}.pl-work__controls .field:first-child{flex-basis:100%}.pl-work__controls button{min-height:44px}.operator-groups__entry>*{flex:1;text-align:center}#pl-refresh-work{width:44px;min-width:44px;padding:0}#pl-refresh-work span{display:none}}

.pl-table--work .pl-next-work{white-space:normal;min-width:260px}
.pl-next-work ul{padding:0;margin:0;list-style:none}
.pl-next-work li+li{margin-top:12px}
.pl-next-work strong,.pl-next-work span,.pl-work-owner{display:block;white-space:normal;overflow-wrap:anywhere}
.pl-next-work span,.pl-work-owner{font-size:12px;color:var(--text-secondary);margin-top:3px}
@media(max-width:720px){.table-wrap .team-table.pl-table--work tbody td.pl-next-work[data-label]{min-width:0;grid-column:1 / -1;display:block;text-align:left!important}.table-wrap .team-table.pl-table--work tbody td.pl-next-work[data-label]::before{display:block;width:auto;margin-bottom:8px;text-align:left}}

.pl-secondary-filters{margin:10px 0 14px}
.pl-secondary-filters>summary{font-weight:600;cursor:pointer;padding:10px 0;min-height:44px}
.pl-secondary-filters[open]>.pl-filterzeile{margin-top:6px}

/* Source-bound operator correction in the existing location record. */
.operator-location .modal { width: 100%; min-width: 0; max-width: 850px; }
.operator-location .modal__header { flex: 0 0 auto; padding: 18px 20px; }
.operator-location .modal__body { display: block; min-height: 0; flex: 1 1 auto; padding: 20px; }
.operator-location .field { display: flex; flex-direction: column; gap: 6px; margin: 16px 0; }
.operator-location .field select, .operator-location .field textarea { width: 100%; min-width: 0; }
.operator-location__identity p, .operator-location__history p, .operator-location [data-selected-source] { overflow-wrap: anywhere; }
.operator-location__effects { margin: 20px 0; padding: 16px; background: var(--bg-secondary); border: 1px solid var(--border); border-radius: 10px; }
.operator-location__effects li { margin: 8px 0; }
.operator-location__effects ul { padding-left: 20px; }
.operator-location__bank { padding: 12px 0; border-top: 1px solid var(--border); }
.operator-location__bank strong { overflow-wrap: anywhere; }
.operator-location__effects table { width: 100%; min-width: 330px; font-size: 13px; }
.operator-location__effects th, .operator-location__effects td { padding: 10px 8px; text-align: left; overflow-wrap: normal; }
.operator-location__effects summary, .operator-location__history summary { cursor: pointer; padding: 12px 0; font-weight: 600; }
.operator-location__confirm { display: flex; align-items: start; gap: 12px; margin: 20px 0; }
.operator-location__confirm input { flex: 0 0 20px; width: 20px; height: 20px; margin: 2px 0 0; }
.operator-location__history { margin-top: 24px; }
.operator-location__history article { padding: 14px 0; border-top: 1px solid var(--border); }
.operator-location__entry { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px; margin: 12px 0 20px; padding-bottom: 16px; border-bottom: 1px solid var(--border); }
@media (max-width: 600px) {
 .operator-location .modal__body { padding: 14px; }
 .operator-location .modal__header { align-items: start; gap: 10px; padding: 14px; }
 .operator-location .modal__header h2 { font-size: 20px; }
 .operator-location__effects { padding: 12px; }
 .operator-location__effects th, .operator-location__effects td { padding: 9px 5px; }
}

/* Original bank evidence shares the existing modal, with readable history. */
.operator-bank-source .operator-bank__original { padding: 0 0 16px; border-top: 0; }
.operator-bank-source dl { display: grid; grid-template-columns: minmax(100px, 1fr) minmax(0, 2fr); gap: 8px 16px; }
.operator-bank-source dt { color: var(--text-secondary); }
.operator-bank-source dd { margin: 0; overflow-wrap: anywhere; }
.operator-bank-source p { overflow-wrap: anywhere; }
.operator-bank-source [data-source-history] { margin-top: 24px; }
.operator-bank-source [data-source-history] > summary { padding: 14px 0; font-weight: 600; cursor: pointer; }
.operator-bank-source [data-source-history] article { padding: 14px 0; border-top: 1px solid var(--border); }
@media (max-width: 480px) { .operator-bank-source dl { grid-template-columns: 1fr; gap: 4px; } .operator-bank-source dd { margin-bottom: 10px; } }

/* A release notice leaves the active form, dialog and navigation intact. */
.release-update { position:fixed; z-index:90; right:16px; bottom:calc(var(--boden-h, 0px) + 16px); width:400px; max-width:calc(100vw - 32px); padding:18px; box-sizing:border-box; background:var(--surface-2); color:var(--text); border:1px solid var(--line-strong); box-shadow:0 8px 24px rgba(0,0,0,.2); }
.release-update[hidden] { display:none; }
.release-update > strong { display:block; color:var(--text-primary); }
.release-update > p { margin:8px 0 14px; line-height:1.5; }
.release-update > div { display:flex; flex-wrap:wrap; gap:8px; }
.release-update button { min-height:44px; }

/* Original bank balances share one compact presentation in intake and planning. */
.bank-balance { display:grid; gap:12px; padding:18px 0; border-bottom:1px solid var(--hairline); margin-bottom:16px; }
.bank-balance p { margin:0; color:var(--text-secondary); line-height:1.55; }
.bank-balance__total { display:flex; align-items:baseline; justify-content:space-between; gap:12px; flex-wrap:wrap; }
.bank-balance__total strong { font-size:24px; color:var(--text-primary); }
.bank-balance summary { cursor:pointer; padding:8px 0; }
.bank-balance__account { display:grid; gap:6px; padding:12px 0; border-bottom:1px solid var(--hairline); }
.bank-balance__account small { color:var(--text-secondary); overflow-wrap:anywhere; }
.bank-balance > a { justify-self:start; }

/* Private source work remains within the existing payroll workspace. */
.payroll-originals { min-width: 0; }
.payroll-originals__head { display:flex; align-items:flex-start; justify-content:space-between; gap:1.25rem; margin:1rem 0 1.5rem; }
.payroll-originals__head h2 { margin:0 0 .5rem; }
.payroll-originals__head p { max-width:65ch; margin:0; color:var(--text-secondary); }
.payroll-originals__filters,.payroll-originals__pair { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:1rem; align-items:end; }
.payroll-originals__filters { grid-template-columns: minmax(180px,2fr) minmax(140px,1fr) minmax(180px,1fr) auto auto; margin:1.25rem 0; }
.payroll-originals label { display:flex; flex-direction:column; gap:.4rem; font-weight:600; min-width:0; }
.payroll-originals input:not([type=hidden]),.payroll-originals select,.payroll-originals textarea { width:100%; min-width:0; box-sizing:border-box; padding:.7rem; color:var(--text); background:var(--surface-inset); border:1px solid var(--border); border-radius:var(--radius-sm,4px); font:inherit; color-scheme:inherit; }
.payroll-originals small { font-size:.8rem; font-weight:400; color:var(--text-secondary); }
.payroll-originals button { min-height:44px; }
.payroll-originals__layout { display:grid; grid-template-columns:minmax(240px,.8fr) minmax(0,1.4fr); gap:1.5rem; align-items:start; }
.payroll-originals__list { list-style:none; padding:0; margin:0; display:grid; gap:.6rem; max-height:min(58vh,650px); overflow-y:auto; overscroll-behavior:contain; padding:2px; }
.payroll-originals__list button { width:100%; text-align:left; padding:1rem; display:grid; gap:.4rem; background:var(--surface); color:var(--text); border:1px solid var(--border); border-radius:var(--radius-sm,4px); font:inherit; overflow-wrap:anywhere; }
.payroll-originals__list button[aria-pressed=true] { border-color:var(--accent); box-shadow:inset 3px 0 0 var(--accent); }
.payroll-originals__detail { min-width:0; }
.payroll-originals__detail h3 { overflow-wrap:anywhere; }
.payroll-originals__detail fieldset { border:0; margin:1.25rem 0; padding:0; display:grid; gap:1rem; min-width:0; }
.payroll-originals__detail legend { font-size:1.05rem; font-weight:700; padding:0; margin-bottom:1rem; }
.payroll-originals__note { white-space:pre-wrap; overflow-wrap:anywhere; }
.payroll-originals__upload { display:grid; gap:1rem; }
.payroll-originals__upload[hidden] { display:none; }
.payroll-originals details { margin:1rem 0; border-top:1px solid var(--border); padding-top:1rem; }
.payroll-originals summary { min-height:44px; cursor:pointer; font-weight:600; }
.payroll-originals__history article { border-top:1px solid var(--border); padding:.8rem 0; }
.payroll-originals__bank ul { list-style:none; padding:0; max-height:360px; overflow:auto; }
.payroll-originals__bank li button { width:100%; text-align:left; display:grid; gap:.35rem; padding:.8rem; margin:.3rem 0; background:var(--surface-inset); color:var(--text); border:1px solid var(--border); font:inherit; overflow-wrap:anywhere; }
.payroll-originals [role=status]:not(:empty) { padding:.8rem 0; }
@media(max-width:1100px) { .payroll-originals__filters { grid-template-columns:repeat(2,minmax(0,1fr)); } }
@media(max-width:720px) { .payroll-originals__head { flex-direction:column; } .payroll-originals__filters,.payroll-originals__layout,.payroll-originals__pair { grid-template-columns:minmax(0,1fr); } }

@media(max-width:720px) { .payroll-originals__list { max-height:320px; } .payroll-originals__detail { scroll-margin-top:1rem; } }

.payroll-originals__preview { margin:1rem 0; padding:1rem; border:1px solid var(--border); background:var(--surface-inset); min-width:0; }
.payroll-originals__preview[hidden] { display:none; }
.payroll-originals__preview header { display:flex; align-items:start; justify-content:space-between; gap:1rem; flex-wrap:wrap; margin-bottom:1rem; }
.payroll-originals__preview h4 { margin:0; overflow-wrap:anywhere; min-width:0; }
.payroll-originals__preview img { display:block; max-width:100%; max-height:65vh; object-fit:contain; margin:0 auto; }
.payroll-originals__preview > a { display:inline-flex; align-items:center; min-height:44px; margin-top:1rem; white-space:normal; }

.private-document-preview { min-width:0; }
.private-document-preview__tools { display:flex; align-items:center; gap:.5rem; flex-wrap:wrap; padding-bottom:.75rem; }
.private-document-preview__tools[hidden],.private-document-preview [data-document-text][hidden] { display:none; }
.private-document-preview__tools label { display:flex; align-items:center; gap:.5rem; margin:0; }
.private-document-preview__tools select { max-width:100%; min-width:0; }
.private-document-preview__paper { width:100%; max-height:65vh; overflow:auto; overscroll-behavior:contain; }
.private-document-preview__paper canvas { display:block; background:#fff; max-width:none; }
.private-document-preview [data-document-text] { margin-top:.75rem; }
.private-document-preview [data-document-text] p { white-space:pre-wrap; overflow-wrap:anywhere; font-size:.875rem; max-height:50vh; overflow:auto; }
@media(max-width:720px) { .payroll-originals__preview { padding:.625rem; } .private-document-preview__tools label { flex-wrap:wrap; } }

.operator-documents__preview { grid-column:1/-1; width:100%; min-width:0; padding:1rem; border-top:1px solid var(--border); }
.operator-documents__preview header { display:flex; align-items:start; justify-content:space-between; gap:1rem; flex-wrap:wrap; margin-bottom:1rem; }
.operator-documents__preview h4 { margin:0; overflow-wrap:anywhere; }
.operator-documents__preview > a { display:inline-flex; align-items:center; min-height:44px; margin-top:1rem; white-space:normal; }

.operator-documents__row:has(> .operator-documents__preview) { flex-wrap:wrap; }
.operator-documents__preview { flex-basis:100%; scroll-margin-top:1rem; contain:inline-size; }
.operator-documents__preview img { display:block; max-width:100%; max-height:65vh; object-fit:contain; margin:0 auto; }
@media(max-width:680px) { .operator-documents__row { grid-template-columns:minmax(0,1fr); } }

/* Dated operator terms in the existing agreement workspace. */
.operator-terms-review { margin-top: 18px; }
.operator-terms-review h2 { margin: 0; font-size: 20px; line-height: 1.35; }
.operator-terms-review__head { display: flex; justify-content: space-between; align-items: flex-start; gap: 16px; flex-wrap: wrap; }
.operator-terms-review__head p { margin: 6px 0 0; color: var(--text-secondary); }
.operator-terms-review__links { display: flex; flex-wrap: wrap; gap: 8px; }
.operator-terms-review__filters { display: flex; gap: 12px; align-items: end; flex-wrap: wrap; margin: 20px 0 10px; }
.operator-terms-review__filters .field { min-width: 170px; flex: 1 1 170px; max-width: 380px; }
.operator-terms-review__filters input, .operator-terms-review__filters select { width: 100%; min-height: 42px; min-width: 0; }
.operator-terms-review__boundary { color: var(--text-secondary); font-size: 13px; max-width: 85ch; line-height: 1.5; }
.operator-terms-review__status { margin: 18px 0 12px; color: var(--text-secondary); font-size: 13px; }
.operator-terms-review__location { padding: 18px 0; border-top: 1px solid var(--border); }
.operator-terms-review__location h3 { margin: 0 0 14px; display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; font-size: 16px; }
.operator-terms-review__location h3 span { font-size: 12px; font-weight: 400; color: var(--text-secondary); }
.operator-terms-review__sites { list-style:none; padding:0; margin:0 0 18px; display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:1px; background:var(--border); border:1px solid var(--border); border-radius:var(--radius,8px); overflow:hidden; }
.operator-terms-review__sites li { display:flex; align-items:center; justify-content:space-between; gap:12px; padding:8px 12px; background:var(--surface); min-width:0; }
.operator-terms-review__sites li:last-child:nth-child(odd) { grid-column:1/-1; }
.operator-terms-review__sites a { min-width:0; min-height:44px; align-content:center; font-size:14px; overflow-wrap:anywhere; }
.operator-terms-review__sites a span { display:block; margin-top:2px; color:var(--text-secondary); font-size:12px; }
.operator-terms-review__sites button { flex-shrink:0; min-height:44px; font-size:12px; }
.operator-terms-review__summary { display: grid; grid-template-columns: 1.3fr 1fr 1fr; gap: 18px; margin: 0 0 14px; }
.operator-terms-review dt { font-size: 12px; color: var(--text-secondary); margin: 0 0 5px; }
.operator-terms-review dd { margin: 0; line-height: 1.6; font-size: 14px; }
.operator-terms-review summary, .operator-terms-review__more > summary { cursor: pointer; min-height: 40px; align-content: center; font-size: 13px; }
.operator-terms-review__rules { margin: 6px 0 0; }
.operator-terms-review__rules > div { display: grid; grid-template-columns: minmax(140px, 1fr) 2fr; gap: 18px; padding: 9px 0; border-top: 1px solid var(--border); }
.operator-terms-review__rules dd span { display: block; font-size: 12px; color: var(--text-secondary); }
.operator-terms-review__more { margin-top: 12px; border-top: 1px solid var(--border); padding-top: 8px; }
.operator-terms-review__more > summary { font-size: 14px; font-weight: 600; }
@media(max-width: 640px) {
  .operator-terms-review__sites { grid-template-columns:minmax(0,1fr); }
  .operator-terms-review__links { width:100%; }
  .operator-terms-review__links > .primary-btn { flex-basis:100%; }
  .operator-terms-review__filters .field { max-width: none; min-width: 0; flex-basis: 100%; }
  .operator-terms-review__filters > button { flex: 1; }
  .operator-terms-review__summary { grid-template-columns: 1fr; gap: 14px; }
  .operator-terms-review__rules > div { grid-template-columns: 1fr; gap: 2px; }
  .operator-terms-review__location { padding: 18px 0; }
}

/* Personal context shares one identity across employment, pay and originals. */
.payroll-person-context{display:grid;grid-template-columns:minmax(220px,1fr) minmax(240px,2fr);align-items:center;gap:24px;padding:20px 24px;margin-block:16px 20px;border:1px solid var(--line);border-inline-start:3px solid var(--accent);border-radius:var(--radius-card);background:var(--surface)}
.payroll-person-context .field{margin:0}.payroll-person-context select{width:100%;min-height:44px}.payroll-person-context p{margin:4px 0;color:var(--muted)}
.payroll-person-context a{display:inline-block;margin-top:6px}.payroll-workspace .stat-strip[hidden]{display:none}
.payroll-amount-chart{margin:20px 0 24px;padding:20px;background:var(--surface);border:1px solid var(--line);border-radius:var(--radius-card)}
.payroll-amount-chart figcaption{font-weight:600;margin-bottom:16px}.payroll-amount-chart__row{display:grid;grid-template-columns:65px minmax(70px,1fr) auto;gap:14px;align-items:center;margin-block:12px}
.payroll-amount-chart__row strong{font-variant-numeric:tabular-nums}.payroll-amount-chart__track{height:10px;background:var(--line);border-radius:3px;overflow:hidden}.payroll-amount-chart__track i{display:block;height:100%;background:var(--accent)}
.payroll-amount-chart__row[data-payroll-amount="abzuege_rp"] i{background:var(--warning,#b47d30)}
.payroll-upload-receipts{margin-block:12px 20px;padding:16px;border:1px solid var(--line);border-inline-start:3px solid var(--accent);border-radius:var(--radius-card)}.payroll-upload-receipts button{margin:4px 8px 4px 0}
@media(max-width:650px){.payroll-person-context{grid-template-columns:1fr;gap:12px;padding:16px}.payroll-amount-chart{padding:14px}.payroll-amount-chart__row{grid-template-columns:50px minmax(35px,1fr) auto;gap:8px;font-size:13px}.payroll-workspace [data-payroll-return]{max-width:100%;white-space:normal}}
.payroll-workspace .work-month input,.payroll-person-context select{background:var(--surface-inset);color:var(--text);border:1px solid var(--control-border);border-radius:var(--radius-button);font:inherit;padding:10px 12px;color-scheme:inherit}
.payroll-workspace .ghost-btn,.payroll-person-name{background:var(--surface-2);color:var(--text);border:1px solid var(--line-strong);border-radius:var(--radius-button);min-height:44px;padding:10px 14px;font:inherit;text-transform:none;letter-spacing:normal;cursor:pointer}
.payroll-workspace .ghost-btn:hover,.payroll-person-name:hover{background:var(--surface-hover)}
.payroll-workspace .ghost-btn:disabled{opacity:.5;cursor:default}
.payroll-person-area:has(.payroll-slip--interactive){padding:0}
.payroll-slip--interactive{max-width:none;margin:12px 0 20px;padding:0;border:0;background:transparent}
.payroll-slip--interactive .payroll-amount-chart{max-width:760px;background:var(--surface-inset)}
.payroll-breakdowns{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:20px}
.payroll-breakdown{border-block:1px solid var(--line);padding:12px 0;align-self:start}
.payroll-breakdown summary{display:flex;gap:12px;align-items:center;cursor:pointer;min-height:44px}
.payroll-breakdown summary:before{content:'›';font-size:22px;color:var(--text-secondary)}
.payroll-breakdown[open] summary:before{transform:rotate(90deg)}
.payroll-breakdown summary strong{margin-inline-start:auto;white-space:nowrap;font-variant-numeric:tabular-nums}
.payroll-source{margin-block:16px}.payroll-source summary,.payroll-slip--interactive .payroll-employer summary{min-height:44px;cursor:pointer;align-content:center}
.payroll-slip--interactive .payroll-statement-reference{overflow-wrap:anywhere}
@media(max-width:650px){.payroll-breakdowns{grid-template-columns:1fr;gap:0}.payroll-slip--interactive{padding:0}.payroll-slip--interactive .payroll-slip-facts{gap:6px}.payroll-breakdown summary{font-size:.875rem}}

/* Existing original -> operator profile, within the file preview. */
.file-assignment{margin-block:1rem;padding:1rem;border:1px solid var(--border);border-radius:12px;background:var(--surface);}
.file-assignment header{display:flex;align-items:start;justify-content:space-between;gap:1rem;}
.file-assignment h3{margin:0;font-size:1rem;line-height:1.4;}
.file-assignment label{display:grid;gap:.4rem;margin-block:.8rem;font-size:.85rem;}
.file-assignment input,.file-assignment select,.file-assignment textarea{width:100%;min-width:0;box-sizing:border-box;}
.file-assignment [data-assignment-partners]{display:grid;gap:.4rem;max-height:230px;overflow:auto;margin-block:.65rem;}
.file-assignment__partner{display:grid;gap:.2rem;min-width:0;text-align:left;padding:.6rem .75rem;background:var(--surface);color:var(--text);border:1px solid var(--border);border-radius:8px;cursor:pointer;}
.file-assignment__partner small,.file-assignment__chosen span{color:var(--muted);}
.file-assignment__partner.is-selected{border-color:var(--accent);background:var(--accent-soft);}
.file-assignment__chosen{display:grid;gap:.35rem;padding:.75rem 0;border-bottom:1px solid var(--border);}
.file-assignment p{font-size:.85rem;line-height:1.5;}
.file-assignment [data-assignment-recovery]{display:flex;flex-wrap:wrap;gap:.6rem;}

/* Keep assignment and its original together; use the list space while classifying. */
.files-layout:has([data-files-assignment]:not([hidden])) { display:block; }
.files-layout:has([data-files-assignment]:not([hidden])) .files-index { display:none; }
.files-layout:has([data-files-assignment]:not([hidden])) .files-preview { width:100%; }
.files-reading:has([data-files-assignment]:not([hidden])) { display:grid; grid-template-columns:minmax(250px,.75fr) minmax(0,1.25fr); gap:24px; align-items:start; }
.files-reading [data-files-document] { min-width:0; }
@container (max-width: 700px) {
 .files-reading:has([data-files-assignment]:not([hidden])) { grid-template-columns:minmax(0,1fr); gap:16px; }
}

.file-assignment header button { flex:none; white-space:nowrap; }

/* ============================================================
   Patch-Integration — Namensraum sp- (Vertriebssteuerung); Quelle: docs/design/patch-sales-progress.css
   ============================================================ */
/* One sales workspace: bounded choices, source-linked facts and private plans. */
.sp-workspace { container-type:inline-size; max-width:1440px; margin:auto; color:var(--text-primary); }
.sp-workspace [hidden] { display:none!important; }
.sp-heading,.sp-section-head,.sp-plan-heading { display:flex; align-items:center; justify-content:space-between; flex-wrap:wrap; gap:18px; }
.sp-heading h1 { margin:0; font-size:clamp(25px,3vw,35px); letter-spacing:-.035em; }
.sp-heading p,.sp-workspace p { color:var(--text-secondary); font-size:14px; line-height:1.6; }
.sp-workspace h2 { margin:0 0 14px; font-size:19px; letter-spacing:-.02em; }
.sp-workspace h3 { margin:0 0 16px; font-size:17px; }
.sp-tabs { display:flex; gap:4px; border-bottom:1px solid var(--border); margin:22px 0; overflow-x:auto; }
.sp-tabs button { border:0; border-bottom:3px solid transparent; padding:14px 18px; background:transparent; color:var(--text-secondary); cursor:pointer; font:inherit; white-space:nowrap; }
.sp-tabs button[aria-pressed=true] { color:var(--text-primary); border-bottom-color:var(--accent); font-weight:600; }
.sp-workspace label { display:grid; gap:7px; font-size:12px; font-weight:550; color:var(--text-secondary); }
.sp-workspace :is(input,select) { color:var(--text-primary); background:var(--surface); border:1px solid var(--border); border-radius:7px; min-height:42px; padding:9px 11px; font:inherit; width:100%; min-width:0; }
.sp-workspace input[type=number] { font-variant-numeric:tabular-nums; }
.sp-workspace :is(button,input,select,summary,a):focus-visible { outline:2px solid var(--accent); outline-offset:3px; }
.sp-filter { display:flex; gap:12px; flex-wrap:wrap; align-items:end; margin:0 0 16px; }
.sp-filter>label { flex:1; min-width:140px; }
.sp-more-filter { flex-basis:100%; }
.sp-more-filter[open] { display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:16px; padding:18px; border:1px solid var(--border); border-radius:9px; }
.sp-more-filter :is(summary,p) { grid-column:1/-1; }
.sp-workspace summary { cursor:pointer; font-size:14px; font-weight:550; padding:11px 0; }
.sp-workspace [data-sp-status] { min-height:22px; font-size:12px; color:var(--text-secondary); margin:15px 0; }
.sp-metrics { display:grid; grid-template-columns:repeat(6,minmax(0,1fr)); gap:0; border:1px solid var(--border); border-radius:12px; overflow:hidden; background:var(--surface); }
.sp-metrics button { border:0; border-right:1px solid var(--border); background:transparent; padding:20px 16px; text-align:left; color:var(--text-primary); cursor:pointer; display:flex; flex-direction:column; gap:12px; }
.sp-metrics button:last-child { border-right:0; }
.sp-metrics button:hover,.sp-metrics button[aria-pressed=true] { background:var(--accent-soft); }
.sp-metrics span { font-size:12px; font-weight:550; line-height:1.5; min-height:36px; }
.sp-metrics strong { font-size:clamp(25px,3vw,36px); line-height:1.1; letter-spacing:-.025em; font-variant-numeric:tabular-nums; }
.sp-metrics small { font-size:11px; line-height:1.5; color:var(--text-secondary); }
.sp-insights { display:grid; grid-template-columns:minmax(0,.85fr) minmax(0,1.15fr); gap:30px; margin:26px 0; padding:24px 0; border-bottom:1px solid var(--border); }
.sp-contact { display:flex; gap:20px; align-items:center; margin:20px 0 12px; }
.sp-contact strong { font-size:36px; letter-spacing:-.025em; font-weight:600; }
.sp-contact span { font-size:12px; color:var(--text-secondary); }
.sp-workspace meter { display:block; width:100%; height:14px; accent-color:var(--accent); }
.sp-chart { display:block; width:100%; max-height:210px; overflow:visible; }
.sp-chart line { stroke:var(--border); }.sp-chart text { fill:var(--text-secondary); font-size:12px; }
.sp-chart-calls { fill:var(--accent); }.sp-chart-booked { fill:var(--warn); }.sp-chart-held { fill:var(--good); }
.sp-legend { display:flex; gap:18px; flex-wrap:wrap; font-size:11px; color:var(--text-secondary); }
.sp-legend span::before { content:''; display:inline-block; width:8px; height:8px; border-radius:2px; margin-right:6px; background:var(--accent); }.sp-legend span:nth-child(2)::before { background:var(--warn); }.sp-legend span:nth-child(3)::before { background:var(--good); }
.sp-section-head>button { border:0; background:transparent; color:var(--accent); font:inherit; cursor:pointer; }
.sp-section-head>select { width:auto; max-width:100%; }
.sp-quality { display:flex; gap:14px; flex-wrap:wrap; padding:14px 18px; border-left:3px solid var(--warn); background:var(--surface); margin:18px 0; }
.sp-quality button { border:0; background:transparent; color:var(--text-primary); text-decoration:underline; cursor:pointer; font:inherit; font-size:13px; padding:5px; }
.sp-people,.sp-definitions { border-bottom:1px solid var(--border); padding:12px 0; }
.sp-table-wrap { overflow:auto; }
.sp-table-wrap table { width:100%; border-collapse:collapse; text-align:left; font-size:13px; }
.sp-table-wrap :is(th,td) { padding:12px; border-bottom:1px solid var(--border); }.sp-table-wrap td { text-align:right; font-variant-numeric:tabular-nums; }
.sp-records { margin-top:28px; }.sp-record { border-top:1px solid var(--border); }.sp-record summary { display:flex; justify-content:space-between; align-items:center; gap:20px; padding:18px 6px; font-weight:400; }
.sp-record summary>span:first-child { display:grid; gap:7px; }.sp-record small { color:var(--text-secondary); font-size:12px; }.sp-record summary>span:last-child { font-size:12px; color:var(--text-secondary); text-align:right; }
.sp-record-body { padding:0 12px 20px; }.sp-record-body li { padding:7px 0; font-size:13px; line-height:1.5; }.sp-record-body time { color:var(--text-secondary); margin-right:8px; }
.sp-pagination { display:flex; align-items:center; justify-content:space-between; gap:14px; border-top:1px solid var(--border); padding-top:18px; font-size:12px; }
.sp-pagination button { padding:10px 15px; background:var(--surface); color:var(--text-primary); border:1px solid var(--border); border-radius:7px; cursor:pointer; }.sp-pagination button:disabled { opacity:.4; cursor:default; }
.sp-plan-grid { display:grid; grid-template-columns:minmax(0,1fr) minmax(290px,.8fr); gap:30px; align-items:start; margin-top:24px; }
.sp-plan-heading>div:first-child { max-width:70ch; }.sp-plan-heading [role=status] { max-width:40ch; }
.sp-plan-switches,.sp-plan-inputs { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:18px; }.sp-plan-switches { margin-bottom:22px; }
.sp-plan-input span { position:relative; }.sp-plan-input input { padding-right:58px; }.sp-plan-input small { position:absolute; right:12px; top:14px; pointer-events:none; font-weight:400; }
.sp-plan-inputs fieldset { grid-column:1/-1; display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:18px; border:1px solid var(--border); border-radius:9px; padding:18px; margin:0; }
.sp-plan-inputs legend { font-size:12px; padding:0 8px; }.sp-plan-result { position:sticky; top:18px; background:var(--surface); border:1px solid var(--border); border-radius:13px; padding:25px; }
.sp-plan-money { display:grid; gap:8px; padding:16px 0 22px; border-bottom:1px solid var(--border); }.sp-plan-money strong { font-size:clamp(28px,3vw,38px); font-weight:600; letter-spacing:-.03em; }.sp-plan-money span { font-size:13px; color:var(--text-secondary); }
.sp-plan-stages { list-style:none; padding:0; margin:12px 0; }.sp-plan-stages li { display:grid; grid-template-columns:minmax(0,1fr) auto; gap:5px 12px; padding:14px 0; border-bottom:1px solid var(--border); font-size:13px; }.sp-plan-stages strong { font-size:19px; font-variant-numeric:tabular-nums; }.sp-plan-stages small { grid-column:1/-1; text-align:right; color:var(--text-secondary); }
.sp-capacity { margin:22px 0; border-top:1px solid var(--border); padding-top:10px; }.sp-capacity-result { padding:15px; background:var(--accent-soft); border-radius:8px; }.sp-capacity-tight { border-left:3px solid var(--warn); }
.sp-target-rows { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:18px; margin:24px 0; }.sp-target-rows article { padding:18px; background:var(--surface); border:1px solid var(--border); border-radius:9px; display:grid; gap:14px; }.sp-target-rows article>div { display:flex; gap:15px; justify-content:space-between; font-size:13px; }.sp-target-rows article>strong { font-size:22px; }.sp-targets form { padding:24px 0; }.sp-targets form>button { margin-top:18px; }.sp-targets form>span { margin-left:14px; color:var(--text-secondary); font-size:12px; }
.sp-day-link { display:flex; justify-content:flex-end; margin:-8px 0 18px; font-size:13px; }
@container(max-width:1000px) { .sp-metrics { grid-template-columns:repeat(3,minmax(0,1fr)); }.sp-metrics button { border-bottom:1px solid var(--border); }.sp-metrics button:nth-child(3n) { border-right:0; }.sp-metrics button:nth-last-child(-n+3) { border-bottom:0; }.sp-plan-grid { grid-template-columns:minmax(0,1fr) minmax(230px,.85fr); gap:20px; } }
@container(max-width:700px) { .sp-insights,.sp-plan-grid { grid-template-columns:minmax(0,1fr); gap:20px; }.sp-plan-result { position:static; }.sp-plan-controls { display:contents; }.sp-plan-switches { order:0; }.sp-plan-result { order:1; }.sp-plan-inputs { order:2; }.sp-capacity { order:3; }.sp-plan-inputs,.sp-plan-switches { gap:14px; }.sp-heading h1 { font-size:27px; }.sp-record summary { align-items:flex-start; flex-direction:column; gap:8px; }.sp-record summary>span:last-child { text-align:left; }.sp-more-filter[open] { grid-template-columns:minmax(0,1fr); }.sp-target-rows { grid-template-columns:minmax(0,1fr); }.sp-tabs button { padding:12px; font-size:13px; }.sp-metrics button { padding:15px 12px; }.sp-metrics strong { font-size:28px; } }
@container(max-width:390px) { .sp-plan-inputs,.sp-plan-switches { grid-template-columns:minmax(0,1fr); }.sp-metrics { grid-template-columns:repeat(2,minmax(0,1fr)); }.sp-metrics button:nth-child(3n) { border-right:1px solid var(--border); }.sp-metrics button:nth-child(2n) { border-right:0; }.sp-metrics button:nth-last-child(-n+3) { border-bottom:1px solid var(--border); }.sp-metrics button:nth-last-child(-n+2) { border-bottom:0; } }
@container(max-width:700px) { .sp-plan-money { padding:8px 0 14px; }.sp-plan-result { padding:18px; }.sp-plan-stages { display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:12px; margin:12px 0 0; }.sp-plan-stages li { display:flex; flex-direction:column; border:0; padding:7px 0; }.sp-plan-stages li>span { font-size:11px; line-height:1.45; }.sp-plan-stages strong { font-size:24px; }.sp-plan-explanation { margin-top:14px; border-top:1px solid var(--border); }.sp-heading p { margin:7px 0; font-size:13px; }.sp-tabs { margin:15px 0; }.sp-plan-heading { gap:12px; }.sp-plan-heading h2 { margin-bottom:2px; }.sp-plan-heading>div:last-child { display:flex; align-items:center; gap:15px; width:100%; }.sp-plan-heading [role=status] { font-size:12px; }.sp-plan-heading .primary-btn { flex-shrink:0; } }
@container(max-width:390px) { .sp-plan-inputs { grid-template-columns:repeat(2,minmax(0,1fr)); }.sp-plan-input { font-size:11px; }.sp-plan-input input { font-size:15px; padding:10px 36px 10px 10px; }.sp-plan-input small { right:9px; }.sp-plan-inputs fieldset { padding:12px; gap:12px; } }
.sp-metrics { grid-template-columns:repeat(var(--sp-columns,6),minmax(0,1fr)); }
@container(max-width:1000px) { .sp-metrics { grid-template-columns:repeat(3,minmax(0,1fr)); } }
@container(max-width:390px) { .sp-metrics { grid-template-columns:repeat(2,minmax(0,1fr)); } }

/* Company planning stays inside the existing sales workspace. */
.bm-mode { display:flex; gap:4px; flex-wrap:wrap; margin:12px 0; }
.bm-mode button { font:inherit; font-size:13px; padding:10px 14px; border:1px solid var(--border); border-radius:7px; background:var(--surface); color:var(--text-secondary); cursor:pointer; }
.bm-mode button[aria-pressed=true] { color:var(--accent); background:var(--accent-soft); border-color:var(--accent); }
.bm-toolbar { display:grid; grid-template-columns:1fr .8fr 1.3fr auto; gap:14px; align-items:end; padding:18px 0; border-block:1px solid var(--border); margin:14px 0 24px; }
.bm-layout { display:grid; grid-template-columns:minmax(0,1.05fr) minmax(0,1fr); gap:32px; align-items:start; }
.bm-packages>p { margin-top:0; }
.bm-package { border-block-end:1px solid var(--border); }
.bm-package>summary { display:flex; gap:16px; align-items:center; justify-content:space-between; padding:18px 0; }
.bm-package>summary>span:first-child { display:grid; gap:6px; }
.bm-package>summary>span:last-child,.bm-package small { font-size:12px; color:var(--text-secondary); font-weight:400; }
.bm-package[open]>summary>span:last-child { color:var(--accent); }
.bm-fields { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:14px; padding-bottom:18px; }
.bm-fields>button,.bm-package-detail { grid-column:1/-1; }
.bm-package-detail .bm-fields { padding-bottom:0; }
.bm-assumptions { margin-top:24px; padding-top:8px; border-top:1px solid var(--border); }
.bm-assumptions fieldset { border:0; padding:12px 0; margin:0; }
.bm-assumptions legend { font-weight:650; font-size:14px; }
.bm-result { position:sticky; top:18px; min-width:0; padding:24px; border-radius:12px; background:var(--surface); border:1px solid var(--border); }
.bm-result-title { display:flex; flex-wrap:wrap; gap:8px; justify-content:space-between; align-items:baseline; }
.bm-result-title span { color:var(--text-secondary); font-size:12px; }
.bm-result h4 { font-size:14px; margin:22px 0 12px; }
.bm-totals,.bm-demand { margin:0; }
.bm-totals>div,.bm-demand>div { display:flex; align-items:baseline; justify-content:space-between; flex-wrap:wrap; gap:8px; padding:12px 0; border-bottom:1px solid var(--border); }
.bm-result dt { font-size:12px; color:var(--text-secondary); }
.bm-result dd { margin:0; font-size:18px; font-weight:600; font-variant-numeric:tabular-nums; }
.bm-demand dd { font-size:15px; }
.bm-chart { width:100%; display:block; }
.bm-chart text { font-size:12px; fill:var(--text-secondary); }
.bm-chart line { stroke:var(--border); }
.bm-monthly { fill:var(--accent); }.bm-once { fill:var(--warn); }
.bm-legend { display:flex; flex-wrap:wrap; gap:16px; font-size:12px; color:var(--text-secondary); }
.bm-legend span::before { content:''; display:inline-block; width:9px; height:9px; margin-right:6px; background:var(--accent); border-radius:2px; }.bm-legend span:last-child::before { background:var(--warn); }
.bm-activity .sp-plan-stages { display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:14px; }.bm-activity .sp-plan-stages li { display:flex; flex-direction:column; border:0; gap:8px; }
.bm-activity button { width:100%; }.bm-meaning { margin-top:18px; }
.bm-empty { padding:28px 0; }.bm-empty p { max-width:44ch; }
.bm-goal-proposal { padding:20px; background:var(--accent-soft); border:1px solid var(--border); border-radius:10px; margin:18px 0; }.bm-goal-proposal strong { font-size:20px; margin-right:18px; }.bm-goal-proposal p { max-width:65ch; }
@container(max-width:950px) { .bm-toolbar { grid-template-columns:1fr 1fr; }.bm-layout { gap:20px; }.bm-result { padding:18px; } }
@container(max-width:720px) { .bm-layout { grid-template-columns:minmax(0,1fr); }.bm-result { position:static; }.bm-fields { gap:12px; }.bm-toolbar { gap:12px; }.bm-toolbar button { font-size:13px; }.bm-result .bm-totals dd { font-size:18px; } }

.bm-mobile-result { display:none; }
@container(max-width:720px) { .bm-mobile-result:not(:empty) { position:sticky; top:0; z-index:2; display:flex; align-items:center; justify-content:space-between; gap:12px; padding:10px 0; background:var(--bg); border-block:1px solid var(--border); margin-bottom:20px; font-size:12px; }.bm-mobile-result span { display:grid; gap:4px; }.bm-mobile-result button { padding:10px; font-size:12px; }.bm-chart text { font-size:22px; } }

/* One case's original commercial records within the sales workspace. */
.sc-work { margin-top:20px; border-top:1px solid var(--border); padding-top:20px; }
.sc-work header { display:flex; align-items:start; justify-content:space-between; gap:20px; }
.sc-work h3,.sc-work h4 { margin:0 0 6px; }
.sc-work header p { margin:4px 0; font-size:12px; }
.sc-offer { margin-top:16px; border:1px solid var(--border); border-radius:10px; overflow:hidden; }
.sc-offer>header { padding:16px; background:var(--surface); }
.sc-offer>p { padding:0 16px; }
.sc-offer small,.sc-offer-value>span,.sc-money span { display:block; font-size:12px; color:var(--text-secondary); }
.sc-offer-value { text-align:right; flex-shrink:0; }
.sc-offer-value strong { display:block; margin-top:6px; font-size:20px; font-variant-numeric:tabular-nums; }
.sc-invoice { border-top:1px solid var(--border); }
.sc-work .sc-invoice>summary { display:flex; align-items:center; justify-content:space-between; gap:14px; padding:14px 16px; }
.sc-invoice-body { padding:4px 16px 16px; }
.sc-money { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:16px; margin-bottom:16px; }
.sc-money strong { display:block; font-size:18px; margin-top:6px; font-variant-numeric:tabular-nums; overflow-wrap:anywhere; }
.sc-note { border-left:3px solid var(--accent); padding:8px 12px; }
.sc-work .sc-events { list-style:none; padding:0; }
.sc-work .sc-events li { display:grid; grid-template-columns:auto 1fr auto; align-items:start; gap:12px; border-bottom:1px solid var(--border); padding:12px 0; }
.sc-events small { overflow-wrap:anywhere; }
.sc-basis { margin-top:16px; }
@container(max-width:560px) {
 .sc-work header { flex-wrap:wrap; gap:12px; }
 .sc-offer-value { text-align:left; }
 .sc-work .sc-invoice>summary { align-items:start; flex-wrap:wrap; }
 .sc-work .sc-events li { grid-template-columns:1fr auto; }
 .sc-events time { grid-column:1/-1; }
}

/* ============================================================
   Patch-Integration — Namensraum cs- (Kampagnen und Reaktionen); Quelle: docs/design/patch-campaign-signals.css
   ============================================================ */
/* Campaign work uses its existing customer, booking and measured source. */
.cs-workspace { container-type:inline-size; max-width:1440px; margin:auto; color:var(--text-primary); }
.cs-workspace [hidden] { display:none!important; }
.cs-heading,.cs-title,.cs-section-heading { display:flex; align-items:center; justify-content:space-between; flex-wrap:wrap; gap:12px; }
.cs-heading { margin-bottom:24px; }.cs-heading h1 { font-size:clamp(26px,3vw,35px); letter-spacing:-.035em; margin:0; }
.cs-workspace h2 { margin:6px 0; font-size:24px; letter-spacing:-.025em; }.cs-workspace h3 { margin:0; font-size:16px; }
.cs-workspace p { font-size:13px; color:var(--text-secondary); line-height:1.6; margin:8px 0; }
.cs-layout { display:grid; grid-template-columns:230px minmax(0,1fr); gap:28px; align-items:start; }
.cs-layout>* { min-width:0; }
.cs-code-list { position:sticky; top:18px; }.cs-code-list>label { margin-bottom:16px; }
.cs-workspace label { display:grid; gap:7px; font-size:12px; color:var(--text-secondary); font-weight:550; }
.cs-workspace :is(input,select) { width:100%; min-width:0; min-height:42px; color:var(--text-primary); background:var(--surface); border:1px solid var(--border); border-radius:7px; font:inherit; padding:9px 10px; }
.cs-workspace :is(button,input,select,summary,a):focus-visible { outline:2px solid var(--accent); outline-offset:3px; }
.cs-code-list [data-cs-codes] { display:grid; gap:7px; max-height:70vh; overflow-y:auto; padding:3px; margin:-3px; }
.cs-code-list button { display:grid; gap:7px; width:100%; padding:15px; text-align:left; color:var(--text-primary); background:transparent; border:1px solid transparent; border-radius:9px; font:inherit; cursor:pointer; }
.cs-code-list button:hover { background:var(--surface); }.cs-code-list button[aria-pressed=true] { background:var(--accent-soft); border-color:var(--accent); }
.cs-code-list button span { font-size:12px; font-weight:550; overflow-wrap:anywhere; }.cs-code-list button strong { font-size:17px; letter-spacing:-.015em; }.cs-code-list button small,.cs-code-list button em { font-size:11px; font-style:normal; color:var(--text-secondary); line-height:1.5; }
.cs-eyebrow { font-size:11px; color:var(--text-secondary); text-transform:uppercase; letter-spacing:.06em; }
.cs-link-line { display:flex; gap:10px 20px; flex-wrap:wrap; margin:15px 0 22px; font-size:12px; color:var(--text-secondary); }.cs-link-line a { color:var(--accent); }
.cs-period { display:flex; gap:12px; flex-wrap:wrap; align-items:end; }.cs-period label { flex:1; min-width:140px; }
.cs-workspace [data-cs-status] { color:var(--text-secondary); font-size:11px; min-height:18px; margin:16px 0 12px; line-height:1.5; }
.cs-metrics { display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); border:1px solid var(--border); border-radius:10px; background:var(--surface); overflow:hidden; }
.cs-metrics>div { display:grid; align-content:start; gap:12px; padding:20px; border-right:1px solid var(--border); }.cs-metrics>div:last-child { border:0; }.cs-metrics span { font-size:12px; color:var(--text-secondary); }.cs-metrics strong { font-size:38px; font-weight:600; letter-spacing:-.025em; line-height:1.2; font-variant-numeric:tabular-nums; }.cs-metrics small { font-size:11px; line-height:1.5; color:var(--text-secondary); }.cs-metrics .cs-last { font-size:21px; margin:10px 0; }
.cs-analysis { display:grid; grid-template-columns:minmax(0,1.2fr) minmax(220px,.8fr); gap:30px; margin:28px 0; }.cs-section-heading { margin-bottom:14px; }
.cs-chart { width:100%; display:block; max-height:230px; overflow:visible; }.cs-chart line { stroke:var(--border); }.cs-chart text { fill:var(--text-secondary); font-size:12px; }.cs-bar-scan { fill:var(--accent); }.cs-bar-action { fill:var(--warn); }
.cs-legend { display:flex; gap:14px; font-size:11px; color:var(--text-secondary); }.cs-legend span::before { content:''; width:8px; height:8px; display:inline-block; border-radius:2px; background:var(--accent); margin-right:5px; }.cs-legend span:last-child::before { background:var(--warn); }
.cs-actions { display:grid; gap:15px; margin-top:18px; }.cs-actions>div { display:grid; grid-template-columns:1fr auto; gap:6px 14px; font-size:12px; }.cs-actions meter { appearance:none; -webkit-appearance:none; min-height:6px; }
.cs-actions meter::-webkit-meter-bar { background:var(--border); border:0; border-radius:3px; height:6px; }
.cs-actions meter::-webkit-meter-optimum-value { background:var(--accent); border-radius:3px; }
.cs-actions meter::-moz-meter-bar { background:var(--accent); border-radius:3px; }
.cs-actions strong { font-variant-numeric:tabular-nums; }.cs-actions meter { grid-column:1/-1; width:100%; height:5px; accent-color:var(--accent); }
.cs-details { border-top:1px solid var(--border); border-bottom:1px solid var(--border); padding:4px 0; }.cs-workspace summary { cursor:pointer; font-size:13px; padding:13px 0; font-weight:550; }
.cs-table-wrap { overflow:auto; margin:18px 0; }.cs-table-wrap table { width:100%; text-align:left; border-collapse:collapse; font-size:12px; }.cs-table-wrap :is(th,td) { padding:10px; border-bottom:1px solid var(--border); }.cs-table-wrap td { text-align:right; font-variant-numeric:tabular-nums; }.cs-table-wrap caption { text-align:left; margin-bottom:12px; font-weight:550; }
.cs-report-foot { display:flex; gap:20px; align-items:start; justify-content:space-between; padding:18px 0; }.cs-report-foot p { max-width:75ch; margin:0; font-size:11px; }.cs-report-foot button { flex-shrink:0; }
.cs-editor { border:1px solid var(--border); background:var(--surface); border-radius:10px; padding:22px; margin-top:18px; }.cs-editor form { display:grid; grid-template-columns:1fr 1fr; gap:16px; margin-top:18px; }.cs-editor-actions { grid-column:1/-1; display:flex; align-items:center; flex-wrap:wrap; gap:16px; }.cs-editor [role=status] { font-size:12px; color:var(--text-secondary); max-width:60ch; }.cs-editor details { margin-top:15px; }.cs-editor li { font-size:12px; line-height:1.8; }.cs-workspace .cs-warning { border-left:3px solid var(--warn); padding:12px 16px; margin:14px 0; background:var(--surface); }
.cs-embedded { padding-bottom:24px; margin-bottom:25px; border-bottom:1px solid var(--border); }.cs-embedded .cs-heading h2 { font-size:22px; }
@container(max-width:1100px) { .cs-layout { grid-template-columns:190px minmax(0,1fr); gap:22px; }.cs-analysis { grid-template-columns:1fr; gap:22px; }.cs-actions { grid-template-columns:repeat(2,minmax(0,1fr)); gap:16px 24px; }.cs-metrics>div { padding:16px 12px; }.cs-metrics strong { font-size:32px; }.cs-metrics .cs-last { font-size:17px; }.cs-report-foot { flex-direction:column; gap:12px; } }
@container(max-width:720px) { .cs-layout { grid-template-columns:minmax(0,1fr); gap:22px; }.cs-code-list { position:static; }.cs-code-list [data-cs-codes] { grid-auto-flow:column; grid-auto-columns:minmax(200px,1fr); overflow-x:auto; max-height:none; }.cs-code-list button { min-width:200px; }.cs-code-list>label { margin-bottom:10px; }.cs-code-list button { padding:12px; }.cs-metrics .cs-last { font-size:16px; }.cs-period label { min-width:120px; }.cs-title h2 { font-size:22px; }.cs-editor { padding:16px; }.cs-editor form { grid-template-columns:1fr; } }
@container(max-width:390px) { .cs-metrics { grid-template-columns:1fr 1fr; }.cs-metrics>div:last-child { grid-column:1/-1; border-top:1px solid var(--border); grid-template-columns:1fr auto; gap:7px; }.cs-metrics .cs-last { margin:0; grid-row:1/3; grid-column:2; align-self:center; }.cs-metrics>div:nth-child(2) { border-right:0; }.cs-actions { grid-template-columns:1fr; } }
@media(prefers-reduced-motion:reduce) { .cs-workspace * { scroll-behavior:auto!important; } }
.cs-source-tabs { display:flex; gap:6px; border-bottom:1px solid var(--border); margin-bottom:26px; }
.cs-source-tabs button { padding:12px 18px; border:0; border-bottom:2px solid transparent; background:transparent; color:var(--text-secondary); font:inherit; font-size:14px; cursor:pointer; }
.cs-source-tabs button[aria-selected=true] { color:var(--accent); border-bottom-color:var(--accent); font-weight:650; }
.ws-workspace { container-type:inline-size; color:var(--text-primary); }
.ws-heading { margin-bottom:22px; }.ws-heading h2 { margin:6px 0; }
.ws-shortcuts { display:flex; gap:5px; }.ws-shortcuts button { padding-inline:11px; }
.ws-status { min-height:18px; margin:16px 0; color:var(--text-secondary); font-size:11px; }
.ws-summary { display:grid; grid-template-columns:minmax(0,1.2fr) minmax(0,1fr); gap:24px; padding:25px 0; border-block:1px solid var(--border); }
.ws-primary { display:grid; align-content:start; gap:7px; }.ws-primary>span { font-size:13px; color:var(--text-secondary); }
.ws-primary>strong { font-size:clamp(44px,5vw,66px); line-height:1.05; letter-spacing:-.04em; color:var(--accent); font-weight:600; font-variant-numeric:tabular-nums; }
.ws-primary small { font-size:11px; line-height:1.6; color:var(--text-secondary); overflow-wrap:anywhere; }
.ws-summary dl { margin:0; display:grid; align-content:center; gap:14px; }.ws-summary dl>div { display:flex; gap:16px; justify-content:space-between; font-size:13px; }.ws-summary dt { color:var(--text-secondary); }.ws-summary dd { margin:0; font-variant-numeric:tabular-nums; font-weight:550; }
.ws-analysis { display:grid; grid-template-columns:minmax(0,1.35fr) minmax(220px,1fr); gap:34px; margin:28px 0; }.ws-analysis>section { min-width:0; }
.ws-chart { width:100%; display:block; min-height:150px; }.ws-chart line { stroke:var(--border); }.ws-chart text { fill:var(--text-secondary); font-size:12px; }.ws-bar { fill:var(--accent); }.ws-missing { fill:var(--text-secondary); opacity:.35; }.ws-workspace .ws-chart-note { font-size:11px; }
.ws-pages>label { display:grid; gap:7px; font-size:12px; color:var(--text-secondary); }.ws-pages input { width:100%; box-sizing:border-box; }
.ws-pages [data-ws-pages] { max-height:365px; overflow-y:auto; margin-top:12px; padding-right:5px; }
.ws-page { width:100%; display:grid; grid-template-columns:minmax(0,1fr) auto; gap:7px 14px; padding:13px 10px; text-align:left; background:transparent; color:var(--text-primary); border:1px solid transparent; border-bottom-color:var(--border); font:inherit; font-size:12px; cursor:pointer; }
.ws-page span { overflow-wrap:anywhere; }.ws-page strong { font-variant-numeric:tabular-nums; }.ws-page[aria-pressed=true] { background:var(--accent-soft); border-color:var(--accent); border-radius:6px; }.ws-page:hover { background:var(--surface); }
.ws-page meter { grid-column:1/-1; width:100%; height:5px; appearance:none; -webkit-appearance:none; }.ws-page meter::-webkit-meter-bar { background:var(--border); border:0; height:5px; }.ws-page meter::-webkit-meter-optimum-value { background:var(--accent); }.ws-page meter::-moz-meter-bar { background:var(--accent); }
.ws-foot { display:flex; align-items:start; justify-content:space-between; gap:24px; border-top:1px solid var(--border); padding-top:12px; }.ws-foot details { max-width:75ch; }.ws-foot button { flex-shrink:0; margin-top:6px; }.ws-notice { border-left:3px solid var(--warn); padding:12px 16px; }
@container(max-width:760px) { .ws-analysis { grid-template-columns:minmax(0,1fr); gap:24px; }.ws-summary { gap:16px; }.ws-summary dl>div { font-size:12px; gap:10px; }.ws-shortcuts { width:100%; }.ws-foot { flex-direction:column; gap:10px; } }
@container(max-width:430px) { .ws-summary { grid-template-columns:1fr; }.ws-summary dl { gap:10px; }.ws-primary>strong { font-size:48px; }.ws-summary { padding:20px 0; } }


/* ============================================================
   Patch-Integration — Namensraum rp- (Personengebundene Rechte); Quelle: docs/design/patch-permissions.css
   ============================================================ */
/* Personal permissions: one person, grouped work areas, details on demand. */
.rp-toolbar { display:flex; align-items:end; gap:12px; flex-wrap:wrap; margin-bottom:20px; }
.rp-toolbar .field { flex:1 1 300px; max-width:560px; min-width:0; }
.rp-toolbar select { width:100%; min-width:0; }
.rp-person-summary { display:flex; flex-direction:column; gap:5px; margin:0 0 18px; }
.rp-person-summary strong { font-size:20px; letter-spacing:-.02em; }
.rp-person-summary span { color:var(--text-secondary); font-size:13px; }
.rp-search { max-width:560px; margin:0 0 20px; }
.rp-group { border-bottom:1px solid var(--border); }
.rp-group > summary { display:flex; align-items:center; gap:12px; padding:18px 4px; cursor:pointer; list-style:none; }
.rp-group > summary::-webkit-details-marker { display:none; }
.rp-group > summary::before { content:'›'; font-size:21px; width:14px; flex-shrink:0; line-height:1; transition:transform .16s; }
.rp-group[open] > summary::before { transform:rotate(90deg); }
.rp-group > summary strong { flex:1; font-size:15px; }
.rp-group > summary > span { font-size:12px; color:var(--text-secondary); white-space:nowrap; }
.rp-group > div { padding:0 4px 14px 26px; }
.rp-permission { gap:14px; align-items:center; flex-wrap:wrap; }
.rp-permission > .panel-row__main { flex:1 1 280px; }
.rp-permission__actions { display:flex; gap:4px; flex-wrap:wrap; }
.rp-permission__actions button { padding:7px 10px; font-size:12px; text-transform:none; letter-spacing:normal; }
.rp-toolbar > a { text-transform:none; letter-spacing:normal; }
.rp-history { margin-top:24px; }
.rp-history > summary { cursor:pointer; color:var(--text-secondary); font-size:13px; padding:10px 0; }
.rp-shared > summary { cursor:pointer; font-size:14px; font-weight:600; }
.rp-shared > section { border:0; padding-inline:0; box-shadow:none; }
@media (max-width:600px) {
  .rp-toolbar { align-items:stretch; }
  .rp-toolbar .field { flex-basis:100%; }
  .rp-toolbar > a { align-self:flex-start; }
  .rp-group > div { padding-left:4px; }
  .rp-permission__actions { width:100%; }
  .rp-permission__actions button { flex:1; min-height:40px; }
  .rp-group > summary { padding-block:16px; }
}
@media (prefers-reduced-motion:reduce) { .rp-group > summary::before { transition:none; } }
/* ============================================================
   Patch-Integration — Namensraum ef- (Eventfrog-Arbeitsplatz); Quelle: docs/design/patch-eventfrog-workspace.css
   ============================================================ */
/* Eventfrog is one operating channel, using the shared booking/material records. */
.ef-workspace { max-width:1480px; margin-inline:auto; }
.ef-channel { display:flex; flex-wrap:wrap; gap:12px 24px; align-items:center; padding:16px 0; border-block:1px solid var(--border); color:var(--text-secondary); font-size:14px; }
.ef-channel a { margin-left:auto; color:var(--accent); font-weight:600; }
.ef-channel-status { display:inline-flex; align-items:center; gap:8px; color:var(--text-primary); font-weight:600; }
.ef-channel-status i { width:8px; height:8px; border-radius:50%; background:var(--text-tertiary); }
.ef-channel-status i.is-open { background:var(--good); }
.ef-filters { display:flex; flex-wrap:wrap; gap:6px; margin:24px 0 18px; }
.ef-filters button { display:flex; align-items:center; gap:12px; min-height:44px; padding:10px 14px; border:1px solid var(--border); border-radius:8px; background:var(--surface); color:var(--text-secondary); }
.ef-filters button[aria-pressed=true] { border-color:var(--accent); color:var(--accent); background:var(--accent-soft); }
.ef-filters b { font-variant-numeric:tabular-nums; }
.ef-toolbar { display:flex; align-items:flex-end; gap:12px; margin-bottom:20px; }
.ef-toolbar label { display:grid; gap:6px; font-size:13px; font-weight:600; width:min(100%,480px); }
.ef-toolbar input,.ef-notice select { min-width:0; min-height:44px; width:100%; padding:10px 12px; border:1px solid var(--control-border,var(--line-strong)); border-radius:7px; color:var(--text-primary); background:var(--surface-inset); }
.ef-work-layout { display:grid; grid-template-columns:minmax(260px,.85fr) minmax(0,1.65fr); gap:24px; align-items:start; }
.ef-bookings,.ef-detail { min-width:0; }
.ef-list { border:1px solid var(--border); border-radius:10px; overflow:hidden; }
.ef-booking { width:100%; display:grid; gap:5px; padding:16px; border:0; border-bottom:1px solid var(--border); border-left:3px solid transparent; background:var(--surface); color:var(--text); text-align:left; min-height:86px; }
.ef-booking:last-child { border-bottom:0; }
.ef-booking[aria-pressed=true] { border-left-color:var(--accent); background:var(--accent-soft); }
.ef-booking:hover { background:var(--surface-hover); }
.ef-booking strong { font-size:15px; color:var(--text-primary); overflow-wrap:anywhere; }
.ef-booking span { font-size:14px; overflow-wrap:anywhere; }
.ef-booking small { font-size:12px; color:var(--text-secondary); }
.ef-pages { display:flex; flex-wrap:wrap; align-items:center; gap:8px; margin-top:12px; font-size:13px; color:var(--text-secondary); }
.ef-pages span { margin-right:auto; }
.ef-detail { border:1px solid var(--border); border-radius:12px; padding:24px; background:var(--surface); }
.ef-detail-head { display:flex; flex-wrap:wrap; justify-content:space-between; align-items:start; gap:12px; }
.ef-detail h2 { font-size:24px; margin:6px 0; overflow-wrap:anywhere; }
.ef-detail h3 { font-size:16px; margin:0 0 12px; }
.ef-detail p { color:var(--text-secondary); font-size:14px; line-height:1.5; overflow-wrap:anywhere; }
.ef-eyebrow { font-size:12px; color:var(--text-secondary); }
.ef-booking-facts { display:flex; flex-wrap:wrap; gap:8px 20px; font-size:14px; color:var(--text-secondary); margin:16px 0 24px; }
.ef-flow { display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:8px; padding:0; margin:0 0 24px; list-style:none; }
.ef-flow li { padding-top:12px; border-top:3px solid var(--border); font-size:14px; font-weight:600; }
.ef-flow li.is-done { border-color:var(--good); }
.ef-flow li.is-attention { border-color:var(--warn); }
.ef-flow span { display:block; color:var(--text-secondary); font-size:12px; font-weight:400; margin-top:5px; }
.ef-notice { padding:18px; border:1px solid var(--border); border-radius:9px; background:var(--surface-1); margin-bottom:24px; }
.ef-notice label { display:grid; gap:8px; font-size:13px; margin:16px 0 10px; }
.ef-notice select { max-width:100%; }
.ef-material { padding-top:8px; }
.ef-detail-links { display:flex; flex-wrap:wrap; gap:16px; margin-top:24px; padding-top:16px; border-top:1px solid var(--border); }
.ef-detail-links a { min-height:44px; display:inline-flex; align-items:center; color:var(--accent); font-size:14px; }
.ef-empty { padding:24px 0; color:var(--text-secondary); line-height:1.6; font-size:15px; }
.ef-workspace [data-error]:not(:empty) { padding:14px; margin-bottom:18px; background:var(--bad-soft); color:var(--bad-strong); border:1px solid var(--border); border-radius:8px; }
.ef-workspace :is(.primary-btn,.ghost-btn) { min-height:44px; text-transform:none; letter-spacing:0; white-space:normal; }
.ef-workspace :is(a,button,input,select):focus-visible { outline:2px solid var(--accent); outline-offset:3px; }
@media(max-width:850px) {
  .ef-work-layout { grid-template-columns:minmax(0,1fr); }
  .ef-list { max-height:320px; overflow:auto; }
  .ef-detail { padding:18px; }
  .ef-channel a { margin-left:0; }
  .ef-filters { gap:6px; margin-top:18px; }
  .ef-filters button { font-size:13px; padding:8px 10px; flex:1 0 auto; }
  .ef-flow { gap:10px; }
  .ef-flow li { font-size:13px; }
}
@media(prefers-reduced-motion:reduce) { .ef-workspace * { transition:none; } }
/* ============================================================
   Patch-Integration — Namensraum sig-work- (Standortbezogene Ausspielung); Quelle: docs/design/patch-signage-workspace.css
   ============================================================ */
.sig-work-search { display:flex; align-items:end; gap:18px; padding:16px 0; flex-wrap:wrap; }
.sig-work-search label { display:grid; gap:8px; flex:1 1 320px; max-width:560px; font-size:13px; font-weight:600; }
.sig-work-search input { width:100%; min-height:44px; }
.sig-work-search p { color:var(--text-secondary); font-size:13px; margin:0 0 10px; }
.sig-work-grid { display:grid; grid-template-columns:minmax(240px,.8fr) minmax(0,1.65fr); border-top:1px solid var(--border); }
.sig-work-list { min-width:0; max-height:calc(100dvh - 230px); overflow-y:auto; overscroll-behavior:contain; border-right:1px solid var(--border); }
.sig-work-list > button { display:grid; gap:6px; width:100%; min-height:82px; text-align:left; padding:16px 18px; color:var(--text-primary); background:transparent; border:0; border-bottom:1px solid var(--border); border-left:3px solid transparent; cursor:pointer; font:inherit; }
.sig-work-list > button:hover { background:var(--surface-hover); }
.sig-work-list > button[aria-pressed="true"] { background:var(--accent-soft); border-left-color:var(--accent); }
.sig-work-list strong { font-size:14px; line-height:1.4; overflow-wrap:anywhere; }
.sig-work-list :is(span,small) { font-size:12px; color:var(--text-secondary); line-height:1.4; overflow-wrap:anywhere; }
.sig-work-detail { padding:20px 24px; min-width:0; background:var(--surface); scroll-margin-top:20px; }
.sig-work-detail .sig-loc { margin:0!important; padding:0!important; border-top:0!important; }
.sig-work-detail .sig-loc > div:first-child { display:grid!important; gap:8px!important; }
.sig-work-detail .sig-loc > div:first-child strong { font-size:20px!important; }
.sig-work-owner { margin-bottom:10px; font-size:13px; color:var(--text-secondary); }
.sig-work-detail .sig-loop { margin:18px 0; }
.sig-work-detail .sig-screen { padding:14px 0!important; }
.sig-work-pages { display:flex; justify-content:space-between; align-items:center; gap:8px; padding:14px 10px; position:sticky; bottom:0; background:var(--surface); border-top:1px solid var(--border); }
.sig-work-pages button { min-height:44px; padding:8px 12px; border:1px solid var(--border); color:var(--text-primary); background:var(--surface); border-radius:6px; cursor:pointer; }
.sig-work-pages button:disabled { opacity:.4; cursor:default; }
.sig-work-list button:focus-visible { outline:2px solid var(--accent); outline-offset:-3px; }
#signage-work-panel-netz .stat-strip { margin-top:20px; grid-template-columns:repeat(3,minmax(0,1fr)); }
@media(min-width:1500px) { #signage-work-panel-netz .stat-strip { grid-template-columns:repeat(6,minmax(0,1fr)); } }
@media(max-width:760px) {
 .sig-work-grid { grid-template-columns:minmax(0,1fr); }
 .sig-work-list { max-height:320px; border-right:0; border-bottom:1px solid var(--border); }
 .sig-work-detail { padding:20px 14px; }
 .sig-work-search { gap:8px; }
 #signage-work-panel-netz .stat-strip { grid-template-columns:repeat(2,minmax(0,1fr)); }
}
.sig-capacity{display:grid;gap:10px;padding:14px 0;color:var(--text-secondary);font-size:.875rem}
.sig-capacity strong{color:var(--text-primary)}
.sig-capacity__head,.sig-capacity__legend{display:flex;align-items:baseline;justify-content:space-between;gap:12px;flex-wrap:wrap}
.sig-capacity__head>span,.sig-capacity small{font-size:.75rem;color:var(--text-tertiary)}
.sig-capacity__track{display:flex;height:10px;border-radius:5px;overflow:hidden;background:rgba(var(--tint-rgb),.12)}
.sig-capacity__track>i{display:block;height:100%}
.sig-capacity__booked{background:var(--accent)}
.sig-capacity__blocked{background:var(--text-tertiary);background-image:repeating-linear-gradient(135deg,transparent,transparent 3px,rgba(var(--tint-rgb),.25) 3px,rgba(var(--tint-rgb),.25) 5px)}
.sig-capacity__legend{justify-content:flex-start;gap:20px;font-variant-numeric:tabular-nums}
/* ============================================================
   Patch-Integration — Namensraum finance- (Finanzarbeitsplatz); Quelle: docs/design/patch-finance-workspace.css
   ============================================================ */
.finance-workspace { container:finance-work / inline-size; }
.finance-shortcuts { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:8px; margin:16px 0 24px; }
.finance-shortcuts .work-link { display:flex; align-items:center; min-height:72px; padding:12px 16px; border:1px solid var(--border); border-radius:8px; background:var(--surface); text-decoration:none; }
.finance-shortcuts .work-link:hover { border-color:var(--accent); background:var(--accent-soft); }
.finance-shortcuts .panel-row__main { min-width:0; }
.finance-shortcuts .panel-row__main b { font-size:14px; }
.finance-shortcuts .panel-row__sub { font-size:12px; line-height:1.4; }
.finance-forecast { margin:24px 0 20px; padding:20px 0 0; border-top:1px solid var(--border); }
.finance-forecast figcaption { margin:0 0 16px; font-size:13px; font-weight:600; color:var(--text-secondary); }
.finance-forecast__plot { position:relative; padding-left:86px; height:var(--forecast-height,180px); }
.finance-forecast__axis { position:absolute; inset:0 auto 0 0; width:74px; font-size:12px; font-variant-numeric:tabular-nums; color:var(--text-secondary); }
.finance-forecast__axis span { position:absolute; right:0; transform:translateY(-50%); white-space:nowrap; }
.finance-forecast svg { display:block; width:100%; height:var(--forecast-height,180px); overflow:visible; }
.finance-forecast__dates { display:flex; justify-content:space-between; padding-left:86px; margin-top:2px; font-size:11px; color:var(--text-secondary); }
.finance-forecast__zero { stroke:var(--border); stroke-dasharray:4 4; }
.finance-forecast__line { fill:none; stroke:var(--accent); stroke-width:2.5; vector-effect:non-scaling-stroke; }
.finance-forecast__point { fill:var(--accent); }
.finance-forecast__point.is-negative { fill:var(--danger); }
.finance-forecast__weeks { display:grid; grid-template-columns:repeat(12,minmax(0,1fr)); gap:4px; margin:10px 0 0; }
.finance-forecast__weeks button { display:grid; justify-items:center; gap:4px; min-height:48px; padding:8px 3px; border:1px solid transparent; border-radius:6px; color:var(--text-primary); background:transparent; cursor:pointer; font:inherit; }
.finance-forecast__weeks button span { font-size:12px; font-weight:600; }
.finance-forecast__weeks button small { font-size:11px; color:var(--text-secondary); }
.finance-forecast__weeks button:hover,.finance-forecast__weeks button[aria-pressed="true"] { border-color:var(--accent); background:var(--accent-soft); }
.finance-forecast__weeks button.is-negative span { color:var(--danger); }
.finance-forecast__weeks button:focus-visible { outline:2px solid var(--accent); outline-offset:1px; }
@container finance-work (max-width:720px) {
 .finance-forecast__weeks { grid-template-columns:repeat(6,minmax(0,1fr)); }
}
@container finance-work (max-width:480px) {
 .finance-shortcuts { grid-template-columns:minmax(0,1fr); gap:6px; }
 .finance-shortcuts .work-link { min-height:58px; padding:10px 12px; }
 .finance-shortcuts .panel-row__sub { display:none; }
 .finance-forecast__weeks button { padding:8px 2px; }
 .finance-forecast { margin-top:16px; padding-top:16px; }
}

/* Keep the ordinary invoice actions visible; show corrections when requested. */
.payable-more { flex-basis:100%; }
.payable-more > summary { width:fit-content; cursor:pointer; list-style:none; }
.payable-more > summary::-webkit-details-marker { display:none; }
.payable-more > summary::after { content:'+'; margin-left:10px; }
.payable-more[open] > summary::after { content:'−'; }
.payable-more__actions { display:flex; flex-wrap:wrap; gap:8px; padding-top:10px; }

/* The payment plan is one complete selection beside its original cash outlook. */
.payment-work{display:grid;gap:16px;margin-top:16px}
.payment-work__head{display:flex;align-items:start;justify-content:space-between;gap:16px}
.payment-work__head h2{margin:0;font-size:26px;letter-spacing:-.025em}
.payment-work__head p{margin:6px 0 0;color:var(--text-secondary)}
.payment-work__forecast{display:grid;grid-template-columns:minmax(170px,.65fr) minmax(0,2fr);gap:28px;align-items:center;padding:20px;border:1px solid var(--border);border-radius:12px;background:var(--panel)}
.payment-work__cash{display:grid;gap:5px;align-content:start}
.payment-work__cash>span{font-size:12px;color:var(--text-secondary)}
.payment-work__cash>strong{font-size:23px;font-variant-numeric:tabular-nums;letter-spacing:-.025em}
.payment-work__cash>small{font-size:12px;color:var(--text-secondary)}
.payment-work__cash>span:not(:first-child){margin-top:18px}
.payment-work .finance-forecast{margin:0;border:0;padding:0;min-width:0}
.payment-work__toolbar{display:flex;gap:12px;align-items:center;flex-wrap:wrap}
.payment-work__toolbar>label:first-child{flex:1;min-width:190px}
.payment-work__toolbar input{width:100%}
.payment-work input,.payment-work select{min-height:42px;max-width:100%;border:1px solid var(--border);border-radius:8px;background:var(--surface-inset);color:var(--text);padding:8px 12px;font:inherit}
.payment-work__filters{border-block:1px solid var(--border);padding:12px 0}
.payment-work__filters summary{cursor:pointer;font-weight:600}
.payment-work__filters summary>span{margin-left:10px;font-weight:400;font-size:12px;color:var(--text-secondary)}
.payment-work__filters form{display:flex;flex-wrap:wrap;align-items:end;gap:12px;padding-top:16px}
.payment-work__filters label{display:grid;gap:6px;font-size:12px}
.payment-work__selection{display:flex;align-items:center;justify-content:space-between;gap:20px}
.payment-work__selection h3{margin:0;font-size:18px}
.payment-work__selection p{margin:6px 0 0;color:var(--text-secondary);font-size:12px}
.payment-work__selection dl{display:flex;gap:24px;margin:0}
.payment-work__selection dt{font-size:12px;color:var(--text-secondary)}
.payment-work__selection dd{margin:5px 0 0;font-size:18px;font-weight:600;font-variant-numeric:tabular-nums}
.payment-work__rows{list-style:none;padding:0;margin:0;max-height:min(58svh,680px);overflow-y:auto;scrollbar-gutter:stable}
.payment-work__group{padding:14px 12px 8px;color:var(--text-secondary);font-size:12px;font-weight:600}
.payment-work__row{display:grid;grid-template-columns:minmax(0,1.3fr) minmax(120px,1fr) minmax(140px,.8fr) 18px;gap:14px;align-items:center;min-height:74px;border-bottom:1px solid var(--border);padding:14px 12px;text-decoration:none;color:var(--text);transition:background 120ms ease}
.payment-work__row:hover,.payment-work__row:focus-visible{background:var(--surface-hover);outline:2px solid var(--accent);outline-offset:-2px}
.payment-work__row>span{min-width:0}.payment-work__row strong{font-size:14px;font-weight:600;overflow-wrap:anywhere}
.payment-work__row small{display:block;margin-top:4px;font-size:12px;color:var(--text-secondary);overflow-wrap:anywhere}
.payment-work__kind{font-size:13px}.payment-work__amount{text-align:right;font-variant-numeric:tabular-nums}.payment-work__amount.is-incoming>strong{color:var(--good)}
.payment-work [data-payment-pages]{display:flex;gap:12px;align-items:center;justify-content:end;font-size:12px}
.payment-work__basis{padding:16px;border:1px solid var(--border);border-radius:10px}
.payment-work__basis>summary{font-weight:600;cursor:pointer}
.payment-work [data-payment-error]{padding:14px;border-left:3px solid var(--danger);color:var(--text)}
@media(max-width:760px){.payment-work__forecast{grid-template-columns:1fr;gap:18px;padding:14px}.payment-work__cash{grid-template-columns:1fr 1fr}.payment-work__cash>span,.payment-work__cash>strong,.payment-work__cash>small{grid-column:1}.payment-work__cash>span:not(:first-child){grid-column:2;grid-row:1;margin:0}.payment-work__cash>.pnl-neg,.payment-work__cash>strong:nth-of-type(2){grid-column:2;grid-row:2}.payment-work__cash>small:last-child{grid-column:2;grid-row:3}.payment-work__cash>strong{font-size:19px}.payment-work__selection{align-items:start;flex-direction:column;gap:12px}.payment-work__selection dl{gap:18px}.payment-work__row{grid-template-columns:minmax(0,1fr) minmax(120px,.8fr) 12px;gap:8px}.payment-work__kind{grid-column:1;grid-row:2}.payment-work__amount{grid-column:2;grid-row:1/3}.payment-work__row>span:last-child{grid-column:3;grid-row:1/3}.payment-work__row strong{font-size:13px}.payment-work__toolbar>label{flex:1}.payment-work__filters summary>span{display:block;margin:6px 0 0}.payment-work__rows{max-height:65svh}}
@media(prefers-reduced-motion:reduce){.payment-work__row{transition:none}}

/* The payments workspace starts with actual work, not four large directory cards. */
.finance-shortcuts--compact{display:flex;flex-wrap:wrap;gap:8px;margin:12px 0 18px}
.finance-shortcuts--compact .work-link{min-height:44px;padding:8px 14px}
.finance-shortcuts--compact .panel-row__sub{display:none}
.payment-work .finance-forecast figcaption{margin-bottom:4px}
.payment-work .finance-forecast__weeks{display:flex;gap:4px;overflow-x:auto;padding:2px;margin-top:4px;scrollbar-width:thin}
.payment-work .finance-forecast__weeks button{flex:1 0 44px;min-height:44px;padding:6px 2px}
@media(max-width:760px){.finance-shortcuts--compact .work-link{flex:1 1 calc(50% - 8px);min-height:44px}.payment-work__head h2{font-size:22px}.payment-work__head p{font-size:12px}.payment-work__forecast{padding:12px;gap:12px}}
/* ============================================================
   Patch-Integration — Namensraum lx-inbox- (Persönlicher Eingang); Quelle: docs/design/patch-inbox.css
   ============================================================ */
/* Eingang493. Quelle: docs/design/patch-inbox.css */
.lx-top .sidebar__bell { width: 44px; min-width: 44px; height: 44px; min-height: 44px; }
.lx-bell-panel.lx-inbox { width: min(440px, calc(100vw - 24px)); padding: 0; border-radius: 14px; }
.lx-inbox .lx-bell-panel__head { padding: 10px 14px 4px; }
.lx-inbox .lx-bell-panel__head > div { display: flex; }
.lx-inbox .lx-bell-panel__head strong { font-size: 17px; }
.lx-inbox .lx-bell-panel__head button { width: 44px; height: 44px; font-size: 22px; }
.lx-inbox .lx-bell-panel__head svg { width: 18px; height: 18px; }
.lx-inbox-tabs { display: grid; grid-template-columns: 1fr 1fr; border-bottom: 1px solid var(--line); padding: 0 12px; }
.lx-inbox-tabs button { min-height: 46px; background: none; color: var(--muted); border: 0; border-bottom: 3px solid transparent; font: inherit; font-weight: 600; cursor: pointer; }
.lx-inbox-tabs button[aria-pressed="true"] { color: var(--text); border-bottom-color: var(--accent); }
.lx-inbox-tabs span { font-size: 12px; padding: 2px 6px; margin-left: 6px; border-radius: 6px; background: var(--hover); }
.lx-inbox-content { padding: 12px; }
.lx-inbox-controls { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 6px; margin-bottom: 10px; }
.lx-inbox-filter { display: flex; gap: 2px; background: var(--hover); border-radius: 8px; padding: 2px; }
.lx-inbox-filter button { min-height: 44px; padding: 7px 10px; background: none; border: 1px solid transparent; color: var(--muted); font: inherit; font-size: 13px; border-radius: 6px; cursor: pointer; }
.lx-inbox-filter button[aria-pressed="true"] { border-color: var(--line); background: var(--panel); color: var(--text); }
.lx-inbox .lx-bell-panel__all { min-height: 44px; color: var(--text); }
.lx-inbox .lx-bell-row { border-radius: 8px; text-decoration: none; min-height: 48px; }
.lx-inbox .lx-bell-row__title { font-size: 14px; line-height: 1.4; }
.lx-inbox .lx-bell-row__meta { line-height: 1.45; }
.lx-inbox .lx-bell-row__age { font-size: 12px; max-width: 75px; }
.lx-inbox .lx-bell-buendel { border-bottom: 1px solid var(--line); }
.lx-inbox .lx-bell-buendel > button { margin-left: 10px; width: calc(100% - 10px); }
.lx-inbox-range,.lx-inbox-footnote { font-size: 12px; line-height: 1.5; color: var(--muted); padding: 0 10px; }
.lx-inbox-footnote { margin: 12px 0 4px; }
.lx-inbox-next { width: 100%; justify-content: center; min-height: 44px; margin-top: 8px; text-align: center; }
.lx-inbox-workhead { display: grid; gap: 4px; padding: 4px 10px 12px; }
.lx-inbox-workhead span { color: var(--muted); font-size: 12px; }
.lx-inbox-error,.lx-inbox-notice { margin: 8px 12px; padding: 10px 12px; border: 1px solid var(--line); border-radius: 8px; font-size: 13px; line-height: 1.5; }
.lx-inbox-error p { margin: 0 0 8px; }
.lx-inbox button:disabled { opacity: .55; cursor: wait; }
.lx-inbox button:focus-visible,.lx-inbox a:focus-visible,.lx-inbox summary:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
@media(max-width:720px) { .lx-bell-panel.lx-inbox { width: auto; } .lx-inbox-filter button { min-height: 44px; } }
/* ============================================================
   Patch-Integration — Namensraum operator-register/pd2-desk (Betreiberarbeitsplatz); Quelle: docs/design/patch-operator-desk.css
   ============================================================ */
/* Betreiberarbeitsplatz494. Quelle: docs/design/patch-operator-desk.css */
.operator-register .seiten-kopf { margin-bottom: 18px; }
.operator-register__tools { display: flex; flex-direction: column; gap: 10px; margin-bottom: 16px; }
.operator-register .pl-suchzeile { margin: 0; }
.operator-register .pl-suche { width: 100%; }
.operator-register .pl-work { margin: 0; padding: 0; border: 0; background: transparent; box-shadow: none; }
.operator-register .pl-work__controls { display: flex; gap: 10px; align-items: end; flex-wrap: wrap; }
.operator-register .pl-work__controls .field { flex: 1 1 190px; min-width: 0; gap: 4px; }
.operator-register .pl-work__controls select { width: 100%; }
.operator-register .pl-work__controls button { min-width: 44px; height: 44px; }
.operator-register .pl-work__controls button span { display: none; }
.operator-register [data-work-summary] { margin: 8px 0 0; font-size: 13px; font-weight: 500; color: var(--muted); }
.operator-register .pl-secondary-filters { margin: 8px 0 0; }
.operator-register .pl-secondary-filters > summary { min-height: 44px; display: flex; align-items: center; font-size: 13px; cursor: pointer; color: var(--text); }
.operator-register .pl-secondary-filters > summary::before { content: ''; width: 7px; height: 7px; border-right: 1.5px solid; border-bottom: 1.5px solid; transform: rotate(-45deg); margin: 0 10px 0 3px; }
.operator-register .pl-secondary-filters[open] > summary::before { transform: rotate(45deg); }
.operator-register .pl-secondary-filters [data-slot="ansichten"] { margin: 4px 0 12px; }
.operator-register .pl-summary { margin-top: 20px; }
.operator-register .pl-table--compact { width: 100%; min-width: 0; table-layout: fixed; }
.operator-register .pl-table--compact th,.operator-register .pl-table--compact td { padding: 13px 10px; white-space: normal; vertical-align: top; overflow-wrap: anywhere; }
.operator-register .pl-table--compact .pl-pick { width: 44px; padding: 8px 0; }
.operator-register .pl-table--compact .pl-menu-cell { width: 44px; padding: 8px 0; }
.operator-register .pl-table--compact .pl-haupt { width: auto; }
.operator-register .pl-table--compact strong { display: block; line-height: 1.45; }
.operator-register .pl-compact__meta,.operator-register .pl-work-owner { display: block; color: var(--muted); font-size: 12px; line-height: 1.5; margin-top: 3px; }
.operator-register .pl-compact__money strong { white-space: nowrap; }
.operator-register .pl-compact__work { font-size: 13px; }
.operator-register .pl-table--compact .pl-money-column { width: 160px; }
.operator-register .pl-table--compact .pl-work-column { width: 30%; }
.operator-record .pd2-section-nav { display: flex; align-items: center; gap: 8px; min-width: 0; margin-bottom: 18px; }
.operator-record .pd2-section-nav .pd2-tabs { min-width: 0; flex: 1; margin: 0; }
.operator-record [data-operator-more] { position: relative; flex: 0 0 auto; }
.operator-more summary { cursor: pointer; padding: 12px; min-height: 44px; box-sizing: border-box; font-size: 13px; }
.operator-more nav { position: absolute; z-index: 35; top: 100%; right: 0; min-width: 210px; border: 1px solid var(--line); border-radius: 10px; padding: 6px; background: var(--panel); }
.operator-more a { display: block; padding: 12px; min-height: 44px; box-sizing: border-box; text-decoration: none; color: var(--text); font-size: 14px; border-radius: 6px; }
.operator-more a:hover,.operator-more a[aria-current] { background: var(--hover); }
.pd2-desk { border: 1px solid var(--line); border-radius: 14px; background: var(--panel); overflow: clip; }
.pd2-desk-main { display: grid; grid-template-columns: minmax(0,1.1fr) minmax(0,1fr); }
.pd2-desk-section { min-width: 0; padding: 20px; }
.pd2-desk-section > header { display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 10px; margin-bottom: 16px; }
.pd2-desk-section > header button { min-height: 44px; }
.pd2-desk-section h2 { margin: 0; font-size: 16px; font-weight: 650; }
.pd2-desk-section .pd2-card__body { padding: 0; }
.pd2-desk-main > section + section { border-left: 1px solid var(--line); }
.pd2-desk-main > section:only-child { grid-column: 1 / -1; }
.pd2-desk .empty-state { padding: 16px 0; text-align: left; align-items: flex-start; }
.pd2-desk .empty-state__text { max-width: none; }
.pd2-desk-routes { margin-top: 18px; border-top: 1px solid var(--line); }
.pd2-desk-routes button { display: flex; align-items: center; gap: 10px; width: 100%; min-height: 48px; padding: 10px 0; border: 0; border-bottom: 1px solid var(--line); border-radius: 0; background: transparent; text-align: left; color: var(--text); font: inherit; font-size: 14px; cursor: pointer; }
.pd2-desk-routes button:last-child { border: 0; }
.pd2-desk-routes svg { width: 18px; height: 18px; flex: 0 0 auto; }
.pd2-desk-routes svg:last-child { margin-left: auto; }
.pd2-desk-routes button:hover { color: var(--accent); }
.pd2-account-values { display: grid; gap: 10px; grid-template-columns: 1fr 1fr; }
.pd2-account-values > span { display: grid; gap: 3px; }
.pd2-account-values > span:last-child { grid-column: 1/-1; display: flex; gap: 8px; align-items: baseline; margin-top: 6px; padding-top: 10px; border-top: 1px solid var(--line); }
.pd2-account-values strong { font-size: 19px; font-variant-numeric: tabular-nums; white-space: nowrap; font-weight: 650; }
.pd2-account-values > span:last-child strong { font-size: 15px; }
.pd2-account-values span span { font-size: 12px; color: var(--muted); }
.pd2-account-actions { display: flex; flex-wrap: wrap; gap: 6px; margin: 14px 0; }
.pd2-account-actions button { min-height: 44px; }
.pd2-settlement { padding: 14px 0; border-top: 1px solid var(--line); display: flex; align-items: center; gap: 12px; justify-content: space-between; }
.pd2-settlement > div { display: grid; gap: 5px; }
.pd2-settlement span { font-size: 12px; line-height: 1.5; color: var(--muted); }
.pd2-settlement strong { font-size: 17px; }
.pd2-account-source summary { font-size: 12px; min-height: 44px; cursor: pointer; padding: 12px 0; box-sizing: border-box; }
.pd2-desk-detail { border-top: 1px solid var(--line); }
.pd2-desk-detail > summary { padding: 16px 20px; cursor: pointer; font-size: 14px; font-weight: 600; min-height: 50px; box-sizing: border-box; }
.pd2-desk-detail__body { display: grid; grid-template-columns: repeat(auto-fit,minmax(min(100%,300px),1fr)); gap: 0; }
.pd2-desk-detail .pd2-desk-section { padding-top: 8px; }
.operator-record [data-slot="kpis"] { margin-top: 16px; }
.pd2-desk button:focus-visible,.pd2-desk summary:focus-visible,.operator-more summary:focus-visible,.operator-more a:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
@media (max-width:900px) {
  .pd2-desk-main { grid-template-columns: 1fr; }
  .pd2-desk-main > section + section { border-left: 0; border-top: 1px solid var(--line); }
}
@media (max-width:720px) {
  .operator-register .pl-work__controls { gap: 8px; }
  .operator-register .pl-work__controls .field { flex-basis: calc(50% - 30px); }
  .operator-register .pl-work__controls .field span { font-size: 12px; }
  .operator-register .pl-work__controls select { min-height: 44px; font-size: 13px; padding-left: 8px; }
  .operator-register .pl-table--compact td { width: auto; padding: 7px 0; }
  .operator-register .pl-table--compact .pl-haupt { width: 100%; }
  .operator-register .pl-table--compact .pl-pick,.operator-register .pl-table--compact .pl-menu-cell { width: 44px; }
  .operator-register .pl-table--compact .pl-compact__work { display: block; width: 100%; text-align: left; }
  .operator-register .pl-table--compact .pl-compact__work::before { display: none; }
  .pd2-desk-section { padding: 16px; }
  .pd2-desk-detail > summary { padding: 16px; }
  .pd2-account-values strong { font-size: 18px; }
  .pd2-settlement { align-items: flex-start; flex-direction: column; }
  .operator-record .pd2-section-nav { gap: 2px; }
  .operator-more summary { padding: 12px 6px; }
}

@media (max-width:720px) {
  .operator-register .pl-table--compact tbody tr { grid-template-columns: 44px minmax(0,1fr) 44px; align-items: start; padding: 8px 12px 12px; gap: 0; }
  /* Own card layout takes precedence over the shared labelled-table stack. */
  .operator-register .table-wrap table.pl-table--compact tbody tr td { display: block; min-width: 0; padding: 6px 0; background: transparent; text-align: left !important; }
  .operator-register .pl-table--compact tbody td::before { display: none; }
  .operator-register .pl-table--compact tbody td.pl-pick { grid-row: 1; grid-column: 1; padding: 0; }
  .operator-register .pl-table--compact tbody td.pl-menu-cell { grid-row: 1; grid-column: 3; padding: 0; }
  .operator-register .pl-table--compact tbody td.pl-haupt { display: block; grid-row: 2; grid-column: 1/-1; white-space: normal; }
  .operator-register .pl-table--compact tbody td.pl-haupt strong { font-size: 15px; }
  .operator-register .pl-table--compact tbody td.pl-compact__work { grid-row: 3; grid-column: 1/-1; }
  .operator-register .table-wrap table.pl-table--compact tbody tr td.pl-compact__money { grid-row: 4; grid-column: 1/-1; display: flex; flex-wrap: wrap; align-items: baseline; justify-content: flex-start; gap: 0 8px; padding-top: 10px; margin-top: 6px; border-top: 1px solid var(--line); }
  .operator-register .pl-table--compact tbody td.pl-compact__money > span:nth-last-child(-n+2) { flex-basis: 100%; }
}

/* A planned partial amount stays beside its original operator account. */
.operator-payment-plan { margin: 0 0 24px; padding: 22px; border-radius: 12px; background: var(--bg-card, var(--surface)); border: 1px solid var(--border); container-type: inline-size; }
.operator-payment-plan:has(> section:empty), [data-contract-status] .operator-payment-plan:not(:has(aside)):not(:has([role="alert"]:not(:empty))) { display: none; }
.operator-payment-plan > header { display: flex; justify-content: space-between; align-items: start; gap: 16px; }
.operator-payment-plan h3, .operator-payment-plan h4 { margin: 0 0 8px; }
.operator-payment-plan p { color: var(--text-secondary); max-width: 70ch; line-height: 1.5; margin: 8px 0 16px; }
.operator-payment-plan [role="alert"]:not(:empty) { color: var(--danger); margin: 0 0 12px; }
.operator-payment-plan__months { display: grid; grid-template-columns: repeat(auto-fit,minmax(min(100%,210px),1fr)); gap: 10px; }
.operator-payment-plan__month { display: grid; gap: 7px; text-align: left; border: 1px solid var(--border); border-radius: 8px; background: transparent; color: var(--text); padding: 16px; min-height: 44px; cursor: pointer; }
.operator-payment-plan__month[aria-pressed="true"] { border-color: var(--accent); background: var(--accent-soft); box-shadow: inset 3px 0 var(--accent); }
.operator-payment-plan__month strong { font-size: 22px; font-variant-numeric: tabular-nums; }
.operator-payment-plan__month small { font-size: 12px; color: var(--text-secondary); }
.operator-payment-plan__form { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; margin-top: 20px; padding-top: 20px; border-top: 1px solid var(--border); }
.operator-payment-plan__form h4,.operator-payment-plan__form p,.operator-payment-plan__form .field:has(textarea) { grid-column: 1/-1; }
.operator-payment-plan__form [hidden] { display: none; }
.operator-payment-plan__form button { min-height: 44px; justify-self: start; grid-column: 1/-1; }
@container (max-width: 480px) { .operator-payment-plan__form { grid-template-columns: 1fr; } }
@media (max-width: 600px) { .operator-payment-plan { padding: 14px; } .operator-payment-plan > header { flex-wrap: wrap; } }
/* Keep the selected month's balance and its plan beside each other. */
.operator-payment-plan { display: grid; grid-template-columns: minmax(190px,.7fr) minmax(280px,1.5fr); gap: 16px; }
.operator-payment-plan > header,.operator-payment-plan > aside,.operator-payment-plan > [role="alert"] { grid-column: 1/-1; }
.operator-payment-plan > [role="alert"]:empty { display: none; }
.operator-payment-plan__months { align-content: start; grid-template-columns: 1fr; max-height: 480px; overflow: auto; }
.operator-payment-plan:has([data-contract-form]:empty) .operator-payment-plan__months { grid-column: 1/-1; grid-template-columns: repeat(auto-fit,minmax(min(100%,210px),1fr)); }
.operator-payment-plan__form { margin: 0; padding: 0; border: 0; grid-template-columns: repeat(auto-fit,minmax(min(100%,220px),1fr)); }
@container (max-width: 580px) { .operator-payment-plan > .operator-payment-plan__months,.operator-payment-plan > [data-contract-form] { grid-column: 1/-1; } .operator-payment-plan__months { max-height: 270px; } }
@media (max-width: 600px) { .operator-payment-plan { grid-template-columns: 1fr; } }
.operator-payment-plan > [data-contract-form] { min-width: 0; container-type: inline-size; }
.operator-payment-plan__form { grid-template-columns: repeat(2,minmax(0,1fr)); }
@container (max-width: 480px) { .operator-payment-plan__form { grid-template-columns: 1fr; } }

/* Operator planning uses the original register and original task editor. */
.operator-planning{padding:14px 0 4px;border-top:1px solid var(--border);margin-top:12px}
.operator-planning__head{display:flex;align-items:center;justify-content:space-between;gap:16px;margin-bottom:12px}
.operator-planning__head h2{font-size:16px;margin:0 0 3px}.operator-planning__head span{font-size:12px;color:var(--muted)}
.operator-planning__head label{min-width:0;display:flex;align-items:center;gap:8px;font-size:12px}.operator-planning select{max-width:250px;min-width:0;min-height:44px;overflow:hidden;text-overflow:ellipsis}
.operator-planning__periods{display:grid;grid-template-columns:repeat(6,minmax(0,1fr));gap:6px}
.operator-planning__periods button{background:var(--panel);border:1px solid var(--border);border-radius:8px;text-align:left;color:var(--text);padding:9px 11px;min-height:76px;cursor:pointer}
.operator-planning__periods button[aria-pressed=true]{border-color:var(--accent);box-shadow:inset 0 0 0 1px var(--accent)}
.operator-planning__periods button>span{display:block;font-size:12px}.operator-planning__periods strong{display:block;font-size:20px;line-height:1.35;font-variant-numeric:tabular-nums}
.operator-planning__periods i{display:block;background:var(--border);height:3px;margin-top:5px;border-radius:2px;overflow:hidden}.operator-planning__periods b{display:block;height:100%;background:var(--accent)}
.operator-planning__custom{margin-top:10px;font-size:12px}.operator-planning__custom summary{cursor:pointer;padding:8px 0}
.operator-planning__custom form{display:flex;align-items:end;flex-wrap:wrap;gap:8px;padding-bottom:8px}.operator-planning__custom label{display:grid;gap:4px}.operator-planning__custom input{min-height:40px}.operator-planning__custom p{flex-basis:100%;margin:0}
.pl-task-edit{display:block;max-width:100%;white-space:normal;overflow-wrap:anywhere;text-align:left;color:var(--text);font:inherit;font-weight:600;background:none;border:0;padding:8px 0;min-height:44px;cursor:pointer}.pl-task-edit:hover{text-decoration:underline;text-underline-offset:3px}.pl-task-edit:focus-visible{outline:2px solid var(--accent);outline-offset:2px;border-radius:3px}
@media(max-width:700px){.operator-planning__head{align-items:start}.operator-planning__head label{display:grid;gap:4px}.operator-planning select{max-width:185px}.operator-planning__periods{grid-template-columns:repeat(3,minmax(0,1fr))}.operator-planning__periods button{min-height:70px;padding:8px}.operator-planning__custom form{display:grid;grid-template-columns:1fr 1fr}.operator-planning__custom form>button,.operator-planning__custom form>p{grid-column:1/-1}.operator-planning__custom input{min-width:0;width:100%}}

@media(max-width:720px){.operator-register .pl-table--work tbody td.pl-haupt{white-space:normal;overflow-wrap:anywhere}.operator-register .pl-table--work tbody td.pl-haupt strong{display:block}.operator-register .pl-table--work tbody td.pl-next-work{width:100%;min-width:0}}

/* On a phone, keep original work visible below the planning controls. */
@media(max-width:720px){
 .operator-planning__periods button{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;gap:3px 5px;min-height:54px;padding:7px 8px}
 .operator-planning__periods strong{font-size:18px}
 .operator-planning__periods i{grid-column:1/-1;margin-top:0}
 .operator-register .table-wrap table.team-table.pl-table--work tbody tr{grid-template-columns:44px minmax(0,1fr) 44px;align-items:start;gap:0;padding:8px 12px 12px}
 .operator-register .table-wrap table.team-table.pl-table--work tbody tr td.pl-pick{grid-row:1;grid-column:1;width:44px;padding:0}
 .operator-register .table-wrap table.team-table.pl-table--work tbody tr td.pl-menu-cell{grid-row:1;grid-column:3;width:44px;padding:0}
 .operator-register .table-wrap table.team-table.pl-table--work tbody tr td.pl-haupt{display:block;text-align:left!important;grid-row:1;grid-column:2;min-width:0;padding:0 6px}
 .operator-register .table-wrap table.team-table.pl-table--work tbody tr td.pl-next-work{display:block;text-align:left!important;box-sizing:border-box;grid-row:2;grid-column:1/-1;padding:10px 0 0}
}
/* ============================================================
   Patch-Integration — Namensraum team-desk (Teamarbeitsplatz); Quelle: docs/design/patch-team-workspace.css
   ============================================================ */
/* One team workspace; figures and work share the existing Sand/Dark palette. */
.team-desk { container-type:inline-size; }
.team-desk__heading, .team-desk__person-heading { display:flex; align-items:center; justify-content:space-between; gap:16px; flex-wrap:wrap; }
.team-desk__header-actions { display:flex; gap:8px; flex-wrap:wrap; }
.team-desk__heading { padding:12px 0 20px; }
.team-desk__heading h2, .team-desk__person-heading h3 { margin:0; color:var(--text-primary); }
.team-desk__heading p, .team-desk__context { color:var(--text-secondary); margin:6px 0 0; font-size:13px; line-height:1.5; }
.team-desk__choose { display:none; }
.team-desk__tools { display:flex; align-items:center; flex-wrap:wrap; gap:12px; margin-bottom:20px; }
.team-desk__tools > label:first-child { flex:1 1 200px; }
.team-desk__tools input { width:100%; }
.team-desk__tools > label:not(:first-child) { display:flex; align-items:center; gap:8px; color:var(--text-secondary); font-size:12px; }
.team-desk__tools input, .team-desk__tools select { min-height:44px; }
.team-desk__body { display:grid; grid-template-columns:minmax(340px,.85fr) minmax(0,1.15fr); gap:24px; align-items:start; }
.team-desk__people, .team-desk__person { min-width:0; }
.team-desk__row { display:grid; grid-template-columns:minmax(100px,1.3fr) repeat(3,minmax(0,1fr)); width:100%; gap:12px; padding:18px 12px; text-align:left; border:0; border-bottom:1px solid var(--border); border-left:3px solid transparent; border-radius:0; background:transparent; color:var(--text-primary); cursor:pointer; }
.team-desk__row:hover { background:var(--surface-2); }
.team-desk__row[aria-pressed="true"] { background:var(--surface-2); border-left-color:var(--accent); }
.team-desk__row:focus-visible { outline:2px solid var(--accent); outline-offset:-2px; }
.team-desk__identity, .team-desk__metric { display:flex; flex-direction:column; min-width:0; gap:5px; }
.team-desk__identity strong { font-size:14px; overflow-wrap:anywhere; line-height:1.35; }
.team-desk__identity small, .team-desk__metric small, .team-desk__person-heading small { color:var(--text-secondary); font-size:11px; line-height:1.35; }
.team-desk__metric strong { font-size:21px; line-height:1; font-variant-numeric:tabular-nums; font-weight:650; }
.team-desk__late strong { color:var(--warn-strong); }
.team-desk__bar { display:block; height:3px; background:var(--border); margin-top:3px; }
.team-desk__bar i { display:block; height:100%; background:var(--accent); }
.team-desk__person { border-left:1px solid var(--border); padding-left:24px; }
.team-desk__person-heading { padding-top:14px; }
.team-desk__context { padding-bottom:20px; border-bottom:1px solid var(--border); margin-bottom:20px; }
.team-desk__empty { padding:28px 12px; color:var(--text-secondary); font-size:14px; }
.team-desk .od { border:0; padding:0; }
.team-desk .od-work { grid-template-columns:minmax(0,1fr); }
.team-desk .od-list { max-height:300px; padding-right:0; }
.team-desk .od-detail { border-left:0; border-top:1px solid var(--border); padding:20px 0 0; }
@container (max-width:880px) {
  .team-desk__choose { display:inline-flex; margin-bottom:16px; }
  .team-desk[data-choosing="false"] .team-desk__tools, .team-desk[data-choosing="false"] .team-desk__people { display:none; }
  .team-desk__body { grid-template-columns:minmax(0,1fr); }
  .team-desk__person { border-left:0; border-top:1px solid var(--border); padding:12px 0 0; }
  .team-desk__people [data-team-rows] { max-height:360px; overflow:auto; }
}
@media(max-width:540px) {
  .team-desk__row { grid-template-columns:repeat(3,minmax(0,1fr)); gap:14px; padding:16px 12px; }
  .team-desk__identity { grid-column:1/-1; flex-direction:row; align-items:baseline; justify-content:space-between; }
  .team-desk__tools > label:not(:first-child) { flex:1 1 200px; }
  .team-desk__tools select { min-width:0; width:100%; }
  .team-desk__metric small { font-size:11px; }
}

/* Profile-linked capture: essential actions first; additional planning on demand. */
.task-work { gap: 16px; }
.task-work .task-modal__link { margin: 0; padding: 10px 12px; border-left: 3px solid var(--accent); background: var(--surface-2); color: var(--text); border-radius: 4px; }
.task-work__fields { border: 0; padding: 0; margin: 0; min-width: 0; display: grid; gap: 14px; }
.task-work__fields:disabled { opacity: .75; }
.task-work__timing { display: grid; gap: 8px; }
.task-work__timing > span { font-size: 13px; color: var(--muted); }
.task-work__days { display: flex; gap: 6px; flex-wrap: wrap; }
.task-work__days .ghost-btn { min-height: 36px; padding: 6px 12px; }
.task-work__days [aria-pressed="true"] { color: var(--accent); border-color: var(--accent); background: var(--surface-2); }
.task-work__more { border-top: 1px solid var(--border); padding-top: 12px; }
.task-work__more > summary { cursor: pointer; font-size: 14px; font-weight: 600; padding: 4px 0; }
.task-work__more-body { display: grid; gap: 14px; padding-top: 14px; }
.task-work__feedback { padding: 12px; background: var(--surface-2); border-left: 3px solid var(--accent); color: var(--text); line-height: 1.5; }
.task-work .notes-area { min-height: 72px; }
.task-work .modal-actions { position: sticky; bottom: -20px; background: var(--surface); padding-top: 12px; border-top: 1px solid var(--border); z-index: 1; }
@media (max-width: 560px) {
  .task-work { gap: 12px; }
  .task-work__fields { gap: 12px; }
  .task-work .modal-actions { bottom: -16px; }
}
/* ============================================================
   Patch-Integration — Namensraum calendar-workspace; Quelle: docs/design/patch-calendar-workspace.css
   ============================================================ */
.calendar-workspace{min-width:0}
.calendar-focus{display:flex;align-items:center;justify-content:space-between;gap:16px;flex-wrap:wrap;padding:12px 16px;margin-bottom:16px;border-left:3px solid var(--accent);background:var(--surface)}
.calendar-focus>div{min-width:0}.calendar-focus strong,.calendar-focus span{display:block;overflow-wrap:anywhere}.calendar-focus span{color:var(--text-secondary);font-size:13px;margin-top:4px}.calendar-focus p{margin:0}.calendar-focus__actions{display:flex;gap:8px;flex-wrap:wrap}
.calendar-workspace .cal-mode-bar{display:flex;align-items:center;gap:16px;flex-wrap:wrap;margin-bottom:16px}
.calendar-workspace .cal-mode-bar__wer{min-width:200px;max-width:360px;flex:1}
.calendar-workspace .cal-mode-bar__wer select{width:100%}
.calendar-workspace .cal-notes-toggle{margin-left:auto}
.cal-work-layout{display:grid;grid-template-columns:minmax(0,1fr);gap:20px;align-items:start}
.cal-work-layout>[data-slot=mode-body]{min-width:0}
.cal-work-layout .cal-side-panel[hidden]{display:none}
.cal-work-layout .cal-side-panel__body{display:flex}
.cal-work-layout .cal-side-panel__chev{display:none}
.calendar-workspace .cal-toolbar{gap:14px;align-items:center}
.calendar-workspace .cal-toolbar__nav{flex:1 1 100%;gap:8px}
.calendar-workspace .cal-toolbar__title{margin-left:auto;font-size:18px;line-height:1.4}
.calendar-workspace .cal-toolbar__views{margin-left:auto}
.calendar-workspace .cal-arten{display:flex;flex-wrap:wrap;gap:6px;padding:12px 16px;border-bottom:1px solid var(--border)}
.calendar-workspace .cal-arten .cal-toggle{min-height:36px;font-size:13px}
.calendar-workspace .cal-src-warn{display:flex;gap:10px;align-items:center;flex-wrap:wrap;line-height:1.5}
.calendar-workspace .cal-note__status{font-weight:500}
.calendar-workspace .cal-note__area:disabled{opacity:.65}
@media(min-width:1200px){.cal-work-layout.has-notes{grid-template-columns:minmax(0,1fr) 300px}}
@media(max-width:1199px){.cal-work-layout.has-notes .cal-side-panel{grid-row:1;position:static}.cal-work-layout .cal-side-panel__head{min-height:0}}
@media(max-width:600px){.calendar-workspace .cal-mode-bar{gap:10px}.calendar-workspace .cal-mode-bar__wer{min-width:0;flex-basis:100%;max-width:none;order:3}.calendar-workspace .cal-toolbar__title{flex-basis:100%;margin:0;font-size:16px}.calendar-workspace .cal-toolbar__controls{flex:1}.calendar-workspace .cal-toolbar__views{width:100%}.calendar-workspace .cal-arten{padding:10px;gap:4px}.calendar-workspace .cal-arten .cal-toggle{font-size:12px;padding-inline:10px}}

.calendar-workspace .cal-view{max-height:max(360px,calc(100dvh - 330px));overflow:auto;overscroll-behavior:contain}
.calendar-workspace .cal-event{padding:5px 7px}
.calendar-workspace .cal-event__time{line-height:18px}
.calendar-workspace .cal-event__firm{line-height:18px}
.calendar-workspace .cal-grid--week{min-width:784px;overflow:visible}
.calendar-workspace .cal-week-body{overflow:visible}
.calendar-workspace .cal-week-cols,.calendar-workspace .cal-week-headers{min-width:0}
.calendar-workspace .cal-time-col{position:sticky;left:0;z-index:1;background:var(--surface-1)}
.calendar-workspace .cal-week-headers>div:first-child{position:sticky;left:0;z-index:3;background:var(--surface-2)}
@media(max-width:600px){.calendar-workspace .cal-toolbar{gap:10px;padding:12px}.calendar-workspace .cal-toolbar__controls{flex:1 1 100%}.calendar-workspace .cal-toolbar__controls .field{display:flex;align-items:center;gap:12px}.calendar-workspace .cal-toolbar__controls .field>span{flex:none}.calendar-workspace .cal-toolbar__controls select{min-width:0;flex:1}.calendar-workspace .cal-toolbar__views{gap:4px}}
.appointment-plan__outcome{border-left:3px solid var(--accent);padding-left:14px}
.appointment-plan__outcome p{white-space:pre-line;line-height:1.6}

/* Occupied time is readable without implying access to its private content. */
.cal-event--type-busy { border-left-color:var(--text-secondary); background:var(--surface); color:var(--text-secondary); cursor:default; }
.cal-busy-count { color:var(--text-secondary); font-size:.78rem; align-self:center; }
@media(max-width:600px){
  .calendar-workspace .cal-toolbar__nav{display:grid;grid-template-columns:40px 62px 40px minmax(0,1fr);gap:5px}
  .calendar-workspace .cal-toolbar__nav .ghost-btn{padding:0;min-width:0}
  .calendar-workspace .cal-toolbar__date{order:0;min-width:0;width:100%;padding-inline:6px;grid-column:4;grid-row:1}
  .calendar-workspace .cal-toolbar__title{grid-column:1/-1}
  .calendar-workspace .cal-toolbar__controls .field{flex-direction:row;text-align:left}
}
