/* lumafy Design-Tokens. Farben ausschliesslich hierueber verwenden. */
:root{
  --lu-black:#0C0C0C; --lu-ink:#1A1917; --lu-amber:#F5A623;
  --lu-white:#FFFFFF; --lu-sand:#F4F3EF;
  --line:#E4E2DC; --muted:#5F5C57; --red:#B23A26; --green:#2F7D4F;
  --r:14px; --r-sm:10px;
  --font:"Outfit","Poppins",system-ui,-apple-system,"Segoe UI",sans-serif;
}
/* Schrift wird lokal ausgeliefert. Dateien nach public/fonts/ legen (siehe public/fonts/README.md).
   Keine Einbindung ueber fonts.googleapis.com - das uebertraegt die Nutzer-IP an Google.
   Benennung wie im lumafy Font Pack: eine Variable Font deckt alle Weights ab. */
@font-face{
  font-family:"Outfit";
  src:url("/fonts/Outfit-Variable.woff2") format("woff2-variations"),
      url("/fonts/Outfit-Variable.woff2") format("woff2");
  font-weight:100 900;font-style:normal;font-display:swap;
}
/* Statische Schnitte als Rueckfallebene, falls die Variable Font nicht vorliegt.
   Liegen beide Saetze im Ordner, gewinnt die zuerst deklarierte Variable Font. */
@font-face{font-family:"Outfit";src:url("/fonts/Outfit-Light.woff2") format("woff2");font-weight:300;font-style:normal;font-display:swap}
@font-face{font-family:"Outfit";src:url("/fonts/Outfit-Regular.woff2") format("woff2");font-weight:400;font-style:normal;font-display:swap}
@font-face{font-family:"Outfit";src:url("/fonts/Outfit-Medium.woff2") format("woff2");font-weight:500;font-style:normal;font-display:swap}
@font-face{font-family:"Outfit";src:url("/fonts/Outfit-SemiBold.woff2") format("woff2");font-weight:600;font-style:normal;font-display:swap}

*{box-sizing:border-box;-webkit-tap-highlight-color:transparent}
html,body{margin:0;padding:0}
body{font-family:var(--font);font-weight:400;font-size:16px;line-height:1.45;color:var(--lu-black);
  background:#DEDCD6;display:flex;justify-content:center;min-height:100vh}
a{color:inherit}
button,input,select,textarea{font:inherit;color:inherit}
button{border:0;background:none;cursor:pointer}
.frame{width:100%;max-width:480px;min-height:100vh;background:var(--lu-sand);display:flex;flex-direction:column;
  position:relative;box-shadow:0 0 40px rgba(0,0,0,.14)}
.topbar{background:var(--lu-black);color:#fff;padding:12px 16px;display:flex;align-items:center;gap:10px}
.brandlink{display:flex;align-items:center;gap:10px;text-decoration:none;color:#fff}
.mark{width:26px;height:26px;border-radius:7px;background:var(--lu-ink);display:grid;
  grid-template-columns:1fr 1fr;grid-template-rows:1fr 1fr;gap:2.5px;padding:5px}
.mark i{border-radius:2px;display:block}
/* Zeichen wie im Logo-Paket (lumafy-color-icon): Amber, Hellgrau, Mittelgrau. */
.mark i.a{background:var(--lu-amber)} .mark i.w{background:#EBEBEB} .mark i.g{background:#737372}
.wordmark{font-weight:300;font-size:21px;line-height:1}
.spacer{flex:1}
.iconbtn{width:36px;height:36px;border-radius:10px;display:grid;place-items:center;color:#fff;
  font-size:17px;text-decoration:none}
.iconbtn.on{background:rgba(245,166,35,.18);color:var(--lu-amber)}
.screens{flex:1;padding:16px 14px calc(116px + env(safe-area-inset-bottom, 0px))}
.flash{margin:0 0 12px;padding:11px 13px;border-radius:var(--r-sm);font-size:14px;background:#EAF3EC;border:1px solid #C9E0D2}
.flash.error{background:#F7E6E2;border-color:#EBC9C0;color:#8A2E1D}
.flash.warn{background:#FDF3E1;border-color:#F0D9A8}
.flash ul{margin:6px 0 0 18px;padding:0}
h1{font-weight:300;font-size:27px;margin:2px 0;letter-spacing:-.01em}
h1 em{font-style:normal;font-weight:500}
.sub{color:var(--muted);font-size:13px;margin:4px 0 16px}
h2{font-weight:500;font-size:12px;letter-spacing:.09em;text-transform:uppercase;color:var(--muted);margin:22px 0 8px}
h2 .cnt{color:var(--lu-black);background:#E7E5DF;border-radius:20px;padding:1px 7px;font-size:11px;margin-left:6px;letter-spacing:0}
h2.warn{color:var(--red)} h2.warn .cnt{background:#F6DDD8;color:var(--red)}
.card{background:var(--lu-white);border-radius:var(--r);border:1px solid var(--line);margin-bottom:9px;overflow:hidden}
.cardmain{display:block;padding:13px 14px;text-decoration:none;color:inherit}
.row1{display:flex;align-items:flex-start;gap:9px}
.row1 .nm{font-weight:500;font-size:16px;flex:1;line-height:1.25}
.next{font-size:14px;margin-top:3px}
.meta{color:var(--muted);font-size:12.5px;margin-top:5px;display:flex;align-items:center;gap:7px;flex-wrap:wrap}
.dot{width:6px;height:6px;border-radius:50%;background:var(--muted)}
.due{font-weight:500} .due.over{color:var(--red)} .due.today{color:#8A5A00}
.b{font-size:11px;font-weight:500;padding:2px 8px;border-radius:99px;background:#EDEBE5;color:#3F3C37;white-space:nowrap}
.b.size{background:var(--lu-black);color:#fff}
.b.st[data-s="gewonnen"]{background:#DCEDE3;color:var(--green)}
.b.st[data-s="verloren"]{background:#F1E2DF;color:var(--red)}
.b.st[data-s="angebot"],.b.st[data-s="verhandlung"]{background:var(--lu-amber);color:var(--lu-black)}
/* flex-wrap ist hier nicht Kosmetik, sondern der Unterschied zwischen benutzbar
   und unbenutzbar. Gemessen am 14.09.2026 bei 390 px Fensterbreite:
   /firmen lief auf 681 px hinaus, /kunden, /artikel, /lieferanten und
   /pipeline auf 432 px - die Seite liess sich seitwaerts schieben, der Knopf
   "Filtern" stand ausserhalb des Bildes. Das trifft ausgerechnet die Seiten,
   die im Aussendienst am Telefon benutzt werden. */
.search{display:flex;align-items:center;gap:9px;background:var(--lu-white);border:1px solid var(--line);
  border-radius:var(--r);padding:11px 13px;margin-bottom:14px;flex-wrap:wrap}
/* min-width:0 gehoert dazu. Ein Flex-Kind bekommt von Haus aus
   "min-width:auto" und schrumpft deshalb NICHT unter seine natuerliche
   Breite - ein <input> bringt rund 170 px mit. Ohne diese Zeile half das
   Umbrechen allein nichts: das Eingabefeld schob den Rest weiterhin hinaus. */
.search input{border:0;outline:0;flex:1;min-width:0;background:none;font-size:16px}
.chips{display:flex;gap:7px;overflow-x:auto;padding:0 14px 12px;margin:0 -14px 10px}
.chip{flex:0 0 auto;font-size:13px;padding:6px 13px;border-radius:99px;background:var(--lu-white);
  border:1px solid var(--line);white-space:nowrap;text-decoration:none;color:inherit}
.chip.on{background:var(--lu-black);color:#fff;border-color:var(--lu-black);font-weight:500}
/* Filterleiste: Suchfeld oben, darunter die Auswahlfelder nebeneinander.
   Sie ersetzt zwei Reihen mit vierzehn Chips. */
.filterleiste{margin-bottom:14px}
.filterfelder{display:flex;gap:9px;flex-wrap:wrap}
.filterfeld{flex:1 1 150px;min-width:140px}
.filterfeld label{display:block;font-size:11px;letter-spacing:.06em;text-transform:uppercase;
  color:var(--muted);font-weight:500;margin-bottom:4px}
.filterfeld select{width:100%;padding:10px 11px;border-radius:var(--r-sm);
  border:1px solid var(--line);background:var(--lu-white);outline:0;font-size:14.5px;min-height:42px}
.filterfeld select:focus{border-color:var(--lu-black);outline:2px solid var(--lu-amber);outline-offset:1px}
/* Bleibt beim Blaettern am oberen Rand stehen. Ohne das musste man bei 95
   Treffern durch die ganze Liste scrollen, um die Auswahl zu uebernehmen.
   Der Hintergrund ist deckend, sonst scheinen die Karten durch. */
.mitlaufend{position:sticky;top:0;z-index:4;background:var(--lu-sand);
  padding:8px 0 10px;margin-bottom:2px;box-shadow:0 6px 10px -8px rgba(12,12,12,.35)}
.mitlaufend .btn{margin-top:0}
.empty{text-align:center;color:var(--muted);font-size:14px;padding:34px 20px;line-height:1.6}
/* Kopfbereich der Detailseiten.
   Reines Schwarz wirkte schwer. Der Verlauf laeuft von lumafy Schwarz in einen
   warmen Amber-Ton und traegt die Hausfarbe in den Kopf, ohne dass die weisse
   Schrift an Kontrast verliert: der hellste Punkt (#7A4E06) ergibt gegen Weiss
   noch rund 8:1, gefordert sind 4,5:1. */
.dhead{background:var(--lu-black);
  background:linear-gradient(118deg, var(--lu-black) 0%, #24190B 42%, #5C3B06 78%, #7A4E06 100%);
  color:#fff;margin:-16px -14px 0;padding:16px;position:relative;overflow:hidden}
/* Schmale Amber-Kante als Abschluss nach unten. */
.dhead::after{content:"";position:absolute;left:0;right:0;bottom:0;height:3px;background:var(--lu-amber)}
.dhead .back{color:#CBBFA8;font-size:13.5px;text-decoration:none;display:inline-block;margin-bottom:10px}
.dhead h1{color:#fff;font-size:25px}
.dhead .co{color:#D6C9B2;font-size:13.5px;margin-top:4px}
.dhead .bs{display:flex;gap:6px;margin-top:13px;flex-wrap:wrap}
.dhead .b{background:rgba(255,255,255,.16);color:#F4EFE5}
.dhead .b.size{background:var(--lu-amber);color:var(--lu-black)}
.chain{display:flex;gap:4px;margin:0 -14px;padding:12px 14px;background:var(--lu-ink);overflow-x:auto}
.chain button{flex:0 0 auto;font-size:11.5px;padding:7px 11px;border-radius:99px;color:#B3AEA6;
  background:rgba(255,255,255,.08);font-weight:500;white-space:nowrap}
.chain button.on{background:var(--lu-amber);color:var(--lu-black)}
.chain button.done{color:#E4E0D9;background:rgba(255,255,255,.16)}
.block{background:var(--lu-white);border:1px solid var(--line);border-radius:var(--r);padding:14px;margin-top:12px}
/* Bereichsueberschrift innerhalb einer Flaeche. Sie sah frueher genauso aus wie
   die Feldbeschriftung darunter - auf der Kontoseite standen dadurch zwei
   gleich aussehende Zeilen uebereinander ("PASSWORT AENDERN" / "AKTUELLES
   PASSWORT"), ohne erkennbare Rangfolge. */
.lbl{font-size:11.5px;letter-spacing:.09em;text-transform:uppercase;color:var(--lu-black);
  font-weight:600;display:block;margin-bottom:8px}
/* Keine Trennlinie: .lbl steht mal als Bereichsueberschrift, mal als Schluessel
   ueber einem Wert (Next Step, Wiedervorlage). Beide Faelle sind im Markup nicht
   zuverlaessig auseinanderzuhalten, und eine Linie ueber einem Wert waere falsch.
   Farbe und Strichstaerke reichen, um die Feldbeschriftungen abzusetzen. */
.val{font-size:17px;font-weight:500;margin-top:4px}
/* Folgt auf einen Wert die naechste Ueberschrift, braucht es Luft dazwischen -
   sonst liest sich "Angebot erstellen / WIEDERVORLAGE" wie ein Block. */
.val + .lbl{margin-top:18px}
.quick{display:flex;gap:6px;flex-wrap:wrap;margin-top:12px}
.quick button,.quick a{font-size:13px;padding:8px 12px;border-radius:99px;background:var(--lu-sand);
  border:1px solid var(--line);font-weight:500;text-decoration:none;color:inherit;display:inline-block;min-height:36px}
.quick .primary{background:var(--lu-amber);border-color:var(--lu-amber)}
.actions{display:grid;grid-template-columns:repeat(4,1fr);gap:7px;margin-top:12px}
.actions a,.actions button{background:var(--lu-white);border:1px solid var(--line);border-radius:var(--r-sm);
  padding:12px 4px;text-align:center;text-decoration:none;color:inherit;font-size:11.5px;font-weight:500;display:block;min-height:60px}
.actions .ic{display:block;font-size:18px;margin-bottom:3px}
.act{display:flex;gap:11px;padding:12px 0;border-bottom:1px solid var(--line)}
.act:last-child{border-bottom:0}
.act .tag{width:34px;height:34px;border-radius:9px;background:var(--lu-sand);display:grid;place-items:center;
  border:1px solid var(--line);flex:0 0 auto}
.act .tt{font-size:12px;color:var(--muted);display:flex;gap:7px}
.act .nn{font-size:14.5px;margin-top:2px;white-space:pre-wrap}
.act .ph{display:flex;gap:6px;margin-top:7px;flex-wrap:wrap}
.act .ph img{width:64px;height:48px;object-fit:cover;border-radius:7px;border:1px solid var(--line)}
.kv{display:flex;justify-content:space-between;gap:14px;padding:9px 0;border-bottom:1px solid var(--line);font-size:14.5px}
.kv:last-child{border-bottom:0}
.kv .k{color:var(--muted);font-size:13.5px}
.kv .v{text-align:right;font-weight:500}
.field{margin-bottom:13px}
.field label{display:block;font-size:12px;letter-spacing:.06em;text-transform:uppercase;color:var(--muted);
  font-weight:500;margin-bottom:5px}
.field input,.field select,.field textarea{width:100%;padding:12px 13px;border-radius:var(--r-sm);
  border:1px solid var(--line);background:var(--lu-white);outline:0;font-size:16px}
.field input:focus,.field select:focus,.field textarea:focus{border-color:var(--lu-black);outline:2px solid var(--lu-amber);outline-offset:1px}
.hint{font-size:12px;color:var(--muted);margin-top:4px}
.checks{display:flex;gap:8px;flex-wrap:wrap}
.checks label{display:inline-flex;align-items:center;gap:7px;background:var(--lu-white);border:1px solid var(--line);
  border-radius:99px;padding:9px 14px;font-size:14px;text-transform:none;letter-spacing:0;color:inherit;min-height:44px}
.checks input{width:18px;height:18px}
.btn{display:block;width:100%;padding:15px;border-radius:var(--r);background:var(--lu-amber);color:var(--lu-black);
  font-weight:600;font-size:16px;margin-top:8px;text-align:center;text-decoration:none;min-height:48px}
.btn.dark{background:var(--lu-black);color:#fff}
.btn.ghost{background:transparent;border:1px solid var(--line);font-weight:500}
/* Verwerfen ist die einzige Aktion, die etwas wegnimmt - sie wird als solche
   gekennzeichnet, steht aber zurueckhaltend am Seitenende. */
.btn.verwerfen{background:var(--red);color:#fff}
.btn.ghost.verwerfen-link{color:var(--red);border-color:#E4C6BF;margin-top:16px}

/* =========================================================================
   Hilfsklassen anstelle eingebetteter Stilattribute.
   GRUND: Der Server sendet Content-Security-Policy mit style-src 'self' und
   OHNE 'unsafe-inline'. Der Browser verwirft damit JEDES style="..."-Attribut
   im HTML. Am 24.08.2026 im Browser nachgemessen: die Balkenfuellung trug
   style="width:50%", gerendert wurden 147 px (die volle Spurbreite) und die
   Farbe aus dieser Datei. Alle 66 eingebetteten Stile der Anwendung waren
   seit jeher wirkungslos. scripts/check.js verbietet das Muster jetzt.
   ========================================================================= */
.mb6{margin-bottom:6px} .mb8{margin-bottom:8px} .mb10{margin-bottom:10px} .mb12{margin-bottom:12px}
.mt4{margin-top:4px} .mt8{margin-top:8px} .mt10{margin-top:10px} .mt12{margin-top:12px}
.mt13{margin-top:13px} .mt14{margin-top:14px} .mt18{margin-top:18px}
.m0{margin:0} .m0010{margin:0 0 10px} .m0004{margin:0 0 4px}
.inl{display:inline} .ml6{margin-left:6px}
.rot{color:var(--red)} .stumm{color:var(--muted)}
.zellemittig{text-align:center} .nichtumbrechen{white-space:nowrap}
/* Rechtetafel: die erste Spalte traegt den Text, die Rollenspalten nur einen
   Haken. Ohne feste Breite zoegen die Rollenspalten sonst auseinander. */
.tbl.rechte td:first-child,.tbl.rechte th:first-child{min-width:190px}
.tbl.rechte th:not(:first-child),.tbl.rechte td:not(:first-child){width:88px;text-align:center}
.tbl.rechte input[type=checkbox]{width:18px;height:18px}
/* Positionstabelle (Phase 2, VT-05): Eingaben in Tabellenzellen, Artikel breit, Zahlen schmal. */
.tbl td input:not([type=checkbox]){width:100%;min-width:4.5em;padding:9px 8px;border-radius:var(--r-sm);
  border:1px solid var(--line);background:var(--lu-white);font-size:15px}
.tbl td:first-child input[list]{min-width:16em}
.tbl td input:focus{border-color:var(--lu-black);outline:2px solid var(--lu-amber);outline-offset:1px}
.tbl td input[type=checkbox]{width:18px;height:18px}
.fs12{font-size:12px} .fs125{font-size:12.5px} .fs14{font-size:14px}
.normal{font-weight:400} .linksbuendig{text-align:left} .ohnestrich{text-decoration:none}
.feldkurz{max-width:140px} .zweispaltig{grid-template-columns:1fr 1fr}
.haken{width:20px;height:20px;margin-right:8px}
.wahlflaeche{display:block;cursor:pointer}
.aufklapp{font-size:13.5px;color:var(--muted);cursor:pointer}
.b.kein-interesse{background:#F1E2DF;color:var(--red)}
/* Zwei-Faktor-Einrichtung */
.codeanzeige{font-size:24px;letter-spacing:.2em;text-align:center}
.qrmitte{text-align:center;margin:4px 0 12px}
.schluesselanzeige{font-family:ui-monospace,Consolas,monospace;font-size:19px;letter-spacing:.06em;
  background:var(--lu-sand);border:1px solid var(--line);border-radius:var(--r-sm);
  padding:12px;text-align:center;word-break:break-all;margin-top:8px}
.qrrahmen{display:inline-block;background:#fff;padding:10px;border:1px solid var(--line);border-radius:var(--r)}

/* Balkenbreite in Prozentschritten. Erzeugt, nicht von Hand gepflegt.
   Klassen statt style="width:..%", weil die Sicherheitsrichtlinie des Servers
   eingebettete Stile verwirft (siehe oben). Die FARBE steht nicht hier: alle
   Balken sind einheitlich amber, nur die Laenge traegt die Aussage. */
.bf--0{width:0%}
.bf--1{width:1%}
.bf--2{width:2%}
.bf--3{width:3%}
.bf--4{width:4%}
.bf--5{width:5%}
.bf--6{width:6%}
.bf--7{width:7%}
.bf--8{width:8%}
.bf--9{width:9%}
.bf--10{width:10%}
.bf--11{width:11%}
.bf--12{width:12%}
.bf--13{width:13%}
.bf--14{width:14%}
.bf--15{width:15%}
.bf--16{width:16%}
.bf--17{width:17%}
.bf--18{width:18%}
.bf--19{width:19%}
.bf--20{width:20%}
.bf--21{width:21%}
.bf--22{width:22%}
.bf--23{width:23%}
.bf--24{width:24%}
.bf--25{width:25%}
.bf--26{width:26%}
.bf--27{width:27%}
.bf--28{width:28%}
.bf--29{width:29%}
.bf--30{width:30%}
.bf--31{width:31%}
.bf--32{width:32%}
.bf--33{width:33%}
.bf--34{width:34%}
.bf--35{width:35%}
.bf--36{width:36%}
.bf--37{width:37%}
.bf--38{width:38%}
.bf--39{width:39%}
.bf--40{width:40%}
.bf--41{width:41%}
.bf--42{width:42%}
.bf--43{width:43%}
.bf--44{width:44%}
.bf--45{width:45%}
.bf--46{width:46%}
.bf--47{width:47%}
.bf--48{width:48%}
.bf--49{width:49%}
.bf--50{width:50%}
.bf--51{width:51%}
.bf--52{width:52%}
.bf--53{width:53%}
.bf--54{width:54%}
.bf--55{width:55%}
.bf--56{width:56%}
.bf--57{width:57%}
.bf--58{width:58%}
.bf--59{width:59%}
.bf--60{width:60%}
.bf--61{width:61%}
.bf--62{width:62%}
.bf--63{width:63%}
.bf--64{width:64%}
.bf--65{width:65%}
.bf--66{width:66%}
.bf--67{width:67%}
.bf--68{width:68%}
.bf--69{width:69%}
.bf--70{width:70%}
.bf--71{width:71%}
.bf--72{width:72%}
.bf--73{width:73%}
.bf--74{width:74%}
.bf--75{width:75%}
.bf--76{width:76%}
.bf--77{width:77%}
.bf--78{width:78%}
.bf--79{width:79%}
.bf--80{width:80%}
.bf--81{width:81%}
.bf--82{width:82%}
.bf--83{width:83%}
.bf--84{width:84%}
.bf--85{width:85%}
.bf--86{width:86%}
.bf--87{width:87%}
.bf--88{width:88%}
.bf--89{width:89%}
.bf--90{width:90%}
.bf--91{width:91%}
.bf--92{width:92%}
.bf--93{width:93%}
.bf--94{width:94%}
.bf--95{width:95%}
.bf--96{width:96%}
.bf--97{width:97%}
.bf--98{width:98%}
.bf--99{width:99%}
.bf--100{width:100%}

/* Aktionen am Seitenanfang statt am Ende: der haeufigste naechste Schritt
   soll nicht hinter der Liste stehen. */
.kopfaktionen{display:flex;gap:9px;flex-wrap:wrap;margin:0 0 18px}
.kopfaktionen .btn{margin-top:0;flex:1 1 240px}

.stats{display:grid;grid-template-columns:1fr 1fr;gap:9px;margin-bottom:16px}
/* Fuenf gleichwertige Filterkacheln. auto-fit statt fester Spaltenzahl, damit
   sie auf dem Telefon zu zweit und auf dem Schreibtisch nebeneinander stehen,
   ohne dass eine einzelne allein in der letzten Zeile haengt. */
.stats--fuenf{grid-template-columns:repeat(auto-fit, minmax(140px, 1fr))}
/* Notiz vom Besuch. Steht unter der Adresse und ist bewusst als Zitat gesetzt -
   sie stammt vom Aussendienst und ist keine Angabe des Werkzeugs. */
.notiz{margin-top:8px;padding:8px 11px;border-left:3px solid var(--lu-amber);
  background:var(--lu-sand);border-radius:0 var(--r-sm) var(--r-sm) 0;
  font-size:13px;line-height:1.45;color:var(--lu-black);white-space:pre-wrap}
/* Die ausgewaehlte Filterkachel bleibt weiss und wird nur umrandet. Amber ist
   auf dem Dashboard fuer die Hauptkennzahl vergeben - dieselbe Farbe hier fuer
   "ausgewaehlt" haette zwei Bedeutungen gehabt. */
.stat.aktiv{border-color:var(--lu-black);box-shadow:inset 0 0 0 1px var(--lu-black)}
.stat.aktiv .l{color:var(--lu-black);font-weight:500}
/* Ein Ziel der naechsten Tour: Nummer, Name, Ort, Ankunft - eine Zeile, ein
   Klick zur Firma. Auf dem Telefon rutschen Ort und Zeit in die zweite Zeile. */
.tourziel{display:flex;align-items:baseline;gap:9px;flex-wrap:wrap;
  padding:10px 2px;border-bottom:1px solid var(--line);text-decoration:none;color:inherit}
.tourziel:last-of-type{border-bottom:0}
.tz-nr{flex:0 0 auto;min-width:22px;height:22px;border-radius:50%;background:#EDEBE5;
  display:inline-grid;place-items:center;font-size:11.5px;font-weight:600}
.tz-name{font-weight:500;font-size:15px}
.tz-ort{color:var(--muted);font-size:13px;flex:1}
.tz-zeit{font-weight:500;font-size:13.5px;white-space:nowrap}
.nurmeine{display:inline-flex;align-items:center;gap:6px;font-size:13.5px;color:var(--muted);white-space:nowrap}
.nurmeine input{width:17px;height:17px}
.stat{background:var(--lu-white);border:1px solid var(--line);border-radius:var(--r);padding:13px}
.stat .n{font-size:30px;font-weight:300;line-height:1}
.stat .l{font-size:12px;color:var(--muted);margin-top:5px}
/* Hervorgehobene Kennzahl in lumafy Amber. Schrift bleibt schwarz -
   Schwarz auf Amber traegt den Kontrast, Weiss auf Amber nicht. */
.stat.acc{background:var(--lu-amber);border-color:var(--lu-amber);color:var(--lu-black)}
.stat.acc .l{color:rgba(12,12,12,.68)}
.bar{display:flex;align-items:center;gap:10px;padding:8px 0;font-size:14px;
  color:inherit;text-decoration:none;border-radius:var(--r-sm)}
.bar .bn{width:140px;flex:0 0 auto;font-size:13.5px}
.bar .bb{flex:1;height:10px;border-radius:99px;background:#E7E5DF;overflow:hidden}
/* display:block ist zwingend. .bf ist ein <span>, also von Haus aus ein
   Inline-Element - und bei Inline-Elementen wirken width und height nicht.
   Die Balkenfuellung war deshalb IMMER 0 px breit, obwohl im Attribut
   width:100% stand. Am 24.08.2026 im Browser nachgemessen. */
/* display:block ist zwingend: .bf ist ein <span>, und bei Inline-Elementen
   wirken width und height nicht.
   Einheitlich lumafy Amber - wie in einem gewoehnlichen Saeulendiagramm sagt
   allein die Laenge etwas aus. Ein Farbverlauf zusaetzlich zur Laenge wiederholt
   nur dieselbe Angabe ein zweites Mal. */
.bar .bf{display:block;height:100%;border-radius:99px;background:var(--lu-amber)}
.bar .bv{width:28px;text-align:right;font-weight:500;font-size:13.5px}
/* Traegt der Wert einen BETRAG, reichen die 28 px einer blossen Anzahl nicht.
   Gefunden am 14.09.2026 im Trichter des Dashboards: aus "0 · 0,00 €" wurden
   drei Zeilen - "0 ·", "0,00", "€" - und die Zeile war dreimal so hoch wie die
   daneben. Die 28 px bleiben fuer die reinen Zaehlbalken (Pipeline,
   Vertriebsauswertung), wo sie die Zahlen sauber untereinander halten. */
.bar .bv--geld{width:auto;min-width:104px;white-space:nowrap}
/* Auf schmalen Geraeten ist fuer Name, Balken und Betrag nebeneinander kein
   Platz. Dann steht der Balken in einer zweiten Zeile - lieber umbrechen als
   den Betrag zerlegen. */
@media (max-width:520px){
  .bar:has(.bv--geld){flex-wrap:wrap}
  .bar:has(.bv--geld) .bn{width:auto;flex:1 1 auto}
  .bar:has(.bv--geld) .bb{flex:1 0 100%;order:3}
}
/* Anklickbare Zeilen und Kacheln fuehren auf die Liste hinter der Zahl. */
.bar--verweis{margin:0 -8px;padding-left:8px;padding-right:8px}
.stat--verweis,.kv--verweis{text-decoration:none;color:inherit}
.stat--verweis{display:block}
.kv--verweis .v{text-decoration:underline;text-decoration-color:var(--line);text-underline-offset:3px}
/* Untere Menueleiste.
   env(safe-area-inset-bottom) ist zwingend: auf Telefonen mit Gestenbalken
   reicht der Bildschirm unter den Balken. Eine Leiste mit bottom:0 liegt dann
   teilweise darunter, und die unterste Zeile - Symbol und Beschriftung - wird
   angeschnitten. Der Plus-Knopf hatte diese Angabe bereits, die Leiste nicht;
   der Unterschied war der Fehler.
   Die Symbole bekommen ausserdem eine eigene Zeilenhoehe. Ohne sie schneidet
   die Zeile bei Zeichen mit Ober- oder Unterlaengen (◉ ⇢ ▦) die Ecken ab. */
.tabbar{position:fixed;bottom:0;left:50%;transform:translateX(-50%);width:100%;max-width:480px;background:var(--lu-white);
  border-top:1px solid var(--line);display:flex;z-index:5;
  padding:9px 6px calc(12px + env(safe-area-inset-bottom, 0px))}
.tabbar a{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:3px;
  text-align:center;color:var(--muted);font-size:11px;font-weight:500;padding:6px 2px;
  text-decoration:none;min-height:52px;border-radius:var(--r-sm)}
.tabbar a .ic{display:block;font-size:21px;line-height:1.15;opacity:.6}
.tabbar a.on{color:var(--lu-black)} .tabbar a.on .ic{opacity:1}
/* Zweite Navigationsebene innerhalb eines Bereichs.
   Sie scrollt waagerecht und unterliegt deshalb keiner Zeichengrenze - anders
   als die untere Leiste, die sich fuenf Eintraege teilt. */
.unter{display:flex;gap:6px;overflow-x:auto;-webkit-overflow-scrolling:touch;
  margin:0 0 14px;padding:2px 0 6px;scrollbar-width:none}
.unter::-webkit-scrollbar{display:none}
.unter a{flex:0 0 auto;padding:8px 14px;border-radius:99px;font-size:13.5px;font-weight:500;
  background:var(--lu-white);border:1px solid var(--line);color:var(--muted);text-decoration:none;white-space:nowrap}
.unter a.on{background:var(--lu-black);border-color:var(--lu-black);color:var(--lu-white)}
/* Schnellanlage: ein Knopf zum Anlegen unter der zweiten Ebene je Bereich, und
   derselbe Knopf auf Firmenseite und Firmensuche (entscheidungen/0022).
   Rechtsbündig und klein - er soll auffallen, aber nicht die Seite übernehmen. */
.schnellanlage{display:flex;justify-content:flex-end;gap:8px;flex-wrap:wrap;margin:0 0 14px}
.schnellanlage a,.schnellanlage button{display:inline-block;padding:9px 16px;border-radius:99px;border:0;
  background:var(--lu-amber);color:var(--lu-black);font:inherit;font-size:14px;font-weight:600;
  text-decoration:none;white-space:nowrap;cursor:pointer}
.card .schnellanlage{margin:10px 0 0}
/* .dhead zieht sich mit margin-top:-16px an die zweite Ebene heran. Steht der
   Knopf dazwischen, ueberdeckte der Kopf ihn (gemessen 15.09.2026, 375 px: 2 px).
   Und unter dem Kopf (Firmenseite) klebte der Knopf ohne Abstand an der Kante. */
.schnellanlage + .dhead{margin-top:0}
/* Dasselbe direkt nach der zweiten Ebene: seit die Firmenseite zu Akquise gehoert
   (15.09.2026), steht dort die Reiterleiste vor dem Kopf. Am Schreibtisch
   (margin:-22px) ueberdeckte er die Reiter um 2 px. */
.unter + .dhead{margin-top:0}
.dhead + .schnellanlage{margin-top:12px}
/* Beschriftung der Reiter.
   Sechs Reiter teilen sich auf einem 390 px breiten Telefon rund 59 px je
   Eintrag. "Interessenten" ist mit 13 Zeichen der laengste Eintrag und passt
   dort bei 11 px nicht mehr in eine Zeile. Statt die Leiste umbrechen oder
   ueberlaufen zu lassen, wird die Schrift kleiner; im aeussersten Fall wird
   abgeschnitten. Die Leiste bleibt damit unter allen Umstaenden einzeilig. */
.tabbar a{min-width:0}
.tabbar .tb{display:block;max-width:100%;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
  font-size:10px;letter-spacing:-.2px}
/* Ueberlauf der Leiste (entscheidungen/0016-acht-bereiche.md).
   Acht Bereiche ergeben 41 px je Eintrag - das traegt sechs Zeichen, und kein
   Bereichsname ist so kurz. Auf dem Telefon stehen deshalb nur die vier
   Eintraege aus LEISTE plus "Mehr"; die uebrigen tragen .nurbreit und erscheinen
   erst in der Seitenspalte am Schreibtisch, wo es keine Zeichengrenze gibt.
   Dort wiederum entfaellt "Mehr" - alle acht stehen untereinander. */
.tabbar a.nurbreit{display:none}
/* „Aktion" (entscheidungen/0023, 15.09.2026): EIN Eintrag der Leiste fuer Akquise,
   Angebote, Auftraege und Abrechnung. Ein Tipp oeffnet die Auswahl nach oben.
   <details> statt Skript - oeffnet und schliesst auch ohne JavaScript.
   Die Leiste ist position:fixed mit transform und damit Bezugsrahmen der Auswahl:
   bottom:100% setzt sie direkt ueber die Leiste. */
.tabbar .aktion{flex:1;display:flex;min-width:0}
.tabbar .aktion > summary{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:3px;
  text-align:center;color:var(--muted);font-size:11px;font-weight:500;padding:6px 2px;min-height:52px;
  border-radius:var(--r-sm);list-style:none;cursor:pointer;min-width:0}
.tabbar .aktion > summary::-webkit-details-marker{display:none}
.tabbar .aktion > summary .ic{display:block;font-size:21px;line-height:1.15;opacity:.6}
.tabbar .aktion > summary.on,.tabbar .aktion[open] > summary{color:var(--lu-black)}
.tabbar .aktion > summary.on .ic,.tabbar .aktion[open] > summary .ic{opacity:1}
.aktion-auswahl{position:absolute;left:6px;right:6px;bottom:100%;margin-bottom:8px;display:flex;flex-direction:column;
  gap:2px;background:var(--lu-white);border:1px solid var(--line);border-radius:var(--r);padding:6px;
  box-shadow:0 -8px 24px rgba(12,12,12,.18)}
.tabbar .aktion-auswahl a{flex:0 0 auto;flex-direction:row;justify-content:flex-start;gap:12px;min-height:48px;
  padding:10px 14px;color:var(--lu-black)}
.tabbar .aktion-auswahl .tb{font-size:15px;letter-spacing:0}
.tabbar .aktion-auswahl a .ic{font-size:18px;opacity:1}
.tabbar .aktion-auswahl a.on{background:var(--lu-sand)}
/* Der schwebende Plus-Knopf („Neue Opportunity") ist am 15.09.2026 auf Vorgabe
   entfallen: neben dem Anlegeknopf je Bereich (.schnellanlage) standen sonst zwei
   „+" mit verschiedener Bedeutung. Eine Opportunity entsteht über die Firmenseite. */
.offline{display:none;position:fixed;top:0;left:50%;transform:translateX(-50%);width:100%;max-width:480px;
  background:var(--red);color:#fff;text-align:center;font-size:13px;padding:7px;z-index:20}
body.is-offline .offline{display:block}
table.tbl{width:100%;border-collapse:collapse;font-size:13.5px}
table.tbl th,table.tbl td{text-align:left;padding:7px 6px;border-bottom:1px solid var(--line)}
.scroll-x{overflow-x:auto}

/* =========================================================================
   Schreibtisch. Ab 900 px wird die Breite genutzt, statt eine schmale Spalte
   in der Bildschirmmitte stehen zu lassen. Gleiche Seiten, gleicher Code -
   nur ein anderes Raster.
   ========================================================================= */
@media (min-width: 900px) {
  body { background: #D9D7D1; }
  .frame {
    max-width: 1180px;
    display: grid;
    grid-template-columns: 210px 1fr;
    grid-template-rows: auto auto 1fr;
    grid-template-areas: "top top" "flash flash" "nav main";
    align-items: start;
    min-height: 100vh;
  }
  .topbar { grid-area: top; padding: 14px 24px; }
  .wordmark { font-size: 23px; }
  /* NUR der Hinweis des Rahmens. Die Einschraenkung auf das direkte Kind ist
     nicht kosmetisch, sondern traegt die Seite:

     ACHTUNG, gefunden am 14.09.2026 auf /rechnungen. Hier stand ".flash".
     "grid-area: flash" benennt eine Rasterlinie, die es NUR im .frame gibt.
     Steht ein Hinweiskasten im Seiteninhalt - und das tun 22 Stueck, etwa der
     Riegelhinweis ueber der Rechnungsliste - dann ist er ein Kind von
     main.screens. Dort gibt es keine Linie "flash", also legt der Browser
     stillschweigend implizite Spalten an. Aus "1fr 1fr 1fr" wurden
     "4px 4px 4px 240px 814px": Ueberschrift, Unterzeile und Liste quetschten
     sich in 40 px und brachen buchstabenweise um. Kein Fehler im Umbruch,
     sondern eine Regel, die eine Ebene zu weit greift. */
  .frame > .flash { grid-area: flash; margin: 14px 24px 0; }

  /* Aus der unteren Leiste wird eine Seitenspalte. */
  .tabbar {
    grid-area: nav; position: static; transform: none; width: auto; max-width: none;
    display: flex; flex-direction: column; gap: 4px;
    border-top: 0; border-right: 1px solid var(--line);
    background: transparent; padding: 22px 14px 22px 18px; align-self: stretch;
  }
  .tabbar a {
    display: flex; align-items: center; gap: 10px; text-align: left;
    padding: 11px 13px; border-radius: var(--r-sm); font-size: 14.5px; flex: 0 0 auto;
  }
  .tabbar a .ic { display: inline; font-size: 17px; margin: 0; }
  .tabbar .tb { font-size: 14.5px; letter-spacing: 0; overflow: visible; }
  .tabbar a.on { background: var(--lu-white); border: 1px solid var(--line); }
  .tabbar a:hover { background: rgba(255,255,255,.6); }
  .tabbar a.nurbreit { display: flex; }
  /* Am Schreibtisch keine Aktion-Auswahl: die Seitenspalte traegt alle Bereiche einzeln. */
  .tabbar .aktion { display: none; }
  .tabbar a.nurschmal { display: none; }

  .screens { grid-area: main; padding: 22px 24px 40px; }

  /* Listen zweispaltig, Überschriften laufen über die volle Breite.
     align-items:start ist wichtig: ohne die Angabe zieht das Raster jede Flaeche
     auf die Hoehe der hoechsten in derselben Zeile. Auf der Firmenseite stand
     "Kontakte" dadurch als halb leerer weisser Kasten da. */
  .screens { display: grid; grid-template-columns: 1fr 1fr; gap: 0 14px;
             align-content: start; align-items: start; }
  .screens > h1, .screens > .sub, .screens > h2, .screens > form,
  .screens > .dhead, .screens > .chain, .screens > .empty,
  .screens > .stats, .screens > .chips, .screens > details, .screens > .kopfaktionen,
  .screens > .unter, .screens > .schnellanlage,
  /* Ein Hinweiskasten im Seiteninhalt gehoert ueber die ganze Breite - er sagt
     etwas ueber die ganze Seite, nicht ueber eine Spalte.
     Bewusst KEIN "grid-area: auto" daneben: grid-area ist die Kurzform und
     wuerde das grid-column dieser Regel gleich wieder zuruecksetzen. */
  .screens > .flash, .screens > .hint,
  .screens > .actions, .screens > .scroll-x, .screens > p { grid-column: 1 / -1; }
  .screens > .card { margin-bottom: 12px; }
  .screens > .btn { grid-column: 1 / -1; max-width: 320px; }

  /* Auf der Detailseite stehen Arbeitsbereich und Historie nebeneinander. */
  .screens > .block { margin-top: 0; margin-bottom: 14px; }

  .dhead { margin: -22px -24px 16px; padding: 22px 24px; border-radius: 0 0 var(--r) var(--r); }
  .dhead h1 { font-size: 30px; }
  .chain { margin: 0 0 16px; border-radius: var(--r); }

  /* Anmeldung und Bestaetigung haben keine Navigation: dort kein Raster mit
     Seitenspalte, sondern eine schmale Karte in der Mitte. */
  .frame--gast { display: block; max-width: 520px; min-height: auto; margin-top: 8vh;
                 border-radius: var(--r); overflow: hidden; align-self: flex-start; }
  .frame--gast .screens { display: block; padding: 26px 26px 34px; }
  .frame--gast .field input { max-width: none; }
  .stats { grid-template-columns: repeat(4, 1fr); }
  h1 { font-size: 32px; }
  .search { max-width: 560px; }
  .field input, .field select, .field textarea { max-width: 560px; }
  .checks { max-width: 700px; }
  .kv { font-size: 14px; }
}

@media (min-width: 1300px) {
  .frame { max-width: 1400px; grid-template-columns: 230px 1fr; }
  .screens { grid-template-columns: 1fr 1fr 1fr; }
}

/* Seiten, bei denen die Reihenfolge der Karten eine Aussage ist (Tourstopps),
   duerfen nicht in Spalten umbrechen - sonst liest man Stopp 1,3,5 / 2,4,6.
   ACHTUNG REIHENFOLGE: Diese Regel muss NACH den Bloecken oben stehen. Stand
   sie davor, gewann bei 1300 px die Dreispaltigkeit (gleiche Spezifitaet,
   spaeter im Text) - am 24.08.2026 im Browser sichtbar geworden. */
/* Dashboard: jeder Abschnitt ist eine eigene Flaeche und damit ein Rasterfeld.
   Vorher lief jede Ueberschrift ueber die volle Breite und erzwang nach jedem
   Block eine neue Zeile - rechts blieb dadurch eine leere Spalte stehen.
   grid-auto-flow:dense fuellt Luecken mit spaeteren, kuerzeren Abschnitten. */
.panel{margin-bottom:14px}
.panel > h2:first-child{margin-top:0}
.panel .block{margin-top:0}

@media (min-width: 900px) {
  .screens--dicht{grid-auto-flow:dense;align-items:start;gap:0 14px}
  .screens--folge { grid-template-columns: 1fr; max-width: 760px; }
  /* In der schmalen Lesespalte darf die Kopfflaeche nicht mehr ueber die
     Seitenraender hinauslaufen - sie endete sonst mitten auf der Seite und
     sah aus wie abgeschnitten. Hier wird sie zur Karte. */
  .screens--folge > .dhead { margin: 0 0 16px; border-radius: var(--r); }
}

/* Zeigegeräte: Zustände sichtbar machen, die es auf dem Telefon nicht gibt. */
@media (hover: hover) {
  .card { transition: border-color .12s, box-shadow .12s; }
  .card:hover { border-color: #CFCCC5; box-shadow: 0 2px 10px rgba(12,12,12,.06); }
  .btn:hover, .quick button:hover, .quick a:hover, .chip:hover,
  .mini:hover:not([disabled]), .kachel:hover, .tourwahl:hover { filter: brightness(.97); }
  .bar--verweis:hover { background: #EDEBE5; }
  .tourziel:hover { background: #F3F1EC; }
  .stat--verweis:hover { border-color: #CFCCC5; }
  .kv--verweis:hover .v { text-decoration-color: var(--lu-black); }
  .kachel:hover, .tourwahl:hover { border-color: #CFCCC5; }
  .mini:hover:not([disabled]) { border-color: #CFCCC5; }
  a:focus-visible, button:focus-visible, input:focus-visible, select:focus-visible, textarea:focus-visible {
    outline: 2px solid var(--lu-amber); outline-offset: 2px;
  }
}

/* Tourplanung: erledigte Stopps treten zurueck, ohne zu verschwinden. */
.card.erledigt { opacity: .62; }
.card.erledigt .nm { text-decoration: line-through; }
.card.schon-da { background: #F7F6F2; }
/* Bereits fuer eine Tour eingeplant. Ohne diesen Hinweis plant man beim
   Durchgehen einer langen Liste dieselbe Firma ein zweites Mal ein - einem
   Namen sieht man nicht an, ob er schon vergeben ist. */
.card.geplant { border-color: #B7D6C3; }
/* Die Kachel selbst sagt, dass und wann eingeplant ist - das spart die
   zusaetzliche Marke in der Kopfzeile und haelt die Karte kompakt. */
.kachel.gruen { background: #DCEDE3; border-color: #A9CFBA; color: var(--green); font-weight: 600; }
/* Ein Potenzial hat drei Wege: Interesse, Kein Interesse, Zur Tour. Die ersten
   beiden stehen nebeneinander (sie schliessen einander aus), die Tour laeuft
   darunter ueber die volle Breite - sie traegt zusaetzlich das Datum. */
.kachel.weit { grid-column: 1 / -1; }
.card.schon-da .nm { color: var(--muted); }
.card.schon-da .nm { color: var(--muted); }

/* Aktionsleiste einer Karte.
   Diese Regeln fehlten. Folge: Navigation/Besucht/Nicht da/Entfernen wurden als
   nackte Textzeilen untereinander gezeichnet - am 24.08.2026 im Browser belegt.
   Ohne Grundregel greift button{border:0;background:none} aus Zeile 31. */
.cardactions{display:flex;flex-wrap:wrap;gap:6px;align-items:center;
  padding:10px 12px 12px;border-top:1px solid var(--line);background:#FBFAF7}
.cardactions form{display:inline-flex;margin:0}
.mini{display:inline-flex;align-items:center;justify-content:center;white-space:nowrap;
  min-height:38px;padding:0 13px;font-size:13px;font-weight:500;border-radius:99px;
  background:var(--lu-white);border:1px solid var(--line);color:inherit;text-decoration:none}
.mini.amber{background:var(--lu-amber);border-color:var(--lu-amber)}
.mini.warn{color:var(--red)}
.cardactions .mini[disabled]{opacity:.35;cursor:default}

/* Vier gleiche Kacheln, zwei in jeder Reihe.
   Vorher waren es je nach Zustand drei bis fuenf verschieden breite Knoepfe,
   sodass keine Karte aussah wie die andere. Jetzt hat jede Karte dieselben
   vier Flaechen an denselben Stellen - man trifft sie blind. */
.kacheln{display:grid;grid-template-columns:1fr 1fr;gap:6px;
  padding:10px 12px 12px;border-top:1px solid var(--line);background:#FBFAF7}
.kacheln form{display:contents}
.kachel{display:flex;align-items:center;justify-content:center;text-align:center;
  width:100%;min-height:44px;padding:6px 10px;font-size:13px;font-weight:500;line-height:1.2;
  border-radius:var(--r-sm);background:var(--lu-white);border:1px solid var(--line);
  color:inherit;text-decoration:none}
.kachel.amber{background:var(--lu-amber);border-color:var(--lu-amber)}
/* Der bereits gesetzte Zustand wird gezeigt, nicht versteckt - sonst wandern
   die uebrigen Kacheln bei jedem Klick an eine andere Stelle. */
.kachel.an{background:var(--lu-black);color:#fff;border-color:var(--lu-black)}
/* Der Kartenverweis aendert nichts an der Firma - er ist deshalb kein Zustands-
   knopf, sondern eine schmale Zeile ueber beide Spalten unter den Kacheln. */
.kachelzeile{grid-column:1 / -1;display:block;text-align:center;padding:8px 0 2px;
  font-size:13px;color:var(--muted);text-decoration:none}
.kachelzeile:hover{color:var(--lu-black);text-decoration:underline}

/* Auswahl einer vorhandenen Tour: ganze Zeile als Flaeche, Datum links. */
.tourwahl{display:flex;align-items:center;justify-content:space-between;gap:12px;
  width:100%;min-height:52px;padding:10px 13px;margin-bottom:7px;text-align:left;
  border-radius:var(--r-sm);background:var(--lu-white);border:1px solid var(--line)}
.tourwahl .tw-tag{font-weight:500;font-size:15px}
.tourwahl .tw-info{color:var(--muted);font-size:13px}

/* Textspalte einer Aktivitaetszeile - ohne min-width:0 sprengen lange
   Notizen ohne Leerzeichen die Karte. */
.tx{flex:1;min-width:0}
.tx .nn{overflow-wrap:anywhere}

/* Stammdaten -> Einstellungen: Vorschau des Firmenlogos (Umbauplan Phase 0). */
.logovorschau { display: block; max-width: 240px; max-height: 96px; background: #FFFFFF; border: 1px solid rgba(0,0,0,.08); border-radius: 8px; padding: 8px; }
