/* =========================================================================
   NEXUP Workspace - design system (aligned with the NEXUP Studio brand)
   ========================================================================= */

/* Montserrat - lokal gebuendelt, dieselben vier Schnitte wie nexup.studio.
   Der 300er-Schnitt ist am 27.08.2026 raus: er war geladen, aber keine einzige Regel
   hat ihn je angefordert, und auf der Website gibt es ihn nicht. */
@font-face { font-family:"Montserrat"; src:url("assets/fonts/montserrat-400.woff2") format("woff2"); font-weight:400; font-style:normal; font-display:swap; }
@font-face { font-family:"Montserrat"; src:url("assets/fonts/montserrat-500.woff2") format("woff2"); font-weight:500; font-style:normal; font-display:swap; }
@font-face { font-family:"Montserrat"; src:url("assets/fonts/montserrat-600.woff2") format("woff2"); font-weight:600; font-style:normal; font-display:swap; }
@font-face { font-family:"Montserrat"; src:url("assets/fonts/montserrat-700.woff2") format("woff2"); font-weight:700; font-style:normal; font-display:swap; }

:root {
  /* Hoehenleiter: FUENF Stufen, weil die App genau fuenf Flaechen benutzt.
     Bis zum 23.08.2026 liefen hier zwei Systeme nebeneinander: --bg/--bg-elev/--surface/
     --surface-2/--surface-3 mit 78 Verwendungen und daneben eine 2026 eingefuehrte
     --e0..--e3-Leiter mit ganzen fuenf. Zwei Namen fuer dieselbe Sache sind schlimmer als
     einer, deshalb ist die Leiter jetzt die einzige Wahrheit - mit denselben Werten wie
     vorher, also ohne jede sichtbare Aenderung. Die alten Namen bleiben als Verweis
     stehen, damit nichts bricht; neue Regeln benutzen --e0 bis --e4.
     Dieselbe Lehre wie bei den Abstaenden: passt die Leiter nicht zur Sache, war die
     Leiter falsch - nicht die Sache. */
  /* 27.08.2026: Die Leiter stand auf einem NEUTRALEN Grauton, die Website auf einem
     BLAUEN. Nebeneinander gehalten sah die App neben nexup.studio kalt-grau aus, die
     Website tiefblau - derselbe Eindruck wie zwei Fotos mit verschiedenem Weissabgleich.
     Die ersten drei Stufen sind jetzt Zeichen fuer Zeichen die der Website
     (--grund / --grund-2 / --grund-3), die beiden oberen setzen dieselbe Rampe fort. */
  --e0:          #070a10;   /* Grund, Seitenhintergrund      = Website --grund   */
  --e1:          #0a0f17;   /* leicht abgehoben: Leiste      = Website --grund-2 */
  --e2:          #0e141e;   /* Panel, Karte, Zeile           = Website --grund-3 */
  --e3:          #141c28;   /* angehoben im Panel: Hover, Eingabe */
  --e4:          #1e2836;   /* Schwebendes: Dialog, Menue, Chip */
  --hairline:    rgba(255,255,255,.07);

  /* Alte Namen, nur noch Verweise. Nicht mehr in neuen Regeln benutzen. */
  --bg:          var(--e0);
  --bg-elev:     var(--e1);
  --surface:     var(--e2);
  --surface-2:   var(--e3);
  --surface-3:   var(--e4);

  /* Linien - die zwei Stufen der Website (--linie / --linie-2) */
  --border:        rgba(255,255,255,.10);
  --border-strong: rgba(255,255,255,.20);

  /* Tinte - Zeichen fuer Zeichen die der Website.
     Wichtig: die Tinte ist nicht reines Weiss, sondern leicht blau gebrochen
     (#eef3f9). Reines Weiss auf blauem Grund liest sich haerter und war der
     zweite Grund, warum die App neben der Website "anders" wirkte.
     Die leiseste Stufe stand auf .40 und damit unter dem Lesbarkeitswert; die
     Website hat sie aus genau dem Grund auf .52 gehoben (5,13:1 auf dem Grund). */
  --text:       #eef3f9;
  --text-muted: rgba(238,243,249,.68);
  --text-faint: rgba(238,243,249,.52);

  /* Markenblau - Licht, keine Farbflaeche. Die drei Stufen der Website. */
  --accent:      #3d77bb;   /* Website --blau      */
  --accent-2:    #7fb2ee;   /* Website --blau-hell: Links, aktive Symbole, Akzentwort */
  --accent-deep: #24518a;   /* Website --blau-tief: untere Haelfte der Knopfverlaeufe */
  --accent-ink:  #ffffff;
  /* Die Website paart bei jeder blauen Markierung eine MITTELBLAUE FLAECHE mit
     einem HELLBLAUEN RING - so markiert sie den aktuellen Punkt in der Leiste
     (`rgba(61,119,187,.2)` innen, `rgba(127,178,238,.3)` als Ring). Die App
     nahm fuer beides dasselbe mittlere Blau; der Ring verschwand dadurch fast
     in seiner eigenen Fuellung. Und die Fuellung stand auf .16 statt .2 -
     wieder so ein Wert, den man einzeln nicht sieht und im Vergleich schon. */
  --accent-soft: rgba(61,119,187,.2);
  --accent-line: rgba(127,178,238,.34);

  /* Statusfarben. Sie muessen sich vom Markenblau unterscheiden - eine Rechnung
     ist ueberfaellig oder bezahlt, das darf nicht nach "Akzent" aussehen.
     ABER sie muessen aus demselben Haus kommen.
     Bis zum 27.08.2026 standen hier die Farben der GitHub-Palette. Nachgemessen:
     die Markenblaus liegen in einem engen Band (Saettigung 51 bis 77 Prozent),
     die Statusfarben streuten von 14 bis 93 - Violett mit 89 und Rot mit 93
     waren gesaettigter als alles, was die Marke je benutzt. Nebeneinander liest
     man das nicht als Bedeutung, sondern als zweite Palette.
     Jetzt: Farbton bleibt (die Bedeutung haengt daran), Saettigung und Helligkeit
     sind ins Band gezogen. Grau bleibt bewusst neutral, es ist die Abwesenheit
     von Status. Alle Werte gegen den Grund geprueft, der schwaechste liegt bei
     5,3:1 auf einer Karte - ueber der Schwelle von 4,5 fuer kleinen Text. */
  --st-lead:     #8d99b0;   /* Anfrage: neutral, blaugrau       S 18 */
  --st-proposal: #a685e0;   /* Angebot                          S 60 */
  --st-active:   #36c6d3;   /* laeuft                           S 64 */
  --st-waiting:  #d69651;   /* wartet auf Kunde                 S 62 */
  --st-done:     #4cc25c;   /* fertig / bezahlt                 S 49 */
  --danger:      #e45f58;   /* ueberfaellig / Fehler            S 72 */
  /* Die gedaempften Flaechen werden aus der Farbe ABGELEITET, nicht daneben
     geschrieben. Vorher stand jede Toenung als eigenes rgba() da und konnte
     beim naechsten Farbwechsel stehen bleiben - genau das war bei
     rgba(90,147,214,.15) im Postfach passiert. */
  --danger-soft: color-mix(in srgb, var(--danger) 14%, transparent);

  /* Radien - die drei der Website plus die kleinste Marke.
     27.08.2026: Die App stand auf 8 / 14, die Website auf 10 / 16 / 24. Zwei Pixel
     Unterschied sieht niemand einzeln, nebeneinander liest sich die App dadurch
     aber spitzer und die Website weicher. Jetzt dieselbe Leiter:
       --r-sm  = Website --r-klein  (Bedienelemente, Chips, Eingaben)
       --r-md  = Website --r-mittel (Karten, Zeilen, Kacheln)
       --r-lg  = Website --r-gross  (Panels, Dialoge, alles mit Glaskante)
     --r-card und --r-ctrl bleiben als Namen bestehen und zeigen auf die Stufen. */
  --r-xs:   4px;   /* kleine Marken, Fortschrittsbalken */
  --r-sm:  10px;   /* Bedienelemente, Chips, Eingaben     = Website --r-klein  */
  --r-md:  16px;   /* Karten, Kacheln, Zeilen             = Website --r-mittel */
  --r-lg:  24px;   /* Panels, Dialoge, Glasflaechen       = Website --r-gross  */
  --r-pill: 999px;
  --r-card: var(--r-md);
  --r-ctrl: var(--r-sm);

  /* Spacing (4pt). Die Zwischenstufen tragen eine halbe Nummer und liegen jeweils
     genau zwischen ihren Nachbarn: 0-5 zwischen nichts und s1, 1-5 zwischen s1 und s2,
     2-5 zwischen s2 und s3, 4-5 zwischen s4 und s5. Sie sind am 23.08.2026 dazugekommen,
     weil die App dicht gebaut ist und der Sprung von 4 auf 8 auf 12 dafuer zu grob war:
     6, 10, 2 und 20 px standen 182-mal NEBEN der Leiter statt darauf. Nichts hat sich
     dabei optisch geaendert, die Werte wurden nur benannt.
     Neue Abstaende gehoeren auf diese zwoelf Stufen. Wer einen dreizehnten Wert braucht,
     hat entweder ein Layoutproblem oder einen guten Grund - dann hier eintragen. */
  --s0-5:2px; --s1:4px; --s1-5:6px; --s2:8px; --s2-5:10px; --s3:12px;
  --s4:16px; --s4-5:20px; --s5:24px; --s6:32px; --s7:48px; --s8:64px;

  /* Typoleiter: sieben Stufen statt zwanzig. 11,5 gegen 12 gegen 12,5 sieht niemand,
     erzeugt aber ein System, das nicht zusammengehoert. Der GEDRUCKTE BELEG ist bewusst
     ausgenommen: seine Groessen sind in mm/pt vermessen und einzeln abgesichert. */
  --t-1: 10px;    /* Marken, Tabellenkoepfe, Versalien */
  --t-2: 11.5px;  /* Unterzeilen, Meta */
  --t-3: 12.5px;  /* Hinweise, sekundaerer Text */
  --t-4: 13.5px;  /* Standard: Zeilentitel, Fliesstext */
  --t-5: 15px;    /* Panel- und Kartenueberschriften */
  --t-6: 20px;    /* Ansichtstitel */
  --t-7: 30px;    /* Leitzahlen */

  /* Laufweite in drei Stufen, gebunden an die GROESSE: je groesser, desto enger.
     Genau die Regel der Website. Vorher lief --track-tighter mit -.032em enger als
     alles andere und wurde ausgerechnet auf 30px-Zahlen gelegt - also enger als die
     groesste Ueberschrift der Website. Das ist die Leiter andersherum. */
  --ls-display: -.02em;    /* --t-7, Leitzahlen */
  --ls-h2:      -.012em;   /* --t-6, Ansichtstitel */
  --ls-h3:      -.01em;    /* --t-5 und darunter */
  /* Und zwei POSITIVE Stufen fuer Versalien. Kleinschrift in Grossbuchstaben
     braucht Luft, sonst wird sie zum Block - aber sie braucht EINE Menge Luft,
     nicht fuenf. Am 27.08.2026 standen in der App .04em, .05em, .06em, .07em
     und .16em nebeneinander, und zwar fuer dieselbe Sache: ein Etikett in
     Versalien. Zwei Tabellenkoepfe mit .04 und .05 untereinander liest niemand
     als Absicht. Beide Werte kommen von der Website:
       --ls-versal = .07em  (Schlagwoerter dort; hier alle Tabellen- und
                             Gruppenkoepfe, weil sie in Reihen stehen)
       --ls-micro  = .16em  (das freistehende Kleinstetikett, dort ueber den
                             drei direkten Wegen)
     Alles andere ist 0. Es gibt keine dritte positive Stufe. */
  --ls-versal:  .07em;
  --ls-micro:   .16em;
  /* Alte Namen, nur noch Verweise auf die Leiter. */
  --track-tight:   var(--ls-h2);
  --track-tighter: var(--ls-display);

  /* Zeilenhoehe in vier Stufen. Vorher vierzehn Werte zwischen 1 und 1,7 -
     der Unterschied zwischen 1,5 und 1,55 ist unsichtbar, das Nebeneinander
     von vierzehn Werten ist es nicht: es macht aus einem System eine Sammlung.
     Die Website kommt mit drei Ueberschriftsstufen und 1,65 im Fliesstext aus.
       --lh-eng    grosse Grade und Leitzahlen (Website --lh-karte)
       --lh-titel  Zeilen- und Kartentitel     (Website --lh-klein)
       --lh-text   Standard in der Flaeche
       --lh-lesen  Text, den man wirklich liest (Website-Fliesstext)
     Der Wert 1 bleibt erlaubt, wo Text kein Zeilenband haben darf: in
     Knoepfen, Marken und Kreisen. */
  --lh-eng:   1.12;
  --lh-titel: 1.25;
  --lh-text:  1.5;
  --lh-lesen: 1.65;

  /* Schatten - dieselbe Staffel wie die Glasscheiben der Website:
     eine harte Nahkante, ein weiter, sehr weicher Wurf. */
  --sh-1: 0 2px 6px rgba(0,0,0,.36);
  --sh-2: 0 30px 60px -40px rgba(0,0,0,.95);
  --sh-3: 0 44px 90px -54px rgba(0,0,0,.95);

  --font: "Montserrat",system-ui,-apple-system,"Segoe UI","Helvetica Neue",Arial,sans-serif;
  --font-display: "Montserrat",system-ui,-apple-system,"Segoe UI",sans-serif;
  /* KEINE zweite Schrift. Bis zum 27.08.2026 lief hier Cascadia Code fuer Betraege,
     Belegnummern und den Wiederherstellungsschluessel - eine Fremdschrift in einem
     Produkt, dessen Identitaet "Montserrat allein" ist, und auf dem Mac ausserdem gar
     nicht vorhanden (es fiel still auf Menlo zurueck). Montserrat hat echte
     Tabellenziffern; die Spaltenordnung kommt jetzt von `font-variant-numeric`,
     nicht von einer anderen Schrift.
     Der Schluessel ist damit nicht mehrdeutig: sein Alphabet (RC_ALPHA) enthaelt
     weder I noch L noch O noch U. */
  --font-zahl: var(--font);
  --font-mono: var(--font-zahl);   /* alter Name, nur noch Verweis */

  /* Kurven und Dauern der Website. --ease stand auf (.23,1,.32,1) und lief damit
     merklich anders aus als jede Bewegung auf nexup.studio. */
  /* ZWEI Kurven, wie die Website. Ein --spring mit Ueberschwung
     (cubic-bezier(.34,1.4,.5,1)) stand hier bis zum 27.08.2026 und war die
     einzige Bewegung im ganzen Haus, die zurueckfedert - auf nexup.studio
     federt nichts. Raus. */
  --ease:   cubic-bezier(.16,1,.3,1);
  --ease-2: cubic-bezier(.22,.61,.36,1);
  /* VIER Dauern, und keine daneben. Vorher lagen in styles.css 57 rohe Werte
     in zwoelf Abstufungen (.1 .12 .14 .15 .16 .18 .2 .25 .3 .4 .5 s). Kein
     Mensch sieht den Unterschied zwischen 120 und 140 Millisekunden - aber
     man spuert, dass zwei Dinge, die gleich aussehen, verschieden schnell
     reagieren. Genau daran erkennt man ein zusammengesetztes System.
       --d-druck    was sofort da sein muss (Druck, Zellenhover)
       --d-schnell  Farbe, Flaeche, Rand, Deckkraft - alles, was nur ANDERS
                    AUSSIEHT (auf der Website: der Hover in der Leiste)
       --d-mittel   Verschiebung, Skalierung, Schatten - alles, was etwas
                    BEWEGT (auf der Website: der Knopf, der sich anhebt)
       --d-lang     Flaechen, die auffahren oder sich fuellen (Blatt, Balken)
     Wer eine fuenfte Dauer braucht, hat meistens die falsche der vier. */
  --d-druck:   110ms;
  --d-schnell: 220ms;
  --d-mittel:  340ms;
  --d-lang:    520ms;
  --spring: var(--ease);   /* alter Name, nur noch Verweis */
  /* EINE Steuerhoehe. Am 27.08.2026 nachgemessen: Knoepfe, Symbolknoepfe,
     Umschalter, Sortierwahl, Eingabefelder und Navigationspunkte standen auf
     SIEBEN verschiedenen Hoehen (27, 28, 30, 34, 36, 38, 40 px) - und in der
     Kopfzeile standen vier davon nebeneinander in einer Reihe. Das ist die
     sichtbarste Art von Unordnung, weil man die Kanten direkt vergleicht.
     36px, weil der Navigationspunkt schon dort stand und weil bei 13,5px
     Schrift darunter nichts mehr bequem anzutippen ist.
     `--sm` macht einen Knopf jetzt SCHMALER und die Schrift kleiner, nicht
     niedriger: eine zweite Hoehe waere genau der Fehler noch einmal. */
  --h-ctrl: 36px;
  --sidebar-w: 244px;
  /* Hoechstbreite des Inhalts: Seitenspalte (244) plus Arbeitsflaeche (1360).
     Das Mesh liest diesen Wert und dunkelt alles ausserhalb davon ab - genau wie
     auf der Website, wo --wrap dieselbe Aufgabe hat. Wer .view breiter macht,
     zieht diese Zahl mit, sonst rahmt das Netz die falsche Kante. */
  --wrap: 1604px;
}

* { box-sizing: border-box; }
html, body { height: 100%; }
body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font);
  font-size: var(--t-5);
  line-height: var(--lh-text);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
/* Markierter Text stand auf --accent-soft, also einem 16-Prozent-Hauch. Auf dem
   dunklen Grund war eine Auswahl damit fast nicht zu sehen - man markierte und
   sah nicht, was. Die Website setzt volles Blau mit weisser Schrift. */
::selection { background: var(--accent); color: #fff; }

/* Dreiecks-Mesh - animiertes Markenzeichen hinter der ganzen App */
.bg-mesh { position: fixed; inset: 0; z-index: 0; width: 100%; height: 100%; pointer-events: none; }
/* Beim Login die App ausblenden -> hinter dem Overlay liegt nur das Mesh (Muster sichtbar + privat) */
body.is-locked .app { visibility: hidden; }

/* ---- Lichthoefe ----------------------------------------------------------
   27.08.2026. Der eine Grund, warum die App neben nexup.studio flach wirkte,
   obwohl ihre Panels bereits Glas waren: hinter dem Glas stand kein Licht.
   Die Website legt vier grosse, sehr weiche blaue Hoefe hinter ihre Scheiben,
   und erst daran bricht sich das Material. Ohne sie ist jede Glasflaeche auf
   dunklem Grund nur eine dunkle Karte - im CSS der Website steht der Satz
   woertlich so.
   Hier liegen sie fest im Fenster statt im Dokument, weil die App in einer
   Flaeche scrollt und nicht als Seite. Sie stehen als Verlaufsschichten EINES
   Elements, damit kein zusaetzliches Markup noetig ist; die Reihenfolge ist
   die des CSS: die erste Schicht liegt oben.
   Die Vignette ganz unten ist deutlich schwaecher als vorher (.55 -> .38): die
   Randabdunklung uebernimmt jetzt zum groesseren Teil das Mesh selbst, so wie
   auf der Website. Zwei Abdunklungen uebereinander frassen den Hoefen genau
   die Raender weg, an denen sie sitzen. */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  background:
    /* oben rechts, das Hauptlicht  (Website .glut--a) */
    radial-gradient(circle 620px at 100% -6%,  rgba(61,119,187,.28), rgba(61,119,187,.07) 42%, transparent 68%),
    /* breite Kuppe ueber der Leiste (Website .glut--e) */
    radial-gradient(ellipse 120vw 62vh at 50% -20%, rgba(61,119,187,.20), rgba(36,81,138,.08) 46%, transparent 72%),
    /* links auf halber Hoehe        (Website .glut--c) */
    radial-gradient(circle 580px at -6% 58%,   rgba(61,119,187,.17), transparent 64%),
    /* rechts unten                  (Website .glut--d) */
    radial-gradient(circle 540px at 106% 84%,  rgba(36,81,138,.20), transparent 64%),
    /* Vignette, damit die Leiste lesbar bleibt */
    radial-gradient(120% 100% at 50% 52%, transparent 58%, rgba(3,5,8,.38) 100%);
  pointer-events: none;
  z-index: 1;
}

/* ---- Korn ----------------------------------------------------------------
   Die Website legt ueber alles eine feine Rauschschicht. Sie ist der
   Unterschied zwischen "flaches Schwarz" und "Material" und kostet einen
   einzigen zusammengesetzten Layer. In der App fehlte sie ganz.
   Liegt ueber allem, auch ueber Dialogen - genau wie auf der Website, wo sie
   ueber dem gesamten Inhalt liegt. Nur auf einem FESTEN Element, nie auf einer
   scrollenden Flaeche: sonst wandert das Korn mit dem Inhalt und wird sichtbar
   als Muster statt als Oberflaeche. */
body::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 300;
  pointer-events: none;
  opacity: .055;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.82' numOctaves='3'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* Laufweite haengt an der GROESSE, nicht am Element. Vorher trug jede Ueberschrift
   -.02em, also der Ansichtstitel mit 20px dieselbe Enge wie eine Leitzahl mit 30px -
   und eine 15px-Panelueberschrift ebenfalls. Bei 15px liest sich -.02em gequetscht.
   Grundwert ist jetzt die unterste Stufe; die groesseren Grade holen sich ihre
   eigene Stufe da, wo sie gesetzt werden. */
h1,h2,h3,h4 { font-family: var(--font-display); margin: 0; letter-spacing: var(--ls-h3); font-weight: 600; }
button { font-family: inherit; }
a { color: inherit; }

/* Scrollbars */
* { scrollbar-width: thin; scrollbar-color: var(--e4) transparent; }
*::-webkit-scrollbar { width: 10px; height: 10px; }
*::-webkit-scrollbar-thumb { background: var(--e4); border-radius: var(--r-pill); border: 3px solid transparent; background-clip: padding-box; }

/* ========================= App shell ========================= */
.app {
  position: relative;
  z-index: 2;
  display: grid;
  grid-template-columns: var(--sidebar-w) 1fr;
  min-height: 100dvh;
}

/* ------- Sidebar ------- */
.sidebar {
  position: sticky;
  top: 0;
  height: 100dvh;
  display: flex;
  flex-direction: column;
  gap: var(--s2);
  padding: var(--s5) var(--s3) var(--s4);
  /* Die Leiste der Website, sobald sie beim Scrollen "fest" wird: derselbe
     Verlauf in 158 Grad, dieselbe dichtere Fuellung, dieselbe Lichtkante.
     Seitenspalte und Topleiste sind in einer App IMMER fest - sie stehen nie
     ueber freiem Grund - deshalb tragen sie hier gleich die dichte Fassung. */
  background:
    linear-gradient(158deg, rgba(255,255,255,.085), rgba(255,255,255,.022) 46%, rgba(255,255,255,.05)),
    rgba(9,14,22,.82);
  -webkit-backdrop-filter: blur(22px) saturate(150%);
  backdrop-filter: blur(22px) saturate(150%);
  border-right: 1px solid var(--border);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.2), 1px 0 60px -40px rgba(0,0,0,.95);
}
.brand { display: flex; align-items: center; gap: var(--s3); padding: 0 var(--s2) var(--s5); }
.brand__mark { color: var(--text); display: grid; place-items: center; }
.brand__mark svg { width: 28px; height: 28px; }
.brand__mark .b { fill: var(--accent); }
.brand__mark polygon:not(.b) { fill: currentColor; }
.brand__text { display: flex; flex-direction: column; line-height: var(--lh-eng); min-width: 0; }
.brand__name { font-family: var(--font-display); font-weight: 700; font-size: var(--t-5); letter-spacing: var(--ls-h3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.brand__sub { font-size: var(--t-2); color: var(--text-faint); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.nav { display: flex; flex-direction: column; gap: var(--s0-5); }
.nav__item {
  display: flex; align-items: center; gap: var(--s3);
  width: 100%; padding: 9px var(--s3);
  background: transparent; border: 0; border-radius: var(--r-pill);
  color: rgba(238,243,249,.80); font-size: var(--t-4); font-weight: 500;
  cursor: pointer; text-align: left;
  transition: background var(--d-schnell) var(--ease), color var(--d-schnell) var(--ease);
}
/* Die Website faerbt den Punkt beim Zeigen nur weiss auf einer weissen Flaeche
   und markiert die aktuelle Stelle blau mit blauem Ring (.nav a.hier). Vorher
   sah in der App der Hover fast aus wie der aktive Punkt: beides blau, beides
   gerahmt - man konnte nicht sehen, wo man IST, nur wohin man zeigt. */
.nav__item:hover { background: rgba(255,255,255,.07); color: var(--text); }
.nav__item:hover .nav__ico { color: var(--text); }
.nav__item.is-active { background: rgba(61,119,187,.2); color: var(--text); box-shadow: inset 0 0 0 1px rgba(127,178,238,.3); }
.nav__item.is-active .nav__ico { color: var(--accent-2); }
.nav__ico { display: inline-grid; place-items: center; width: 18px; height: 18px; color: var(--text-faint); flex: none; }
.nav__ico svg { width: 18px; height: 18px; }
.nav__count { margin-left: auto; font-size: var(--t-3); color: var(--text-faint); font-variant-numeric: tabular-nums; }
.nav__item.is-active .nav__count { color: var(--text-muted); }

.sidebar__foot { margin-top: auto; display: flex; flex-direction: column; gap: var(--s3); }
.backup { display: flex; align-items: center; gap: var(--s2); padding: var(--s2) var(--s3); font-size: var(--t-2); color: var(--text-faint); border-top: 1px solid var(--border); }
.backup__dot { width: 7px; height: 7px; border-radius: var(--r-pill); background: var(--text-faint); flex: none; }
.backup__dot.is-on { background: var(--st-done); box-shadow: 0 0 0 3px color-mix(in srgb, var(--st-done) 15%, transparent); }
.backup__label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ------- Main ------- */
.main { display: flex; flex-direction: column; min-width: 0; }
.topbar {
  position: sticky; top: 0; z-index: 20;
  display: flex; align-items: center; gap: var(--s4);
  padding: var(--s4) var(--s6);
  background:
    linear-gradient(158deg, rgba(255,255,255,.085), rgba(255,255,255,.022) 46%, rgba(255,255,255,.05)),
    rgba(9,14,22,.82);
  -webkit-backdrop-filter: blur(22px) saturate(150%);
  backdrop-filter: blur(22px) saturate(150%);
  border-bottom: 1px solid var(--border);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.2), 0 2px 8px rgba(0,0,0,.42), 0 30px 60px -40px rgba(0,0,0,.95);
}
.topbar__title { min-width: 0; }
.topbar__title h1 { font-family: var(--font-display); font-size: var(--t-6); font-weight: 700; letter-spacing: var(--ls-h2); }
.topbar__sub { margin: var(--s0-5) 0 0; font-size: var(--t-3); color: var(--text-faint); }
.topbar__actions { display: flex; gap: var(--s2); align-items: center; }

/* Hier sass bis zum 27.08.2026 der Hell/Dunkel-Regler samt kreisfoermiger
   Ueberblendung (View Transitions API). Beides ist raus: das Aussehen ist
   dunkel, ohne Wahl - so wie nexup.studio. Im Git steht es vollstaendig. */
.topbar__menu { display: none; }

.view { flex: 1; padding: var(--s6); max-width: 1360px; width: 100%; }

/* ========================= Buttons ========================= */
/* Der Knopf ist auf der Website `.tat`. Uebernommen sind Verlaufsrichtung,
   Farben, Lichtkante, Wurf und die Bewegung; NICHT die Groesse - die Website
   setzt 14/26 Polster bei 15px Schrift, das ist ein Knopf fuer eine Seite mit
   vier Knoepfen, nicht fuer eine Werkzeugleiste mit sieben. */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--s2);
  height: var(--h-ctrl); padding: 0 var(--s4); border-radius: var(--r-pill);
  border: 1px solid var(--border-strong); background: rgba(255,255,255,.045);
  color: var(--text); font-size: var(--t-4); font-weight: 600; line-height: 1;
  cursor: pointer; white-space: nowrap;
  transition: background var(--d-schnell) var(--ease), transform var(--d-mittel) var(--ease), box-shadow var(--d-mittel) var(--ease), filter var(--d-schnell) var(--ease);
}
@media (hover: hover) { .btn:hover { background: rgba(255,255,255,.08); } }
/* Der Druck ist auf der Website .97 und dauert --d-druck. Vorher .95 in .18s:
   ein anderer Weg und eine andere Zeit fuer dieselbe Geste. */
.btn:active { transform: scale(.97); transition-duration: var(--d-druck); }
/* Grundgroesse fuer jedes Symbol. Steht bewusst VOR den Sonderfaellen, damit .btn svg,
   .icon-btn svg und .panel__head h2 svg sie weiter ueberschreiben koennen. */
.ico { width: 1em; height: 1em; flex: 0 0 auto; }
.btn svg { width: 16px; height: 16px; }
/* Der Verlauf lief senkrecht von #4a83c6 nach #3d77bb. Beides zu hell: weisse
   Schrift auf #4a83c6 kommt auf 3,54:1 und verfehlt die 4,5:1. Die Website hat
   denselben Fehler am 26.08. behoben und steht seitdem auf #3a72b4 -> #26527f
   (4,99:1 an der hellsten Stelle, und das haelt auch im Hover). */
.btn--primary {
  background: linear-gradient(150deg, #3a72b4, #26527f); color: #fff; font-weight: 600; border-color: transparent;
  box-shadow: inset 0 1px 0 rgba(255,255,255,.34), 0 10px 26px -14px rgba(61,119,187,.9);
}
@media (hover: hover) {
  .btn--primary:hover {
    transform: translateY(-2px); filter: brightness(1.06);
    box-shadow: inset 0 1px 0 rgba(255,255,255,.4), 0 18px 40px -16px rgba(61,119,187,.95);
  }
}
/* Website `.tat--still`: nur ein Ring, keine Flaeche. */
.btn--ghost { background: transparent; border-color: var(--border); box-shadow: none; color: var(--text-muted); }
@media (hover: hover) { .btn--ghost:hover { color: var(--text); background: rgba(255,255,255,.06); filter: none; } }
.btn--danger { color: var(--danger); border-color: var(--danger-soft); background: transparent; }
.btn--danger:hover { background: var(--danger-soft); }
.btn--sm { padding: 0 var(--s3); font-size: var(--t-3); }
/* Der Ring lief auf --accent (#3d77bb). Das ist das MITTLERE Blau, und auf dem
   dunklen Grund ist es der schlechteste der drei Werte fuer eine Umrandung:
   dunkel gegen dunkel. Die Website nimmt dafuer --blau-hell, und zwar als
   EINE Auffangregel fuer alles, was Fokus bekommen kann - nicht als Liste
   einzelner Bauteile, die man beim naechsten neuen Knopf vergisst.
   Genau das ist hier vorher passiert: Regeln gab es fuer .btn, .nav__item,
   .icon-btn, .theme-switch und .switch, fuer alles andere nichts. */
:focus-visible { outline: 2px solid var(--accent-2); outline-offset: 3px; border-radius: 4px; }
.btn:focus-visible, .nav__item:focus-visible, .icon-btn:focus-visible { outline-offset: 3px; }
/* Auffangregel: alles, was per Tastatur angesteuert werden kann, zeigt das auch. Vorher
   gab es Fokusringe nur fuer Knoepfe und Navigation; Zeilen, Karten und Kanban-Karten
   waren ab dem 23.08.2026 zwar erreichbar, aber unsichtbar fokussiert - ein Fokus, den
   man nicht sieht, ist keiner. `outline-offset` negativ, damit der Ring bei Zeilen
   innerhalb der Trennlinie bleibt und die Liste nicht springt. */
/* Zeilen und Karten: der Ring liegt INNEN, damit die Liste beim Fokus nicht
   springt. Farbe und Staerke kommen aus der Auffangregel darueber. */
[tabindex="0"]:focus-visible { outline-offset: -2px; border-radius: var(--r-sm); }

.icon-btn {
  display: inline-grid; place-items: center; width: var(--h-ctrl); height: var(--h-ctrl);
  border-radius: var(--r-ctrl); border: 1px solid var(--border);
  background: var(--e3); color: var(--text-muted); cursor: pointer;
  transition: background var(--d-schnell) var(--ease), color var(--d-schnell) var(--ease);
}
.icon-btn:hover { background: var(--e4); color: var(--text); }
.icon-btn svg { width: 17px; height: 17px; }

/* ========================= Cards / panels ========================= */
/* ---- DAS GLAS ------------------------------------------------------------
   Das ist das Material, das nexup.studio traegt, und ab dem 27.08.2026 Zeichen
   fuer Zeichen dasselbe hier. Die App hatte vorher eine eigene, schwaechere
   Fassung davon: 155 statt 158 Grad, zwei Verlaufsmarken statt drei, 14 statt
   22 Pixel Unschaerfe, eine Lichtkante bei .06 statt .16 und nur einen einzigen
   Wurfschatten statt der zwei Staffeln. Jeder Wert fuer sich unsichtbar,
   zusammen der Unterschied zwischen "dunkle Karte" und "Scheibe".

   Vier Dinge machen die Scheibe aus, kein dekoratives Blur:
     1. drei Verlaufsmarken - die dritte holt das Licht am unteren Rand zurueck
     2. Unschaerfe MIT Saettigung, sonst wird alles dahinter grau
     3. eine harte Lichtkante oben (inset 0 1px 0)
     4. zwei Schatten: eine Nahkante und ein sehr weiter, weicher Wurf

   `.glas` ist der Name der Website und steht hier als eigene Klasse zur
   Verfuegung; alles, was in der App eine Scheibe sein soll, haengt sich hier
   an, statt die Werte noch einmal abzuschreiben. */
.glas,
.panel {
  position: relative; isolation: isolate;
  background:
    linear-gradient(158deg, rgba(255,255,255,.072), rgba(255,255,255,.018) 46%, rgba(255,255,255,.042)),
    rgba(12,18,27,.58);
  -webkit-backdrop-filter: blur(22px) saturate(150%);
  backdrop-filter: blur(22px) saturate(150%);
  border: 1px solid transparent;
  border-radius: var(--r-lg);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.16),
    0 2px 6px rgba(0,0,0,.36),
    0 44px 90px -54px rgba(0,0,0,.95);
}
/* Die Glaskante: ein Verlauf im Rand selbst, hell oben-links, blau unten-rechts.
   Nur die AEUSSEREN Behaelter tragen sie. Auf Kacheln und Karten ergaben sich
   damit neun gerahmte Flaechen auf einem Bildschirm, und der Rahmen hoerte auf,
   etwas zu bedeuten. */
.glas::before,
.panel::before, .modal::before {
  content: ""; position: absolute; inset: 0; border-radius: inherit; padding: 1px;
  background: linear-gradient(152deg, rgba(255,255,255,.42), rgba(255,255,255,.05) 44%, rgba(127,178,238,.32));
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor; mask-composite: exclude;
  pointer-events: none; z-index: 2;
}
/* Zeigerlicht: die Scheibe faengt das Licht dort, wo der Zeiger steht.
   Auf der Website heisst das .glas--licht und liegt auf Angebotskarten und
   Fragen. In der App bekommen es die Flaechen, die man wirklich anfasst.
   Nur bei echtem Zeiger - am Finger gibt es keine Position zu leuchten. */
/* Dieselbe Liste steht in app.js als GLAS_LICHT. Wer hier etwas ergaenzt,
   ergaenzt es dort mit. */
.glas--licht::after,
.stat::after, .ccard::after, .pcard::after {
  content: ""; position: absolute; inset: 0; border-radius: inherit;
  pointer-events: none; z-index: 1;
  background: radial-gradient(280px circle at var(--mx,50%) var(--my,0%), rgba(127,178,238,.16), transparent 70%);
  opacity: 0; transition: opacity var(--d-mittel) var(--ease);
}
@media (hover: hover) {
  .glas--licht:hover::after,
  .stat:hover::after, .ccard:hover::after, .pcard:hover::after { opacity: 1; }
}
.panel__head { display: flex; align-items: center; gap: var(--s3); padding: var(--s4) var(--s5); border-bottom: 1px solid var(--border); }
/* Ein Symbol in einer Ueberschrift hatte keine Groesse: das SVG streckte sich auf
   ueber 90 px, fuellte die halbe Kopfzeile und schob den Titel darunter. Betraf drei
   Panels. Die Regel hier deckelt es ein fuer alle Mal, egal wo jemand eins einsetzt. */
.panel__head h2 { font-size: var(--t-5); font-weight: 600; display: flex; align-items: center; gap: var(--s2); min-width: 0; }
.panel__head h2 svg { width: 17px; height: 17px; flex: 0 0 auto; color: var(--text-faint); }
.panel__head .panel__act { margin-left: auto; }
.panel__body { padding: var(--s5); }

/* ========================= Dashboard ========================= */
.stat-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--s4); margin-bottom: var(--s5); }
/* Eine Leitzahl fuehrt, drei ordnen sich unter. Die enge Laufweite macht die grosse
   Zahl kompakt statt gespreizt - das ist der Unterschied, den man nicht benennt,
   aber sieht. */
.stat-grid--lead { grid-template-columns: 1.55fr 1fr 1fr 1fr; align-items: stretch; }
.stat.stat--lead {
  background: linear-gradient(158deg, var(--accent-soft), rgba(61,119,187,.03) 62%), var(--e1);
  border-color: var(--accent-line);
  display: flex; flex-direction: column; justify-content: space-between;
}
.stat__value.stat__value--lead { font-size: var(--t-7); letter-spacing: var(--track-tighter); }
.stat__foot { margin-top: var(--s4); }
/* Monatsverlauf auf dem Dashboard. Bewusst Balken statt Linie: bei zwoelf Monaten mit
   teils leeren Monaten liest sich eine Linie als durchgehender Verlauf, den es nicht gibt.
   Leere Monate bleiben als Haarlinie stehen, damit die Luecke sichtbar ist statt geglaettet. */
.mchart { display: flex; align-items: flex-end; gap: var(--s1-5); height: 96px; margin-bottom: var(--s4); }
.mchart__col { flex: 1; display: flex; flex-direction: column; justify-content: flex-end; align-items: stretch; gap: var(--s1-5); height: 100%; min-width: 0; }
.mchart__bar { height: var(--h, 0%); min-height: 2px; background: var(--accent-line); border-radius: var(--r-xs) var(--r-xs) 0 0; transition: height var(--d-lang) var(--ease); }
.mchart__bar.is-now { background: var(--accent-2); }
.mchart__bar.is-leer { background: var(--hairline); }
.mchart__lbl { font-size: var(--t-1); color: var(--text-faint); text-align: center; letter-spacing: var(--ls-versal); }
.kv--tight { margin-top: 0; }

/* Kacheln und "Jetzt dran" liegen in einer Spalte, damit sie am Handy die Reihenfolge
   tauschen koennen. Am Schreibtisch bleibt es bei Kacheln zuerst: die vier passen dort
   in eine Reihe und stehen dem Handeln nicht im Weg. */
.dash-top { display: flex; flex-direction: column; }
/* Was zu tun ist und wie der Umsatz laeuft, nebeneinander statt untereinander.
   Gleich breit: gaebe man der Liste die breitere Spalte, bliebe Text das
   Beherrschende - und genau das war die Kritik. */
.dash-puls { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s5); align-items: start; margin-bottom: var(--s5); }
.dash-puls > .panel { margin-bottom: 0; }
@media (max-width: 1100px) { .dash-puls { grid-template-columns: minmax(0, 1fr); } }
@media (max-width: 720px) {
  /* Die Reihe loest sich auf, damit ihre beiden Kinder direkt in .dash-top haengen
     und einzeln sortierbar werden. Sonst koennte nur die ganze Reihe vor die
     Kacheln wandern - mitsamt der Kurve, die dort niemand zuerst braucht. */
  .dash-puls { display: contents; }
  .dash-top .focus { order: -1; }
  .dash-puls > .panel { margin-bottom: var(--s5); }
}

/* ===================== "Jetzt dran" ===================== */
/* Eine Zeile pro Sache, mit dem Grund darunter. Der Farbstreifen links traegt die
   Dringlichkeit, das Wort im Grund traegt die Bedeutung - Farbe allein sagt nichts.
   Die Stufen heissen bewusst `fokus-row--bad/-warn/-info` und nicht `is-bad/is-warn/
   is-info`: `.is-info` gibt es in dieser Datei schon global mit `text-align: right`.
   Beim ersten Versuch lief die letzte Zeile deshalb rechtsbuendig. Kurze Zustandsnamen
   wie `is-info` gehoeren niemandem allein - Modifikator immer an den Bauteilnamen haengen. */
.focus { margin-bottom: var(--s5); }
.focus__zahl { font-size: var(--t-3); color: var(--text-faint); font-variant-numeric: tabular-nums; }
.focus__zahl .is-over { color: var(--danger); }
.focus__mehr { padding: var(--s2-5) var(--s5) var(--s3); font-size: var(--t-3); color: var(--text-faint); border-top: 1px solid var(--hairline); }
.focus--leer .panel__body { color: var(--text-muted); font-size: var(--t-4); }

.fokus-row {
  display: flex; align-items: center; gap: var(--s3);
  padding: var(--s2-5) var(--s5); border-bottom: 1px solid var(--hairline);
  cursor: pointer; position: relative;
  transition: background var(--d-schnell) var(--ease);
}
.fokus-row:last-child { border-bottom: 0; }
.fokus-row::before {
  content: ""; position: absolute; left: 0; top: 6px; bottom: 6px; width: 3px;
  border-radius: 0 var(--r-xs) var(--r-xs) 0; background: var(--text-faint);
}
.fokus-row--bad::before  { background: var(--danger); }
.fokus-row--warn::before { background: var(--st-waiting); }
.fokus-row--info::before { background: var(--accent); }
.fokus-row:hover { background: var(--accent-soft); }
.fokus-row__ico { flex: 0 0 auto; display: grid; place-items: center; width: 28px; height: 28px; border-radius: var(--r-sm); background: var(--e3); color: var(--text-faint); }
.fokus-row--bad .fokus-row__ico  { color: var(--danger); }
.fokus-row--warn .fokus-row__ico { color: var(--st-waiting); }
.fokus-row__ico svg { width: 15px; height: 15px; }
.fokus-row__main { min-width: 0; flex: 1; }
.fokus-row__titel { font-size: var(--t-4); font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fokus-row__grund { font-size: var(--t-2); color: var(--text-faint); margin-top: 1px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fokus-row__pfeil { flex: 0 0 auto; color: var(--text-faint); opacity: 0; transition: opacity var(--d-schnell) var(--ease); }
.fokus-row__pfeil svg { width: 15px; height: 15px; }
.fokus-row:hover .fokus-row__pfeil, .fokus-row:focus-visible .fokus-row__pfeil { opacity: 1; }
@media (max-width: 720px) {
  .fokus-row { padding-left: var(--s4); padding-right: var(--s4); }
  .fokus-row__pfeil { display: none; }
}

.spark { display: flex; align-items: flex-end; gap: 3px; height: 30px; margin-bottom: var(--s2); }
.spark i { flex: 1; height: var(--h, 0%); min-height: 2px; background: var(--accent-line); border-radius: var(--r-xs) var(--r-xs) 0 0; }
.spark i.is-leer { background: var(--hairline); }
.spark i.is-now { background: var(--accent-2); }
@media (max-width: 1080px) { .stat-grid--lead { grid-template-columns: repeat(2, 1fr); } .stat--lead { grid-column: span 2; } }
@media (max-width: 480px) { .stat-grid--lead { grid-template-columns: 1fr; } .stat--lead { grid-column: span 1; } }
/* Kacheln sind dieselbe Scheibe wie die Panels, nur ohne Glaskante: sie stehen
   zu viert nebeneinander, und vier Rahmen in einer Reihe sind ein Zaun. */
.stat {
  position: relative; overflow: hidden; isolation: isolate;
  padding: var(--s4) var(--s5);
  background:
    linear-gradient(158deg, rgba(255,255,255,.072), rgba(255,255,255,.018) 46%, rgba(255,255,255,.042)),
    rgba(12,18,27,.58);
  -webkit-backdrop-filter: blur(22px) saturate(150%);
  backdrop-filter: blur(22px) saturate(150%);
  border: 1px solid transparent; border-radius: var(--r-md);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.16),
    0 2px 6px rgba(0,0,0,.36),
    0 44px 90px -54px rgba(0,0,0,.95);
}
/* Hier sass bis zum 27.08.2026 ein statischer blauer Eckhof auf jeder Kachel.
   Zwei Gruende, warum er raus ist: die Website hat nichts dergleichen (ihre
   Karten bekommen ihr Licht von den Hoefen HINTER dem Glas, nicht aus sich
   selbst), und er belegte genau das ::after, das jetzt das Zeigerlicht traegt.
   Vier Kacheln mit je einem eigenen Leuchtpunkt lasen sich ausserdem als vier
   Warnungen. */
.stat__label { font-size: var(--t-3); color: var(--text-muted); display:flex; align-items:center; gap:var(--s1-5); }
.stat__label svg { width: 15px; height: 15px; opacity: .8; }
.stat__value { font-family: var(--font-display); font-size: var(--t-6); font-weight: 700; letter-spacing: var(--track-tight); margin-top: var(--s1-5); font-variant-numeric: tabular-nums; line-height: 1; }
.stat__meta { font-size: var(--t-3); color: var(--text-faint); margin-top: var(--s1-5); }
.stat--danger .stat__value { color: var(--danger); }
/* Warnt in der Zusatzzeile statt in der grossen Zahl: nicht der Gesamtbetrag ist
   das Problem, sondern der ueberfaellige Anteil davon. */
.stat--warn .stat__meta { color: var(--danger); font-weight: 600; }
.stat--warn { border-color: var(--danger-soft); }

/* minmax(0, …) statt blossem fr: eine Grid-Spalte hat sonst min-width:auto und
   waechst mit ihrem breitesten Inhalt, statt ihn umbrechen zu lassen. Genau daran
   lief die Seite ueber, als die Aufgabenzeile zwei Knoepfe mehr bekam. */
.dash-grid { display: grid; grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr); gap: var(--s5); align-items: start; }

/* ========================= Lists / rows ========================= */
.rowlist { display: flex; flex-direction: column; }
.row {
  display: flex; align-items: center; gap: var(--s4);
  padding: var(--s2) var(--s5) var(--s2) var(--s4);
  border-bottom: 1px solid var(--border);
  cursor: pointer;
  transition: background var(--d-schnell) var(--ease);
}
.row:last-child { border-bottom: 0; }
.row:hover { background: var(--accent-soft); }
.row__main { min-width: 0; flex: 1; }
.row__title { font-size: var(--t-4); font-weight: 600; line-height: var(--lh-titel); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.row__sub { font-size: var(--t-3); color: var(--text-faint); margin-top: 1px; line-height: var(--lh-titel); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.row__aside { display: flex; align-items: center; gap: var(--s3); flex: none; }
/* Werkstatt: Form statt Marke. Der Streifen traegt den Status, die Zahl traegt den
   Fortschritt, der Rest erscheint erst beim Darueberfahren. Zeile von 66 auf 44 px. */
.row { position: relative; padding-left: var(--s4); }
.row__stripe {
  position: absolute; left: 0; top: 8px; bottom: 8px; width: 3px;
  border-radius: var(--r-xs); background: var(--stripe, var(--text-faint));
  flex: 0 0 auto;
}
.row--late .row__stripe { background: var(--danger); }
.row__end { display: flex; flex-direction: column; align-items: flex-end; gap: 1px; flex: none; min-width: 84px; text-align: right; }
.row__pct { font-size: var(--t-4); font-weight: 600; font-variant-numeric: tabular-nums; letter-spacing: var(--track-tight); }
.row__pct--none { color: var(--text-faint); font-weight: 400; font-size: var(--t-2); }
.row__due { font-size: var(--t-2); color: var(--text-faint); white-space: nowrap; }
.row__due--none { opacity: .55; }
.row--late .row__pct, .row--late .row__due { color: var(--danger); }
/* Zusatzangabe, die den Blick sonst nur teilt - beim Darueberfahren ist sie da. */
.row__more { opacity: 0; transition: opacity var(--d-schnell) var(--ease); }
.row:hover .row__more { opacity: 1; }
@media (hover: none) { .row__more { opacity: 1; } }

/* Avatar */
.avatar {
  /* --av kommt vom Element, alles andere aus dem System. Der Schriftgrad folgt einer
     Regel statt einer Rechnung je Aufrufstelle. */
  width: var(--av, 36px); height: var(--av, 36px); border-radius: var(--r-sm); flex: none;
  display: grid; place-items: center; font-weight: 700;
  font-size: calc(var(--av, 36px) * .38);
  background: var(--e4); color: var(--text);
  font-family: var(--font-display);
}


/* HIER STAND EIN FEHLER, gefunden am 27.08.2026 im zweiten Durchgang.
   Am 23.08. wurde entschieden, dass Kacheln und Karten keinen eigenen
   LEUCHTRAND mehr tragen: neun gerahmte Flaechen auf einem Bildschirm, und der
   Rahmen hoert auf, etwas zu bedeuten. Die Entscheidung war richtig. Die
   Umsetzung hat aber nicht den Rand abgeschaltet, sondern das ganze MATERIAL:
   `background: var(--e1); box-shadow: none` auf .stat, .ccard, .pcard, .ncard
   und .kcard.
   Weil diese Regel WEITER UNTEN steht als `.stat`, hat sie dessen Glas
   ueberschrieben - die vier Kennzahlen auf dem Dashboard waren flache Kaesten,
   auch nach dem Umbau vom Vormittag. Bei .ccard und .pcard fiel es nicht auf,
   weil deren eigene Regeln noch weiter unten stehen und wieder gewinnen. Drei
   verschiedene Behandlungen fuer vier Kartenfamilien.
   Die Trennung ist jetzt sauber: das MATERIAL (Verlauf, Unschaerfe, Lichtkante,
   Schatten) tragen alle, die GLASKANTE (der Verlauf im Rand, `::before`) nur
   Panel und Dialog. Damit bleibt die Entscheidung vom 23.08. erhalten und das
   Material trotzdem eines. */
.stat, .ccard, .pcard, .ncard { border: 1px solid transparent; }
.ccard:hover, .pcard:hover, .ncard:hover { border-color: var(--accent-line); }

/* ========================= Progress ========================= */
.progress { --p: 0; height: 6px; border-radius: var(--r-pill); background: var(--e4); overflow: hidden; }
.progress__fill { height: 100%; width: calc(var(--p) * 1%); background: linear-gradient(90deg, var(--accent), var(--accent-2)); border-radius: var(--r-pill); transition: width var(--d-lang) var(--ease); }
.progress--done .progress__fill { background: linear-gradient(90deg, var(--st-done), #57d873); }
.progress-wrap { display: flex; align-items: center; gap: var(--s3); }
.progress-wrap .progress { flex: 1; }
.progress-pct { font-size: var(--t-3); color: var(--text-muted); font-variant-numeric: tabular-nums; min-width: 34px; text-align: right; }

/* ========================= Badges ========================= */
.badge {
  display: inline-flex; align-items: center; gap: var(--s1-5);
  padding: 3px 9px; border-radius: var(--r-pill);
  font-size: var(--t-2); font-weight: 600; white-space: nowrap;
  background: var(--e4); color: var(--text-muted);
  border: 1px solid transparent;
}
.badge__dot { width: 6px; height: 6px; border-radius: var(--r-pill); background: currentColor; }
/* Jede Toenung kommt aus ihrer eigenen Farbe. `.badge--proposal` trug bis zum
   27.08.2026 ein nacktes #a371f7 - das einzige Violett im ganzen Produkt, an
   keiner Marke haengend und deshalb bei jeder Palettenaenderung uebersehen. */
.badge--lead     { color: var(--st-lead);     background: color-mix(in srgb, var(--st-lead) 12%, transparent); }
.badge--proposal { color: var(--st-proposal); background: color-mix(in srgb, var(--st-proposal) 14%, transparent); }
.badge--active   { color: var(--st-active);   background: color-mix(in srgb, var(--st-active) 14%, transparent); }
.badge--waiting  { color: var(--st-waiting);  background: color-mix(in srgb, var(--st-waiting) 14%, transparent); }
.badge--done     { color: var(--st-done);     background: color-mix(in srgb, var(--st-done) 13%, transparent); }
.badge--lost     { color: var(--danger);     background: var(--danger-soft); }
.badge--type    { color: var(--text-muted); background: var(--e3); border-color: var(--border); }
.badge--overdue { color: var(--danger); background: var(--danger-soft); }

/* ========================= Toolbar / filters ========================= */
.toolbar { display: flex; align-items: center; gap: var(--s3); margin-bottom: var(--s5); flex-wrap: wrap; }
.search {
  display: flex; align-items: center; gap: var(--s2);
  height: var(--h-ctrl); padding: 0 13px; border-radius: var(--r-ctrl);
  background: var(--e2); border: 1px solid var(--border); min-width: 240px; flex: 1; max-width: 380px;
}
.search svg { width: 16px; height: 16px; color: var(--text-faint); flex: none; }
.search input { border: 0; background: transparent; color: var(--text); font: inherit; font-size: var(--t-4); width: 100%; min-height: 0; padding: 0; outline: none; }
.search input::placeholder { color: var(--text-faint); }
/* Tastenkuerzel als eigenes Zeichen statt im Platzhalter - der wurde im schmalen
   Topbar-Feld mitten im Text abgeschnitten. Beim Tippen tritt es zurueck. */
.search__key {
  flex: none; min-width: 18px; padding: 1px var(--s1-5); font-size: var(--t-2); line-height: var(--lh-text);
  color: var(--text-faint); background: transparent; border: 1px solid var(--border);
  border-bottom-width: 1px; border-radius: var(--r-xs);
  transition: opacity var(--d-schnell) var(--ease);
}
.search:focus-within .search__key { opacity: 0; }
/* Listenfilter, nicht zu verwechseln mit der globalen Suche oben: Trichter statt Lupe,
   schmaler und ruhiger, damit auf einem Bildschirm nicht zwei gleiche Suchfelder stehen. */
.search--filter { max-width: 300px; min-width: 180px; background: transparent; }
.search--filter input { font-size: var(--t-4); }

/* Sechs Knoepfe passen bei 375 px nicht in 341 px: die letzten wurden abgeschnitten
   und waren nicht mehr erreichbar. Statt sie zu verstecken, schiebbar machen -
   max-width:100% verhindert, dass die Leiste die Werkzeugzeile aufspreizt. */
.segmented { display: inline-flex; align-items: stretch; height: var(--h-ctrl); gap: var(--s0-5); padding: 3px; background: var(--e2); border: 1px solid var(--border); border-radius: var(--r-ctrl); max-width: 100%; overflow-x: auto; scrollbar-width: none; -webkit-overflow-scrolling: touch; }
.segmented::-webkit-scrollbar { display: none; }
.segmented button { flex: 0 0 auto; }
.segmented button {
  padding: 0 var(--s3); border: 0; background: transparent; color: var(--text-muted);
  font-size: var(--t-3); font-weight: 600; border-radius: var(--r-sm); cursor: pointer; white-space: nowrap;
  transition: background var(--d-schnell) var(--ease), color var(--d-schnell) var(--ease);
}
.segmented button:hover { color: var(--text); }
.segmented button.is-active { background: var(--e4); color: var(--text); }

/* ========================= Card grid (customers) ========================= */
.card-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: var(--s4); }
.ccard {
  position: relative; isolation: isolate;
  padding: var(--s5);
  background:
    linear-gradient(158deg, rgba(255,255,255,.072), rgba(255,255,255,.018) 46%, rgba(255,255,255,.042)),
    rgba(12,18,27,.58);
  border: 1px solid transparent;
  -webkit-backdrop-filter: blur(22px) saturate(150%); backdrop-filter: blur(22px) saturate(150%);
  border-radius: var(--r-card); cursor: pointer;
  box-shadow: inset 0 1px 0 rgba(255,255,255,.05);
  transition: transform var(--d-mittel) var(--ease), box-shadow var(--d-mittel) var(--ease), background var(--d-schnell) var(--ease);
}
.ccard:hover { background:
    linear-gradient(158deg, rgba(255,255,255,.10), rgba(255,255,255,.026) 46%, rgba(255,255,255,.06)),
    rgba(16,23,34,.62); transform: translateY(-2px); box-shadow: inset 0 1px 0 rgba(255,255,255,.22), 0 2px 6px rgba(0,0,0,.36), 0 30px 60px -40px rgba(0,0,0,.95); }
.ccard__head { display: flex; align-items: center; gap: var(--s3); margin-bottom: var(--s4); }
.ccard__name { font-size: var(--t-5); font-weight: 600; }
.ccard__company { font-size: var(--t-3); color: var(--text-faint); }
/* Drei gleich breite Spalten statt freiem Fluss: sonst schiebt ein langes
   "vor 9 Tagen" die Karte auf zwei Zeilen und das Raster wird unruhig. */
.ccard__stats { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s3); padding-top: var(--s4); border-top: 1px solid var(--border); }
.ccard__stat { min-width: 0; }
.ccard__stat b { font-family: var(--font-display); font-size: var(--t-5); display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ccard__stat span { font-size: var(--t-1); color: var(--text-faint); display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* ========================= Project cards ========================= */
.pcard {
  position: relative; isolation: isolate;
  padding: var(--s5);
  background:
    linear-gradient(158deg, rgba(255,255,255,.072), rgba(255,255,255,.018) 46%, rgba(255,255,255,.042)),
    rgba(12,18,27,.58);
  border: 1px solid transparent;
  -webkit-backdrop-filter: blur(22px) saturate(150%); backdrop-filter: blur(22px) saturate(150%);
  border-radius: var(--r-card); cursor: pointer; display: flex; flex-direction: column; gap: var(--s3);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.05);
  transition: box-shadow var(--d-mittel) var(--ease), background var(--d-schnell) var(--ease);
}
.pcard:hover { background:
    linear-gradient(158deg, rgba(255,255,255,.10), rgba(255,255,255,.026) 46%, rgba(255,255,255,.06)),
    rgba(16,23,34,.62); box-shadow: inset 0 1px 0 rgba(255,255,255,.22), 0 2px 6px rgba(0,0,0,.36), 0 30px 60px -40px rgba(0,0,0,.95); }
/* Titel und Abzeichen nebeneinander zwangen bei schmalen Karten den Titel auf
   drei Zeilen. Jetzt untereinander: der Titel bekommt die volle Breite, die
   Abzeichen stehen darunter. Ruhiger und bei jeder Kartenbreite stabil. */
.pcard__top { display: flex; flex-direction: column; gap: 7px; }
.pcard__title { font-size: var(--t-5); font-weight: 600; line-height: var(--lh-titel); overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
.pcard__client { font-size: var(--t-3); color: var(--text-faint); margin-top: var(--s0-5); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pcard__badges { display: flex; gap: var(--s1-5); flex-wrap: wrap; }
.pcard__foot { display: flex; align-items: center; gap: var(--s3); font-size: var(--t-3); color: var(--text-muted); flex-wrap: wrap; }
.pcard__foot .meta { white-space: nowrap; }
.pcard__foot .meta { display: inline-flex; align-items: center; gap: 5px; }
.pcard__foot .meta svg { width: 14px; height: 14px; opacity: .7; }
.pcard__foot .meta.is-overdue { color: var(--danger); }

/* ========================= Steps checklist ========================= */
.steps { display: flex; flex-direction: column; gap: var(--s0-5); }
.step {
  display: flex; align-items: center; gap: var(--s3);
  padding: 9px 11px; border-radius: var(--r-ctrl);
  transition: background var(--d-schnell) var(--ease);
}
.step:hover { background: var(--e3); }
.step__check {
  width: 20px; height: 20px; border-radius: var(--r-sm); flex: none;
  border: 1.6px solid var(--border-strong); background: transparent;
  display: grid; place-items: center; cursor: pointer; color: transparent;
  transition: background var(--d-schnell) var(--ease), border-color var(--d-schnell) var(--ease), color var(--d-schnell) var(--ease);
}
.step__check svg { width: 13px; height: 13px; }
.step.is-done .step__check { background: var(--st-done); border-color: var(--st-done); color: #fff; }
.step__label { font-size: var(--t-4); flex: 1; cursor: pointer; }
.step.is-done .step__label { color: var(--text-faint); text-decoration: line-through; }
.step__del { opacity: 0; color: var(--text-faint); }
.step:hover .step__del { opacity: 1; }
.step__del:hover { color: var(--danger); }

/* ========================= Forms ========================= */
.form { display: flex; flex-direction: column; gap: var(--s4); }
.field { display: flex; flex-direction: column; gap: var(--s1-5); }
.field > label { font-size: var(--t-3); font-weight: 600; color: var(--text-muted); }
.field .hint { font-size: var(--t-2); color: var(--text-faint); }
.grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s4); }
.grid-3 { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: var(--s4); }

/* Das Eingabefeld ist auf der Website eine VERTIEFUNG IM SELBEN MATERIAL:
   eine leichte weisse Aufhellung mit innenliegendem Ring. Hier stand
   stattdessen eine deckende Flaeche (--e1). Auf einer Glasscheibe liest sich
   ein deckendes dunkles Rechteck als Loch, nicht als Feld - das war der
   sichtbarste verbliebene Materialunterschied zwischen App und Seite.
   Der Ring liegt innen (box-shadow statt border), damit die Feldhoehe beim
   Fokus nicht um zwei Pixel springt. */
input:not([type=checkbox]):not([type=radio]):not([type=color]):not([type=range]):not([type=file]),
select, textarea {
  width: 100%; min-height: var(--h-ctrl); padding: var(--s2) var(--s3);
  background: rgba(255,255,255,.045); border: 0;
  box-shadow: inset 0 0 0 1px var(--border-strong);
  border-radius: var(--r-ctrl);
  color: var(--text); font: inherit; font-size: var(--t-4); outline: none;
  transition: box-shadow var(--d-schnell) var(--ease), background-color var(--d-schnell) var(--ease);
}
/* Im Fokus wird der Ring hellblau und die Flaeche eine Spur heller - genau das
   Rezept der Website. Vorher war der Ring --accent-line, also mittleres Blau
   auf dunklem Grund, und der Hof --accent-soft mit 16 Prozent: zusammen kaum
   zu sehen. */
input:not([type=checkbox]):not([type=radio]):not([type=color]):focus, select:focus, textarea:focus {
  box-shadow: inset 0 0 0 1px var(--accent-2), 0 0 0 3px rgba(61,119,187,.22);
  background: rgba(255,255,255,.07);
}
/* Der Platzhalter lief auf --text-faint. Diese Stufe ist am 27.08. bewusst auf
   .52 gehoben worden, damit LESBARER Text lesbar bleibt - ein Platzhalter ist
   aber kein Text, den man liest, sondern einer, den man ersetzt. Bei .52 sah
   ein leeres Feld aus wie ein ausgefuelltes. Die Website steht auf .32. */
input::placeholder, textarea::placeholder { color: rgba(238,243,249,.32); }
textarea { resize: vertical; min-height: 84px; line-height: var(--lh-text); }
select { appearance: none; 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='%237fb2ee' stroke-width='2' stroke-linecap='round'><path d='M6 9l6 6 6-6'/></svg>"); background-repeat: no-repeat; background-position: right 12px center; padding-right: 36px; cursor: pointer; }

.chips { display: flex; flex-wrap: wrap; gap: var(--s1-5); }
.chip { display: inline-flex; align-items: center; gap: var(--s1-5); padding: var(--s1) var(--s2-5); border-radius: var(--r-pill); background: var(--e3); border: 1px solid var(--border); font-size: var(--t-3); cursor: pointer; color: var(--text-muted); transition: background var(--d-schnell) var(--ease), border-color var(--d-schnell) var(--ease), color var(--d-schnell) var(--ease); }
.chip:hover { color: var(--text); border-color: var(--border-strong); }
.chip.is-active { background: var(--accent-soft); border-color: var(--accent-line); color: var(--accent-2); }

/* ========================= Modal ========================= */
.modal-host { position: fixed; inset: 0; z-index: 100; display: grid; place-items: center; padding: var(--s5); }
.modal-host[hidden] { display: none; }
.modal-scrim { position: absolute; inset: 0; background: rgba(6,8,12,.62); backdrop-filter: blur(3px); }
/* Dieselbe Scheibe wie ein Panel, nur dichter: ein Dialog muss decken, sonst
   liest man den Bildschirm dahinter mit. Darum .9 statt .58 in der Fuellung. */
.modal {
  position: relative; isolation: isolate; width: 100%; max-width: 620px; max-height: 90dvh; overflow: hidden;
  background:
    linear-gradient(158deg, rgba(255,255,255,.072), rgba(255,255,255,.018) 46%, rgba(255,255,255,.042)),
    rgba(12,18,27,.9);
  -webkit-backdrop-filter: blur(24px) saturate(150%); backdrop-filter: blur(24px) saturate(150%);
  border: 1px solid transparent; border-radius: var(--r-lg);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.16),
    0 2px 6px rgba(0,0,0,.36),
    var(--sh-3);
  display: flex; flex-direction: column;
  animation: modal-in var(--d-schnell) var(--ease);
}
.modal--wide { max-width: 760px; }
@keyframes modal-in { from { opacity: 0; transform: translateY(8px) scale(.98); } to { opacity: 1; transform: none; } }
.modal__head { display: flex; align-items: center; gap: var(--s3); padding: var(--s5) var(--s5) var(--s4); border-bottom: 1px solid var(--border); }
.modal__head h2 { font-size: var(--t-5); font-weight: 600; }
.modal__head .sub { font-size: var(--t-3); color: var(--text-faint); margin-top: var(--s0-5); }
.modal__close { margin-left: auto; }
.modal__body { padding: var(--s5); overflow-y: auto; }
.modal__foot { display: flex; align-items: center; gap: var(--s3); padding: var(--s4) var(--s5); border-top: 1px solid var(--border); background: var(--e1); }
.modal__foot .spacer { flex: 1; }

/* ========================= Empty states ========================= */
.empty { text-align: center; padding: var(--s8) var(--s5); }
.empty__ico { width: 56px; height: 56px; margin: 0 auto var(--s4); border-radius: var(--r-md); display: grid; place-items: center; background: var(--e3); color: var(--text-faint); border: 1px solid var(--border); }
.empty__ico svg { width: 26px; height: 26px; }
.empty h3 { font-size: var(--t-5); margin-bottom: var(--s1-5); }
.empty p { color: var(--text-faint); font-size: var(--t-4); max-width: 380px; margin: 0 auto var(--s5); }

/* ========================= Detail layout ========================= */
.detail-grid { display: grid; grid-template-columns: 1.6fr 1fr; gap: var(--s5); align-items: start; }
.kv { display: grid; grid-template-columns: 120px 1fr; gap: var(--s3) var(--s4); font-size: var(--t-4); }
.kv dt { color: var(--text-faint); }
.kv dd { margin: 0; color: var(--text); }
.kv dd a { color: var(--accent-2); text-decoration: none; }
.kv dd a:hover { text-decoration: underline; }
.section-title { font-size: var(--t-3); text-transform: uppercase; letter-spacing: var(--ls-versal); color: var(--text-faint); margin: 0 0 var(--s3); font-weight: 600; }

/* ========================= Calendar ========================= */
.cal { display: grid; grid-template-columns: minmax(0, 1.7fr) minmax(0, 1fr); gap: var(--s5); align-items: start; }
.cal__grid-head { display: flex; align-items: center; gap: var(--s3); margin-bottom: var(--s4); }
.cal__month { font-family: var(--font-display); font-size: var(--t-6); font-weight: 600; min-width: 190px; }
.cal__weekdays { display: grid; grid-template-columns: repeat(7,1fr); gap: var(--s1); margin-bottom: var(--s1); }
.cal__weekdays span { text-align: center; font-size: var(--t-2); color: var(--text-faint); font-weight: 600; padding: var(--s1) 0; }
.cal__days { display: grid; grid-template-columns: repeat(7,1fr); gap: var(--s1); }
.cal__day {
  /* Etwas hoeher, damit zwei zweizeilige Termine sichtbar hineinpassen. */
  min-height: 96px; padding: var(--s1-5) 7px; border-radius: var(--r-sm);
  background: var(--e2); border: 1px solid var(--border); cursor: pointer;
  display: flex; flex-direction: column; gap: 3px; overflow: hidden;
  transition: background var(--d-schnell) var(--ease), border-color var(--d-schnell) var(--ease);
}
.cal__day:hover { background: var(--e3); border-color: var(--border-strong); }
.cal__day.is-out { opacity: .4; }
.cal__day.is-today { border-color: var(--accent-line); }
.cal__daynum { font-size: var(--t-3); color: var(--text-muted); font-variant-numeric: tabular-nums; }
.cal__day.is-today .cal__daynum { color: var(--accent); font-weight: 700; }
/* Zwei Zeilen statt einer: die Uhrzeit klein darueber, der Titel darunter.
   Vorher stand beides nebeneinander und der Titel wurde weggeschnitten. */
.cal__evt {
  display: flex; flex-direction: column; gap: 1px; line-height: var(--lh-titel);
  padding: 3px var(--s1-5) var(--s1); border-radius: var(--r-xs); background: var(--accent-soft);
  color: var(--accent-2); overflow: hidden; cursor: pointer;
  border-left: 2px solid var(--accent);
}
.cal__evt-t { font-size: var(--t-1); opacity: .8; font-variant-numeric: tabular-nums; }
.cal__evt-n { font-size: var(--t-2); font-weight: 500; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cal__evt:hover { background: rgba(61,119,187,.28); }
.cal__evt.is-done { background: var(--e4); border-left-color: var(--border-strong); color: var(--text-faint); }
.cal__evt.is-done .cal__evt-n { color: var(--text-faint); text-decoration: line-through; }
.cal__more { font-size: var(--t-1); color: var(--text-faint); padding-left: var(--s1-5); }

/* Appointment list item */
.appt { display: flex; gap: var(--s3); padding: var(--s3) var(--s5); border-bottom: 1px solid var(--border); cursor: pointer; transition: background var(--d-schnell) var(--ease); }
.appt:last-child { border-bottom: 0; }
.appt:hover { background: var(--e3); }
.appt__date { flex: none; width: 46px; text-align: center; }
.appt__day { font-family: var(--font-display); font-size: var(--t-6); font-weight: 700; line-height: 1; }
.appt__mon { font-size: var(--t-1); text-transform: uppercase; color: var(--text-faint); letter-spacing: var(--ls-versal); }
.appt__main { flex: 1; min-width: 0; }
.appt__title { font-size: var(--t-4); font-weight: 600; }
.appt__meta { font-size: var(--t-3); color: var(--text-faint); display: flex; gap: var(--s3); margin-top: var(--s0-5); }
.appt.is-done .appt__title { color: var(--text-faint); text-decoration: line-through; }
.appt.is-today .appt__date .appt__day { color: var(--accent); }

/* ========================= Toasts ========================= */
.toasts { position: fixed; bottom: var(--s5); right: var(--s5); z-index: 200; display: flex; flex-direction: column; gap: var(--s2); }
/* Alles, was ueber dem Inhalt SCHWEBT, ist auf der Website aus demselben Glas:
   die Leiste, das mobile Blatt. In der App waren Toast, Ueberlaufmenue und
   Suchergebnisse bis zum 27.08. die letzten drei schwebenden Flaechen mit einer
   deckenden Fuellung und einem harten Rand - drei Fremdkoerper zwischen lauter
   Scheiben. Sie tragen jetzt dasselbe Rezept wie der Dialog (dichtere Fuellung,
   weil man durch sie hindurch nichts lesen koennen soll). */
.toast {
  display: flex; align-items: center; gap: var(--s3);
  padding: var(--s3) var(--s4); border-radius: var(--r-md);
  background:
    linear-gradient(158deg, rgba(255,255,255,.072), rgba(255,255,255,.018) 46%, rgba(255,255,255,.042)),
    rgba(12,18,27,.9);
  -webkit-backdrop-filter: blur(22px) saturate(150%); backdrop-filter: blur(22px) saturate(150%);
  border: 1px solid transparent;
  box-shadow: inset 0 1px 0 rgba(255,255,255,.16), 0 2px 6px rgba(0,0,0,.36), var(--sh-3);
  font-size: var(--t-4); min-width: 220px;
  animation: toast-in var(--d-schnell) var(--ease);
}
.toast svg { width: 17px; height: 17px; flex: none; }
.toast--ok svg { color: var(--st-done); }
.toast--info svg { color: var(--st-active); }
@keyframes toast-in { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }

/* ========================= Utility ========================= */
/* ========================= Kleine Helfer =========================
   Nur fuer das, was sich im JavaScript oft genug wiederholt, um eigenen Namen zu
   verdienen. Absichtlich wenige: eine Sammlung von hundert Hilfsklassen waere
   dasselbe Durcheinander wie hundert Inline-Stile, nur an anderer Stelle. */
.u-flush    { margin: 0; }
.u-stack    { margin: 0 0 var(--s4); }
.u-gap-s5   { margin-bottom: var(--s5); }
.u-t1 { font-size: var(--t-1); }
.u-t2 { font-size: var(--t-2); }
.u-t3 { font-size: var(--t-3); }
.u-t4 { font-size: var(--t-4); }
.u-lead     { line-height: var(--lh-text); }
.u-strong   { font-weight: 600; }
.u-warn     { color: var(--st-waiting); }
.u-mid      { justify-content: center; }
.u-auto     { width: auto; }
/* Fliesstext, der zurueckhaltend bleiben soll - traegt Groesse und Durchschuss
   jetzt selbst, damit die Aufrufe nichts mehr nachschieben muessen. */
.faint--text { font-size: var(--t-3); line-height: var(--lh-text); }

.muted { color: var(--text-muted); }
.faint { color: var(--text-faint); }
.mono { font-family: var(--font-zahl); font-variant-numeric: tabular-nums; }
.stack { display: flex; flex-direction: column; }
.stack-4 { display: flex; flex-direction: column; gap: var(--s4); }
.stack-5 { display: flex; flex-direction: column; gap: var(--s5); }
.rowflex { display: flex; align-items: center; gap: var(--s3); }
.spacer { flex: 1; }
.nowrap { white-space: nowrap; }
/* Auch auf einem <button> verwendbar. Ohne den Ruecksetzer schlaegt dort die
   Standarddarstellung des Browsers durch und aus dem Textlink wird ein weisser
   Kasten mitten im Satz. Fuer <a> und <span> aendern diese vier Angaben nichts,
   die haben ohnehin keinen Rahmen, kein Polster und keine eigene Flaeche. */
.link { color: var(--accent-2); cursor: pointer; text-decoration: none; background: none; border: 0; padding: 0; font: inherit; }
.link:hover { text-decoration: underline; }
/* Ein SVG ohne eigene Groesse fuellt die verfuegbare Breite. In Knoepfen greift
   `.btn svg`, in einem Textlink griff bisher NICHTS - dort wuchs das Pfeil-Symbol
   auf ueber 140 px. Diese Regel deckt alle Symbole im Fliesstext ab. */
a svg, dd svg, .meta svg, .kv svg { width: 1em; height: 1em; flex: 0 0 auto; vertical-align: -.14em; }
a.btn svg { width: 16px; height: 16px; }
.divider { height: 1px; background: var(--border); margin: var(--s4) 0; }
.tag-list { display: flex; flex-wrap: wrap; gap: var(--s1-5); }

/* ========================= Responsive ========================= */
@media (max-width: 1080px) {
  .stat-grid { grid-template-columns: repeat(2, 1fr); }
  /* minmax(0,1fr) statt 1fr: eine reine 1fr-Spalte schrumpft nie unter die Mindest-
     Inhaltsbreite ihrer Kinder und blaeht das Grid sonst ueber die Fensterbreite auf. */
  .dash-grid, .detail-grid, .cal { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 860px) {
  .app { grid-template-columns: 1fr; }
  .sidebar {
    position: fixed; left: 0; top: 0; z-index: 60; width: 260px;
    transform: translateX(-100%); transition: transform var(--d-lang) var(--ease);
  }
  .sidebar.is-open { transform: none; box-shadow: var(--sh-3); }
  .topbar__menu { display: inline-grid; }
  .view { padding: var(--s4); }
  .topbar { padding: var(--s3) var(--s4); }
  .grid-2, .grid-3 { grid-template-columns: 1fr; }
  .scrim-mobile { position: fixed; inset: 0; background: rgba(0,0,0,.5); z-index: 55; }
}
@media (max-width: 620px) {
  /* Listenzeilen sind fuer eine Zeile gebaut: Avatar + Titel + Badges + Fortschritt + Prozent.
     Das sind zusammen ueber 600px, die nicht schrumpfen - auf dem Handy schob das die ganze
     Seite seitlich weg. Ab hier bricht der rechte Teil unter den Titel. */
  .row { flex-wrap: wrap; row-gap: var(--s2-5); }
  .row__main { flex: 1 1 auto; }
  .row__aside { flex: 1 0 100%; flex-wrap: wrap; gap: var(--s2) var(--s2-5); }
  .doc-row { flex-wrap: wrap; row-gap: 8px; }
  .task { flex-wrap: wrap; row-gap: var(--s1-5); }

  /* Kopfzeile in zwei Reihen: oben Menue und Titel, darunter Regler und Knoepfe.
     Vorher teilte sich der Titel die Reihe mit beidem, wurde dadurch auf gut 100 px
     gequetscht und brach ueber drei Zeilen um ("0 / laufend · / 17 / gesamt").
     Die Grundbreite erzwingt den Umbruch, ohne dass das Menue mitgeht. */
  /* Zwei Reihen: oben Menue und Titel ueber die volle Breite, darunter Regler und
     Knoepfe. Der Titel teilte sich die Reihe vorher mit beidem und wurde auf gut
     100 px gequetscht, sodass er ueber drei Zeilen umbrach.
     Die engeren Abstaende sind kein Schoenheitswunsch: mit den normalen 8 px fehlten
     der Auftrags-Kopfzeile genau sechs Pixel und ihr letzter Knopf fiel in eine
     dritte Reihe. Die Knopfreihe eine Reihe tiefer zu setzen waere teurer gewesen,
     das haette JEDE Ansicht 40 px hoeher gemacht, auch die mit nur einem Knopf. */
  .topbar { flex-wrap: wrap; row-gap: var(--s2-5); gap: var(--s3); }
  .topbar__title { flex: 1 1 calc(100% - 52px); min-width: 0; }
  .topbar__title h1 { font-size: var(--t-6); }
  .topbar__sub { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  #themeToggle { order: 3; flex: 0 0 auto; }
  /* flex-basis 0 statt auto: sonst misst sich die Knopfgruppe an ihrer vollen
     Inhaltsbreite, passt nie neben den Regler und laesst ihn allein in einer Reihe. */
  .topbar__actions { order: 4; flex: 1 1 0; min-width: 0; flex-wrap: wrap; justify-content: flex-end; gap: var(--s1-5); row-gap: var(--s1-5); }
  .panel__head { flex-wrap: wrap; row-gap: var(--s2); }
  .panel__head .panel__act { margin-left: 0; }
  .rowflex { flex-wrap: wrap; row-gap: var(--s2); }
  .chrome-actions, .view-actions { flex-wrap: wrap; row-gap: var(--s1-5); }
  .cal__grid-head { flex-wrap: wrap; row-gap: var(--s2); }

  /* Die Auftragskarte stapelt Titel und Marken inzwischen ohnehin (.pcard__top ist
     eine Spalte). Die alte Regel von damals rechnete noch mit einer Zeile: in einer
     Spalte meint flex-basis 100 % die HOEHE, die Marken wurden 73 px hoch, sahen als
     Pillen wie Kreise aus und liefen aus der Karte. Ersatzlos raus. */
  .pcard__badges { justify-content: flex-start; }

  /* Filterleisten sind Reiter: sie scrollen in sich, die Seite bleibt ruhig. */
  .segmented {
    max-width: 100%; overflow-x: auto; scrollbar-width: none; -ms-overflow-style: none;
    overscroll-behavior-x: contain;
  }
  .segmented::-webkit-scrollbar { display: none; }
}
@media (max-width: 480px) {
  .stat-grid { grid-template-columns: 1fr; }
}

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

/* ========================= Global search (topbar) ========================= */
.topbar__search { position: relative; margin-left: auto; }
.search--top { min-width: 200px; max-width: 260px; padding: 0 var(--s3); }
.search--top input { font-size: var(--t-4); }
@media (max-width: 720px) { .topbar__search { display: none; } }
.search-results {
  position: absolute; top: calc(100% + 6px); right: 0; width: 380px; max-width: 84vw; max-height: 60vh; overflow-y: auto;
  border-radius: var(--r-card); z-index: 50; padding: var(--s1-5);
  background:
    linear-gradient(158deg, rgba(255,255,255,.072), rgba(255,255,255,.018) 46%, rgba(255,255,255,.042)),
    rgba(12,18,27,.9);
  -webkit-backdrop-filter: blur(22px) saturate(150%); backdrop-filter: blur(22px) saturate(150%);
  border: 1px solid transparent;
  box-shadow: inset 0 1px 0 rgba(255,255,255,.16), 0 2px 6px rgba(0,0,0,.36), var(--sh-3);
}
.search-results .sr-group { font-size: var(--t-1); text-transform: uppercase; letter-spacing: var(--ls-versal); color: var(--text-faint); padding: var(--s2) var(--s2-5) var(--s1); font-weight: 600; }
.sr-item { display: flex; align-items: center; gap: var(--s2-5); padding: var(--s2) var(--s2-5); border-radius: var(--r-sm); cursor: pointer; }
.sr-item:hover, .sr-item.is-active { background: var(--e4); }
.sr-item svg { width: 16px; height: 16px; color: var(--text-faint); flex: none; }
.sr-item .sr-main { min-width: 0; flex: 1; }
.sr-item .sr-title { font-size: var(--t-4); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sr-item .sr-sub { font-size: var(--t-2); color: var(--text-faint); }
.sr-empty { padding: var(--s4-5); text-align: center; color: var(--text-faint); font-size: var(--t-4); }

/* ========================= View toggle ========================= */
.view-toggle { display: inline-flex; align-items: stretch; height: var(--h-ctrl); gap: var(--s0-5); padding: 3px; background: var(--e2); border: 1px solid var(--border); border-radius: var(--r-ctrl); }
.view-toggle button { display: inline-grid; place-items: center; width: 38px; border: 0; background: transparent; color: var(--text-muted); border-radius: var(--r-sm); cursor: pointer; }
.view-toggle button svg { width: 16px; height: 16px; }
.view-toggle button.is-active { background: var(--e4); color: var(--text); }

/* ========================= Kanban board ========================= */
/* Spalten gleich hoch statt jede so hoch wie ihr Inhalt. Vorher endete jede Spalte
   auf einer anderen Hoehe und das Board sah aus wie eine Treppe; ausserdem war die
   Ablaeche zum Hineinziehen bei einer leeren Spalte nur 60 px hoch und schwer zu treffen.
   `align-items: stretch` (Vorgabe im Grid) plus eine Mindesthoehe fuer den Rumpf. */
.board { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--s4); align-items: stretch; }
/* HIER STAND ES VERKEHRT HERUM, gefunden am 27.08.2026.
   Die Regel aus dem zweiten Durchgang lautet: AUSSENFLAECHEN sind Glas,
   INNENKAESTEN sind eine flache Aufhellung darauf. Auf der Tafel war es genau
   andersherum - die Spalte war ein flacher Kasten und die Beitraege darin
   trugen die Scheibe. Damit lag das Material auf der falschen Ebene: es sah
   aus, als schwebten dreissig kleine Scheiben in einem Karton.
   Die Spalte ist ein Behaelter wie ein Panel und traegt deshalb dasselbe
   Glas und denselben grossen Radius. Ohne Glaskante, weil vier bis fuenf
   Spalten nebeneinander stehen und vier Rahmen in einer Reihe ein Zaun sind. */
.board__col {
  position: relative; isolation: isolate;
  background:
    linear-gradient(158deg, rgba(255,255,255,.072), rgba(255,255,255,.018) 46%, rgba(255,255,255,.042)),
    rgba(12,18,27,.58);
  -webkit-backdrop-filter: blur(22px) saturate(150%);
  backdrop-filter: blur(22px) saturate(150%);
  border: 1px solid transparent;
  border-radius: var(--r-lg);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.16),
    0 2px 6px rgba(0,0,0,.36),
    0 44px 90px -54px rgba(0,0,0,.95);
  min-height: 120px; display: flex; flex-direction: column;
}
/* Beim Hineinziehen leuchtet die ganze Scheibe blau an, statt ihre Fuellung zu
   verlieren - sonst faellt die Spalte im Moment des Ziehens aus dem Material. */
.board__col.is-drop {
  border-color: var(--accent-line);
  box-shadow: inset 0 0 0 1px var(--accent-line), inset 0 1px 0 rgba(255,255,255,.2), 0 0 34px -6px var(--accent-soft);
}
.board__head { display: flex; align-items: center; gap: var(--s2); padding: var(--s3) 14px; border-bottom: 1px solid var(--border); font-size: var(--t-3); font-weight: 600; }
.board__head .dot { width: 8px; height: 8px; border-radius: var(--r-pill); }
.board__head .n { margin-left: auto; color: var(--text-faint); font-variant-numeric: tabular-nums; }
.board__body { padding: var(--s2-5); display: flex; flex-direction: column; gap: var(--s2-5); min-height: 140px; flex: 1; }
/* Der Beitrag LIEGT AUF der Scheibe der Spalte, er ist nicht selbst eine.
   Bis zum 27.08.2026 trug er das volle Glas - dreissig kleine Scheiben in
   einem flachen Karton. Jetzt dasselbe Mittel wie bei den drei Bereichen im
   Hilfebereich: eine leichte Aufhellung mit Ring, also ein Blatt auf Glas.
   Der Radius ist eine Stufe KLEINER als der der Spalte. Ein Innenkasten mit
   demselben Radius wie sein Behaelter sieht aus, als sei er hineingerutscht.
   Nebenbei kostet das keine einzige Unschaerfe mehr: die Unschaerfe gehoert
   auf Flaechen, die man ansieht, nicht auf Dinge, die man zu Dutzenden
   ueberfliegt. */
.kcard { background: rgba(255,255,255,.05); border: 1px solid var(--border); border-radius: var(--r-sm); padding: var(--s3); cursor: grab; display: flex; flex-direction: column; gap: var(--s2); }
.kcard:hover { border-color: var(--border-strong); }
.kcard.dragging { opacity: .5; }
.kcard__title { font-size: var(--t-4); font-weight: 600; line-height: var(--lh-titel); }
.kcard__client { font-size: var(--t-2); color: var(--text-faint); }
/* Umbruch erlaubt, aber nie INNERHALB einer Angabe - sonst steht "in 9" und "Tagen"
   auf zwei Zeilen und die Karten wirken unruhig. */
.kcard__foot { display: flex; align-items: center; flex-wrap: wrap; gap: var(--s1-5) var(--s2-5); font-size: var(--t-2); color: var(--text-muted); }
.kcard__foot .m { display: inline-flex; align-items: center; gap: var(--s1); white-space: nowrap; }
.kcard__foot .m svg { width: 12px; height: 12px; }
.kcard__foot .m.is-overdue { color: var(--danger); }
.kcard__foot .m.is-late { color: var(--danger); font-weight: 600; }
.kcard.is-late { border-color: color-mix(in srgb, var(--danger) 40%, transparent); }
/* Eine Spalte mit 17 Karten wurde 1674 px hoch und schob den Rest des Bretts weg.
   Die Spalte scrollt jetzt in sich, das Brett bleibt auf einem Bildschirm. */
.board__body--cap { max-height: min(62vh, 640px); overflow-y: auto; }
.board__late { display: inline-flex; align-items: center; justify-content: center; min-width: 18px; height: 18px; padding: 0 5px; border-radius: var(--r-sm); font-size: var(--t-1); font-weight: 700; color: var(--danger); background: var(--danger-soft); }
.board__leer { font-size: var(--t-3); color: var(--text-faint); text-align: center; margin: var(--s2) 0; }
@media (max-width: 1080px) { .board { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 620px) { .board { grid-template-columns: 1fr; } }

/* ========================= Tasks ========================= */
.task { display: flex; align-items: center; gap: var(--s3); padding: 11px var(--s5); border-bottom: 1px solid var(--border); flex-wrap: wrap; row-gap: var(--s1-5); }
.task:last-child { border-bottom: 0; }
.task:hover { background: var(--e3); }
.task__check { width: 20px; height: 20px; border-radius: var(--r-sm); flex: none; border: 1.6px solid var(--border-strong); background: transparent; display: grid; place-items: center; cursor: pointer; color: transparent; transition: background var(--d-schnell) var(--ease), border-color var(--d-schnell) var(--ease), color var(--d-schnell) var(--ease); }
.task__check svg { width: 13px; height: 13px; }
.task.is-done .task__check { background: var(--st-done); border-color: var(--st-done); color: #fff; }
.task__main { flex: 1; min-width: 0; cursor: pointer; }
/* Einzeilig mit Auslassung. Vorher liefen Titel und Unterzeile je ueber zwei Zeilen und
   eine Aufgabenzeile wurde 100 px hoch - vier Aufgaben fuellten damit den halben Bildschirm,
   und die Zeilen waren unterschiedlich hoch, was die Liste unruhig machte. Der volle Text
   steht im title-Attribut und beim Oeffnen der Aufgabe. */
.task__title { font-size: var(--t-4); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.task.is-done .task__title { color: var(--text-faint); text-decoration: line-through; }
.task__sub { font-size: var(--t-2); color: var(--text-faint); margin-top: 1px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.task__due { font-size: var(--t-3); color: var(--text-muted); white-space: nowrap; }
.task__due.is-overdue { color: var(--danger); }
.task__due.is-today { color: var(--accent-2); }
.task__del { opacity: 0; }
.task:hover .task__del { opacity: 1; }

/* ========================= Timer ========================= */
.timer-banner { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2) var(--s4); padding: 14px var(--s5); background: linear-gradient(90deg, var(--accent-soft), transparent); border: 1px solid var(--accent-line); border-radius: var(--r-card); margin-bottom: var(--s5); }
/* Ohne Umbruch und ohne schrumpfbaren Textblock schob ein langer Auftragstitel den
   Stoppen-Knopf bei 375 px um 10 px aus dem Fenster. Gefunden am 23.08.2026, weil die
   Aktionspruefung erstmals am Handy gelaufen ist statt nur am Schreibtisch. */
.timer-banner > div:not(.spacer) { min-width: 0; overflow-wrap: anywhere; }
.timer-banner .pulse { width: 10px; height: 10px; border-radius: var(--r-pill); background: var(--accent); box-shadow: 0 0 0 0 var(--accent-line); animation: pulse 1.6s infinite; }
@keyframes pulse { 0%{box-shadow:0 0 0 0 rgba(61,119,187,.5)} 70%{box-shadow:0 0 0 8px rgba(61,119,187,0)} 100%{box-shadow:0 0 0 0 rgba(61,119,187,0)} }
.timer-live { font-family: var(--font-zahl); font-size: var(--t-6); font-weight: 600; font-variant-numeric: tabular-nums; letter-spacing: var(--ls-h2); }
.time-entry { display: flex; align-items: center; gap: var(--s3); padding: 9px var(--s5); border-bottom: 1px solid var(--border); font-size: var(--t-4); }
.time-entry:last-child { border-bottom: 0; }
.time-entry .dur { font-family: var(--font-zahl); font-variant-numeric: tabular-nums; color: var(--text); min-width: 64px; }
.time-entry .note { color: var(--text-muted); flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.time-entry .date { color: var(--text-faint); font-size: var(--t-3); }
.time-entry .del { opacity: 0; } .time-entry:hover .del { opacity: 1; }

/* ========================= Finance list ========================= */
.doc-row { display: flex; align-items: center; gap: var(--s4); padding: var(--s3) var(--s5); border-bottom: 1px solid var(--border); cursor: pointer; transition: background var(--d-schnell) var(--ease); }
.doc-row:last-child { border-bottom: 0; }
.doc-row:hover { background: var(--accent-soft); box-shadow: inset 3px 0 0 var(--accent); }
.doc-row__num { font-family: var(--font-zahl); font-variant-numeric: tabular-nums; font-size: var(--t-4); color: var(--text-muted); min-width: 130px; }
.doc-row__main { flex: 1; min-width: 0; }
.doc-row__title { font-size: var(--t-4); font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.doc-row__sub { font-size: var(--t-3); color: var(--text-faint); }
.doc-row__amount { font-family: var(--font-zahl); font-variant-numeric: tabular-nums; font-size: var(--t-4); text-align: right; min-width: 110px; }
.badge--draft { color: var(--st-lead); background: color-mix(in srgb, var(--st-lead) 12%, transparent); }
.badge--sent { color: var(--st-active); background: rgba(68,147,248,.13); }
.badge--paid { color: var(--st-done); background: color-mix(in srgb, var(--st-done) 13%, transparent); }
.badge--accepted { color: var(--st-done); background: color-mix(in srgb, var(--st-done) 13%, transparent); }
.badge--declined { color: var(--danger); background: var(--danger-soft); }

.fin-summary { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--s4); margin-bottom: var(--s5); }
@media (max-width: 720px) { .fin-summary { grid-template-columns: 1fr; } }

/* Items editor */
.items-editor { display: flex; flex-direction: column; gap: var(--s2); }
.item-row { display: grid; grid-template-columns: 1fr 64px 96px 90px 32px; gap: var(--s2); align-items: center; }
.item-row .ir-total { font-family: var(--font-zahl); font-variant-numeric: tabular-nums; font-size: var(--t-4); text-align: right; color: var(--text-muted); }
.item-head { display: grid; grid-template-columns: 1fr 64px 96px 90px 32px; gap: var(--s2); font-size: var(--t-2); color: var(--text-faint); padding: 0 var(--s0-5); }
.item-head span:nth-child(2), .item-head span:nth-child(3), .item-head span:nth-child(4) { text-align: right; }
.doc-total-line { display: flex; justify-content: flex-end; gap: var(--s5); padding: 6px 2px; font-size: var(--t-4); }
.doc-total-line.grand { font-size: var(--t-5); font-weight: 700; border-top: 1px solid var(--border); padding-top: 12px; margin-top: 4px; }
.doc-total-line .val { font-family: var(--font-zahl); font-variant-numeric: tabular-nums; min-width: 110px; text-align: right; }

/* ========================= Invoice sheet (paper, light - also for print) ========================= */
.sheet-wrap { display: flex; flex-direction: column; gap: var(--s4); }
/* ===== Der Beleg ist ein echtes A4-Blatt =====
   210 x 297 mm mit Rändern in mm. Was hier steht, kommt genau so aus dem Drucker.
   Die Vorschau skaliert das Blatt nur, sie baut es nicht anders auf. */
.sheet-stage { display: flex; justify-content: center; overflow: hidden; }
.sheet-stage__inner { transform-origin: top center; }

.invoice-sheet {
  background: #ffffff; color: #1a1a1a; box-shadow: var(--sh-2);
  width: 210mm; min-height: 297mm; margin: 0 auto;
  padding: 18mm 20mm 12mm;
  display: flex; flex-direction: column;
  font-size: 10.5pt; line-height: 1.5;
}
.invoice-sheet * { box-sizing: border-box; }
/* Der Inhalt waechst, die Briefbogen-Fusszeile bleibt am Blattfuss. */
.is-body { flex: 1 1 auto; }
.is-briefbogen {
  margin-top: 10mm; padding-top: 4mm; border-top: .5pt solid #ddd;
  display: grid; grid-template-columns: repeat(auto-fit, minmax(38mm, 1fr)); gap: 6mm;
  font-size: 7.6pt; line-height: 1.5; color: #6b7280;
}
/* Absenderzeile ueber dem Anschriftenfeld, wie im Fensterumschlag. */
.is-absender { font-size: 7.4pt; color: #8a94a3; border-bottom: .5pt solid #e5e7eb; padding-bottom: 1.5mm; margin-bottom: 2.5mm; }
.is-fehlt { color: #c0392b; }
.is-gruss { margin-top: 6mm; font-size: 9.5pt; color: #444; }

.is-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 24px; margin-bottom: 14mm; }
.is-logo { height: 54px; width: 240px; max-width: 55%; background-repeat: no-repeat; background-position: left center; background-size: contain; }
/* Ohne eigenes Logo tragen Belege die Initialen des Nutzers, keine fremde Marke. */
.is-logo--ini { width: 54px; display: flex; align-items: center; justify-content: center; border-radius: 9px; background: #eef1f6; color: var(--accent); font-family: var(--font-display); font-weight: 700; font-size: 22px; letter-spacing: .01em; }
.is-brand { font-size: 20px; font-weight: 700; color: #111; letter-spacing: -.01em; }
.is-brand small { display: block; font-size: 11px; font-weight: 400; color: #888; margin-top: 2px; letter-spacing: 0; }
.is-from { text-align: right; font-size: 11px; color: #555; line-height: 1.5; }
.is-meta { display: flex; justify-content: space-between; gap: 24px; margin-bottom: 32px; }
.is-to .lbl, .is-info .lbl { font-size: 10px; text-transform: uppercase; letter-spacing: .06em; color: #999; margin-bottom: 5px; }
.is-to strong { font-size: 14px; color: #111; }
.is-to div { color: #444; }
.is-info { text-align: right; }
.is-info table td { padding: 1px 0 1px 16px; color: #444; }
.is-info table td:first-child { color: #999; }
.is-title { font-size: 22px; font-weight: 700; color: #111; margin-bottom: 24px; }
.is-table { width: 100%; border-collapse: collapse; margin-bottom: 20px; }
.is-table thead th { text-align: left; font-size: 10px; text-transform: uppercase; letter-spacing: .05em; color: #999; border-bottom: 2px solid #eee; padding: 8px 10px; }
.is-table thead th.num, .is-table td.num { text-align: right; }
.is-table tbody td { padding: 10px; border-bottom: 1px solid #f0f0f0; color: #333; vertical-align: top; }
.is-table tbody td.num { font-variant-numeric: tabular-nums; white-space: nowrap; }

/* Rechnungs-Layout-Varianten */
.invoice-sheet.is-layout-modern { border-top: 6px solid var(--sheet-accent, #3d77bb); }
.invoice-sheet.is-layout-modern .is-title { color: var(--sheet-accent, #3d77bb); }
.invoice-sheet.is-layout-modern .is-table thead th { color: var(--sheet-accent, #3d77bb); border-bottom-color: var(--sheet-accent, #3d77bb); }
.invoice-sheet.is-layout-modern .is-totals .grand { color: var(--sheet-accent, #3d77bb); }
.invoice-sheet.is-layout-modern .is-to .lbl, .invoice-sheet.is-layout-modern .is-info td:first-child { color: var(--sheet-accent, #3d77bb); }
.invoice-sheet.is-layout-compact { padding: 32px 38px; font-size: 12px; }
.invoice-sheet.is-layout-compact .is-head { margin-bottom: 22px; }
.invoice-sheet.is-layout-compact .is-logo { height: 42px; }
.invoice-sheet.is-layout-compact .is-title { font-size: 18px; margin-bottom: 16px; }
.invoice-sheet.is-layout-compact .is-meta { margin-bottom: 18px; }
.invoice-sheet.is-layout-compact .is-table tbody td { padding: 6px 8px; }
.invoice-sheet.is-layout-compact .is-table thead th { padding: 6px 8px; }
.is-totals { margin-left: auto; width: 280px; }
.is-totals .line { display: flex; justify-content: space-between; padding: 5px 10px; color: #444; }
.is-totals .line.grand { font-size: 16px; font-weight: 700; color: #111; border-top: 2px solid #eee; margin-top: 6px; padding-top: 10px; }
.is-totals .num { font-variant-numeric: tabular-nums; }
.is-note { margin-top: 28px; padding-top: 18px; border-top: 1px solid #eee; color: #555; font-size: 12px; white-space: pre-wrap; }
.is-paywrap { margin-top: 20px; display: flex; align-items: flex-end; justify-content: space-between; gap: 24px; }
.is-paywrap > div:first-child { flex: 1; min-width: 0; }
.is-pay { font-size: 11.5px; color: #555; display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 10px 24px; }
.is-pay .lbl { font-size: 9.5px; text-transform: uppercase; letter-spacing: .05em; color: #aaa; }
.is-giro { flex: none; text-align: center; }
.is-giro svg { display: block; width: 118px; height: 118px; border: 1px solid #eee; border-radius: 8px; padding: 5px; background: #fff; }
.is-giro-cap { margin-top: 6px; font-size: 9.5px; line-height: 1.35; color: #888; }
.is-giro-cap strong { display: block; color: #444; font-size: 10.5px; font-weight: 600; }
.is-foot { margin-top: 36px; padding-top: 16px; border-top: 1px solid #eee; font-size: 10.5px; color: #999; text-align: center; }
.sheet-actions { display: flex; gap: var(--s2); flex-wrap: wrap; align-items: center; }

/* Logo preview in settings */
.logo-drop { display: flex; align-items: center; gap: var(--s4); }
/* Die weisse Platte ist Absicht: Kundenlogos sind meist dunkel auf
   durchsichtigem Grund und waeren auf dunklem Material unsichtbar.
   LEER ist sie aber ein weisser Block mitten im Dialog - das lauteste Element
   auf dem Bildschirm, und zwar fuer "hier ist nichts". Solange kein Logo
   gesetzt ist, traegt sie deshalb das Material der App; erst mit Bild wird
   die Platte weiss. Erkannt wird der Leerzustand am Hinweistext darin, den
   updLogo() genau dann setzt und sonst entfernt. */
.logo-preview { width: 140px; height: 64px; border-radius: var(--r-sm); border: 1px dashed var(--border-strong); background-color: #fff; background-repeat: no-repeat; background-position: center; background-size: contain; background-origin: content-box; padding: var(--s2); }
.logo-preview:has(.faint) { background-color: rgba(255,255,255,.045); }

/* ========================= Finance tabs ========================= */
.fin-tabs { display: flex; gap: var(--s0-5); border-bottom: 1px solid var(--border); margin-bottom: var(--s5); overflow-x: auto; }
.fin-tabs button { padding: 11px var(--s4); background: transparent; border: 0; border-bottom: 2px solid transparent; color: var(--text-muted); font-size: var(--t-4); font-weight: 600; cursor: pointer; margin-bottom: -1px; white-space: nowrap; transition: color var(--d-schnell) var(--ease); }
.fin-tabs button:hover { color: var(--text); }
.fin-tabs button.is-active { color: var(--text); border-bottom-color: var(--accent); }

/* ========================= Charts (Auswertungen) ========================= */
.legend { display: inline-flex; align-items: center; gap: var(--s1-5); font-size: var(--t-3); color: var(--text-muted); }
.legend .dot { width: 9px; height: 9px; border-radius: var(--r-xs); }
/* Balkendiagramm mit Werteachse: das Gitter liegt hinter den Balken, die Beschriftungen
   links davor. Ohne Achse liess sich die Balkenhoehe nicht in Betraege uebersetzen. */
.chart-wrap { position: relative; padding-left: 42px; }
.chart-grid { position: absolute; inset: 10px 0 22px 42px; pointer-events: none; }
.chart-grid__line { position: absolute; left: 0; right: 0; height: 0; border-top: 1px solid var(--border); opacity: .55; }
.chart-grid__line:first-child { opacity: .3; }
.chart-grid__val {
  position: absolute; right: calc(100% + 8px); top: 50%; transform: translateY(-50%);
  font-size: var(--t-1); color: var(--text-faint); font-variant-numeric: tabular-nums; white-space: nowrap;
}
.chart { position: relative; display: flex; align-items: flex-end; gap: var(--s1-5); height: 210px; padding-top: var(--s2-5); }
.chart-col { flex: 1; display: flex; flex-direction: column; align-items: center; gap: var(--s2); height: 100%; min-width: 0; }
.chart-stack { flex: 1; width: 100%; display: flex; align-items: flex-end; justify-content: center; gap: 3px; }
.chart-stack .bar { width: 42%; max-width: 22px; min-height: 2px; border-radius: var(--r-xs) 4px 0 0; transition: height var(--d-lang) var(--ease); }
.chart-stack .bar--rev { background: linear-gradient(180deg, var(--accent-2), var(--accent)); }
.chart-stack .bar--exp { background: linear-gradient(180deg, #efb066, var(--st-waiting)); }
.chart-col .clabel { font-size: var(--t-1); color: var(--text-faint); }

.hbars { display: flex; flex-direction: column; gap: 14px; }
.hbar { display: grid; grid-template-columns: 120px 1fr auto; gap: var(--s3); align-items: center; }
.hbar .hlabel { font-size: var(--t-4); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.hbar .track { height: 10px; background: var(--e4); border-radius: var(--r-pill); overflow: hidden; }
.hbar .fill { height: 100%; background: linear-gradient(90deg, var(--accent), var(--accent-2)); border-radius: var(--r-pill); transition: width var(--d-lang) var(--ease); }
.hbar .hval { font-family: var(--font-zahl); font-variant-numeric: tabular-nums; color: var(--text-muted); font-size: var(--t-3); min-width: 70px; text-align: right; }

/* ===================== Offene Posten (Aging) ===================== */
.aging-bar { display: flex; height: 16px; border-radius: var(--r-pill); overflow: hidden; background: var(--e4); }
.aging-seg { min-width: 3px; transition: flex var(--d-lang) var(--ease); }
.aging-legend { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: var(--s2-5) 18px; margin-top: var(--s4); }
.aging-leg { display: flex; align-items: center; gap: var(--s2); font-size: var(--t-3); }
.aging-leg .dot { width: 9px; height: 9px; border-radius: var(--r-xs); flex: none; }
.aging-leg .lbl { color: var(--text-muted); flex: 1; white-space: nowrap; }
.aging-leg .amt { font-family: var(--font-zahl); font-variant-numeric: tabular-nums; color: var(--text); }
.aging-leg .cnt { color: var(--text-faint); min-width: 18px; text-align: right; font-size: var(--t-2); }

/* ===================== Liquidität ===================== */
.liq-head { display: flex; align-items: flex-end; justify-content: space-between; gap: var(--s4); margin-bottom: var(--s5); flex-wrap: wrap; }
.liq-bal { font-family: var(--font-zahl); font-variant-numeric: tabular-nums; font-size: var(--t-2); color: var(--text-muted); white-space: nowrap; }
.liq-bal.is-neg { color: var(--danger); }
.liq-table { display: flex; flex-direction: column; }
.liq-row { display: grid; grid-template-columns: 1.2fr 1fr 1fr 1fr 1.1fr; gap: var(--s2-5); padding: var(--s2-5) var(--s5); border-bottom: 1px solid var(--border); align-items: center; }
.liq-row:last-child { border-bottom: 0; }
.liq-row--head { font-size: var(--t-2); text-transform: uppercase; letter-spacing: var(--ls-versal); color: var(--text-faint); background: var(--e3); }
.liq-row span { font-family: var(--font-zahl); font-variant-numeric: tabular-nums; font-size: var(--t-4); text-align: right; }
.liq-row .liq-m { font-family: var(--font); text-align: left; font-weight: 600; }
.liq-row--head span { font-family: var(--font); }
.liq-row .liq-in { color: var(--st-done); }
.liq-row .liq-out { color: var(--st-waiting); }
.liq-row .liq-net.is-neg, .liq-row .liq-run.is-neg { color: var(--danger); }
.liq-row .liq-run { font-weight: 700; }
@media (max-width: 640px) {
  .liq-row { grid-template-columns: 1fr 1fr; gap: var(--s1-5) var(--s2-5); }
  .liq-row .liq-m { grid-column: 1 / -1; }
  .liq-row--head { display: none; }
}

/* ===================== Aktivitäts-Verlauf (Timeline) ===================== */
.timeline { padding: var(--s4) var(--s5) var(--s5); }
.tl-item { display: flex; gap: var(--s3); padding: var(--s2) 0; position: relative; }
.tl-item:not(:last-child)::before { content: ""; position: absolute; left: 13px; top: 30px; bottom: -8px; width: 1px; background: var(--border); }
.tl-item[data-action]:hover .tl-text { color: var(--accent); }
.tl-ico { flex: none; width: 27px; height: 27px; border-radius: var(--r-pill); background: var(--e4); display: grid; place-items: center; color: var(--text-muted); z-index: 1; }
.tl-ico svg { width: 15px; height: 15px; }
.tl-body { flex: 1; min-width: 0; padding-top: 3px; }
.tl-text { font-size: var(--t-4); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tl-date { font-size: var(--t-2); color: var(--text-faint); margin-top: 1px; }

/* ===================== Anlässe (Kundenliste) ===================== */
.occ-strip { display: flex; gap: var(--s2); flex-wrap: wrap; margin-bottom: var(--s4); }
.occ-chip { display: inline-flex; align-items: center; gap: 7px; padding: 7px var(--s3); background: var(--e3); border: 1px solid var(--border); border-radius: var(--r-pill); color: var(--text-muted); font-size: var(--t-4); cursor: pointer; transition: border-color var(--d-schnell) var(--ease), color var(--d-schnell) var(--ease); }
.occ-chip:hover { border-color: var(--accent); color: var(--text); }
.occ-chip svg { width: 15px; height: 15px; color: var(--accent); }
.occ-chip .occ-when { color: var(--text-faint); font-size: var(--t-2); }

/* ===================== Kapazitätsplanung ===================== */
.cap-list { display: flex; flex-direction: column; gap: var(--s3); }
.cap-row { display: grid; grid-template-columns: 110px 1fr 150px; gap: 14px; align-items: center; }
.cap-wk { display: flex; flex-direction: column; line-height: var(--lh-titel); }
.cap-wk b { font-size: var(--t-4); }
.cap-wk .faint { font-size: var(--t-2); }
.cap-track { position: relative; height: 12px; background: var(--e4); border-radius: var(--r-pill); overflow: hidden; }
.cap-fill { height: 100%; background: linear-gradient(90deg, var(--accent), var(--accent-2)); border-radius: var(--r-pill); transition: width var(--d-lang) var(--ease); }
.cap-fill.is-over { background: linear-gradient(90deg, var(--st-waiting), var(--danger)); }
.cap-cap { position: absolute; top: -2px; bottom: -2px; width: 2px; background: var(--text-faint); opacity: .6; }
.cap-meta { font-size: var(--t-3); color: var(--text-muted); text-align: right; }
.cap-meta .cap-over { color: var(--danger); font-weight: 600; }
@media (max-width: 640px) { .cap-row { grid-template-columns: 84px 1fr; } .cap-meta { grid-column: 2; text-align: left; } }

/* ===================== Teilzahlungen ===================== */
.pay-panel { background: var(--e2); border: 1px solid var(--border); border-radius: var(--r-card); padding: var(--s4) 18px; margin-bottom: var(--s4); }
.pay-head { display: flex; align-items: center; gap: var(--s4-5); flex-wrap: wrap; }
.pay-kpi { display: flex; flex-direction: column; }
.pay-lbl { font-size: var(--t-1); text-transform: uppercase; letter-spacing: var(--ls-versal); color: var(--text-faint); }
.pay-val { font-family: var(--font-zahl); font-variant-numeric: tabular-nums; font-size: var(--t-5); font-weight: 700; }
.pay-of { font-size: var(--t-3); }
.pay-bar { height: 7px; background: var(--e4); border-radius: var(--r-pill); overflow: hidden; margin-top: var(--s3); }
.pay-bar-fill { height: 100%; background: linear-gradient(90deg, var(--st-done), #57d873); border-radius: var(--r-pill); transition: width var(--d-lang) var(--ease); }
.pay-list { margin-top: var(--s3); display: flex; flex-direction: column; gap: var(--s0-5); }
.pay-row { display: flex; align-items: center; gap: var(--s3); padding: 7px 0; border-top: 1px solid var(--border); font-size: var(--t-4); }
.pay-row .pay-date { color: var(--text-muted); min-width: 78px; font-size: var(--t-3); }
.pay-row .pay-note { flex: 1; color: var(--text); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pay-row .pay-amt { color: var(--st-done); font-variant-numeric: tabular-nums; }

/* ===================== USt-Voranmeldung ===================== */
.ust-table { display: flex; flex-direction: column; }
.ust-row { display: grid; grid-template-columns: 1.4fr 1fr 1fr 1fr; gap: var(--s2-5); padding: var(--s2-5) var(--s5); border-bottom: 1px solid var(--border); align-items: center; }
.ust-row:last-child { border-bottom: 0; }
.ust-row span:not(.ust-p) { text-align: right; font-variant-numeric: tabular-nums; font-size: var(--t-4); }
.ust-row .ust-p { font-weight: 600; font-size: var(--t-4); }
.ust-head { font-size: var(--t-2); text-transform: uppercase; letter-spacing: var(--ls-versal); color: var(--text-faint); background: var(--e3); }
.ust-head span { font-family: var(--font); font-weight: 500 !important; }
.ust-row .is-neg { color: var(--st-done); }
@media (max-width: 600px) { .ust-row { grid-template-columns: 1fr 1fr; } .ust-head { display: none; } }

/* ===================== Umsatz-Heatmap ===================== */
.heatmap { display: flex; flex-direction: column; gap: 5px; min-width: 520px; }
.hm-row { display: grid; grid-template-columns: 40px repeat(12, 1fr); gap: 5px; align-items: center; }
.hm-y { font-size: var(--t-2); color: var(--text-muted); font-variant-numeric: tabular-nums; }
.hm-m { font-size: var(--t-1); color: var(--text-faint); text-align: center; }
.hm-cell { height: 26px; border-radius: var(--r-xs); border: 1px solid var(--border); transition: transform var(--d-mittel) var(--ease); }
.hm-cell:hover { transform: scale(1.12); border-color: var(--accent-line); }
.heatmap-scroll { overflow-x: auto; }

/* ===================== Kontoauszug-Import ===================== */
.bank-list { display: flex; flex-direction: column; gap: var(--s2); max-height: 52vh; overflow-y: auto; }
.bank-row { display: grid; grid-template-columns: 1fr 260px; gap: 14px; align-items: center; padding: var(--s2-5) var(--s3); background: var(--e2); border: 1px solid var(--border); border-radius: var(--r-sm); }
.bank-amt { font-size: var(--t-4); font-weight: 700; color: var(--st-done); }
.bank-meta { font-size: var(--t-3); margin-top: 1px; }
.bank-purpose { font-size: var(--t-2); margin-top: var(--s0-5); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bank-assign { display: flex; flex-direction: column; gap: var(--s1); }
.bank-reason { font-size: var(--t-1); color: var(--st-done); }
@media (max-width: 620px) { .bank-row { grid-template-columns: 1fr; } }

/* ===================== Projekt-Rentabilität ===================== */
.prof-list { display: flex; flex-direction: column; gap: var(--s3); }
.prof-row { display: grid; grid-template-columns: 1fr 140px 90px; gap: 14px; align-items: center; cursor: pointer; }
.prof-row:hover .prof-title { color: var(--accent); }
.prof-main { min-width: 0; }
.prof-title { font-size: var(--t-4); font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.prof-sub { font-size: var(--t-2); }
.prof-track { position: relative; height: 10px; background: var(--e4); border-radius: var(--r-pill); overflow: hidden; }
.prof-fill { height: 100%; border-radius: var(--r-pill); transition: width var(--d-lang) var(--ease); }
.prof-cap { position: absolute; top: -2px; bottom: -2px; width: 2px; background: var(--text-faint); opacity: .7; }
.prof-rate { font-size: var(--t-4); font-variant-numeric: tabular-nums; text-align: right; font-weight: 600; }
@media (max-width: 640px) { .prof-row { grid-template-columns: 1fr 84px; } .prof-track { display: none; } }

/* ===================== Tastenkürzel ===================== */
kbd { display: inline-block; min-width: 20px; padding: var(--s0-5) 7px; font-family: var(--font-zahl); font-size: var(--t-3); line-height: var(--lh-text); text-align: center; color: var(--text); background: var(--e4); border: 1px solid var(--border); border-bottom-width: 2px; border-radius: var(--r-sm); }
.kbd-keys { display: inline-flex; align-items: center; gap: 5px; min-width: 130px; }

/* ===================== Assistent (NEX) ===================== */
.nav__item--assist { position: relative; }
.panel--assist { border-color: var(--accent-line); background: linear-gradient(180deg, var(--accent-soft), transparent 60%); }
.panel--assist h2 { display: flex; align-items: center; gap: var(--s2); }
.status-box { margin-top: var(--s3); padding: 11px 14px; border-radius: var(--r-ctrl); font-size: var(--t-4); line-height: var(--lh-text); display: flex; gap: 9px; align-items: flex-start; border: 1px solid var(--border); }
.status-box svg { width: 16px; height: 16px; flex: none; margin-top: 1px; }
.status-box code { background: rgba(255,255,255,.08); padding: 1px 5px; border-radius: var(--r-xs); font-size: var(--t-3); font-family: var(--font-zahl); }
.status-box.is-ok { background: color-mix(in srgb, var(--st-done) 10%, transparent); border-color: color-mix(in srgb, var(--st-done) 30%, transparent); color: var(--text); }
.status-box.is-ok svg { color: var(--st-done); }
.status-box.is-err { background: color-mix(in srgb, var(--danger) 9%, transparent); border-color: color-mix(in srgb, var(--danger) 28%, transparent); color: var(--text); }
.status-box.is-err svg { color: var(--danger); }
.status-box.is-loading { color: var(--text-muted); }
.status-box[hidden] { display: none; }


/* ---- Assistent: Oberflaeche ----
   Verlauf scrollt, die Eingabe bleibt stehen. Antworten koennen eine Kennzahl-
   oder Listenkarte tragen, damit Zahlen sofort lesbar sind statt in Fliesstext. */
.asst-wrap { display: flex; flex-direction: column; height: calc(100vh - 164px); min-height: 460px; max-width: 780px; margin: 0 auto; }
.asst-log { flex: 1; overflow-y: auto; display: flex; flex-direction: column; gap: var(--s4-5); padding: var(--s1) var(--s0-5) var(--s4-5); scroll-behavior: smooth; }

.asst-hero { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; padding: var(--s4-5); }
.asst-hero__mark { width: 58px; height: 58px; border-radius: var(--r-md); background: var(--accent-soft); display: grid; place-items: center; margin-bottom: 18px; }
.asst-hero__mark .nx-mark { width: 28px; height: 28px; }
.asst-hero h2 { font-size: var(--t-6); margin-bottom: var(--s2-5); }
.asst-hero p { color: var(--text-muted); font-size: var(--t-4); line-height: var(--lh-lesen); max-width: 460px; margin: 0 auto 22px; }
.asst-chips { display: flex; flex-wrap: wrap; gap: var(--s2); justify-content: center; max-width: 620px; }
.asst-chip {
  padding: var(--s2) 14px; border-radius: var(--r-pill); background: var(--e3); border: 1px solid var(--border);
  color: var(--text-muted); font-size: var(--t-3); font-family: inherit; cursor: pointer;
  transition: border-color var(--d-schnell) var(--ease), color var(--d-schnell) var(--ease), background var(--d-schnell) var(--ease);
}
.asst-chip:hover { border-color: var(--accent-line); color: var(--text); background: var(--e4); }

.asst-msg { display: flex; gap: var(--s3); max-width: 100%; }
.asst-msg--user { justify-content: flex-end; }
.asst-bubble { background: var(--accent); color: var(--accent-ink); padding: var(--s2-5) 15px; border-radius: var(--r-md) 16px 4px 16px; max-width: 78%; font-size: var(--t-4); line-height: var(--lh-text); }
.asst-msg--asst { align-items: flex-start; }
.asst-avatar { flex: none; width: 30px; height: 30px; border-radius: var(--r-sm); background: var(--e4); display: grid; place-items: center; }
.asst-avatar .nx-mark { width: 16px; height: 16px; }
.asst-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: var(--s2-5); }
/* pre-line, weil die laengeren Auskuenfte aus der Wissensbasis in Absaetzen kommen.
   Ohne das klebte alles zu einer Wand zusammen. */
.asst-text { font-size: var(--t-4); line-height: var(--lh-lesen); color: var(--text); white-space: pre-line; }
.asst-actions { display: flex; flex-wrap: wrap; gap: var(--s2); }

.asst-stat { background: var(--e3); border: 1px solid var(--border); border-radius: var(--r-card); padding: var(--s4) 18px; }
.asst-stat__value { font-family: var(--font-display); font-size: var(--t-7); font-weight: 600; letter-spacing: var(--ls-display); line-height: var(--lh-eng); font-variant-numeric: tabular-nums; }
.asst-stat__label { font-size: var(--t-4); color: var(--text-muted); margin-top: 5px; }
.asst-stat__meta { font-size: var(--t-2); color: var(--text-faint); margin-top: 3px; }
.asst-stat.is-plus .asst-stat__value { color: var(--st-done); }
.asst-stat.is-minus .asst-stat__value { color: var(--danger); }

.asst-rows { border: 1px solid var(--border); border-radius: var(--r-card); overflow: hidden; }
.asst-row { display: flex; align-items: center; gap: var(--s3); padding: var(--s2-5) 14px; border-bottom: 1px solid var(--border); background: var(--e2); }
.asst-row:last-child { border-bottom: 0; }
.asst-row.is-klick { cursor: pointer; transition: background var(--d-schnell) var(--ease); }
.asst-row.is-klick:hover { background: var(--e3); }
.asst-row__main { flex: 1; min-width: 0; }
.asst-row__title { font-size: var(--t-4); font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.asst-row__sub { font-size: var(--t-2); color: var(--text-faint); margin-top: var(--s0-5); }
.asst-row__value { font-size: var(--t-4); font-variant-numeric: tabular-nums; flex: none; color: var(--text-muted); }
.asst-row__value.is-minus { color: var(--danger); }
.asst-empty { font-size: var(--t-4); color: var(--text-faint); padding: var(--s1) 0; }

.asst-composer { display: flex; gap: var(--s2); align-items: center; padding-top: 14px; border-top: 1px solid var(--border); }
.asst-composer input { flex: 1; font-size: var(--t-4); padding: 13px var(--s4); }
.asst-composer .btn { height: 46px; width: 46px; padding: 0; justify-content: center; flex: none; }
.asst-fuss { font-size: var(--t-2); color: var(--text-faint); text-align: center; margin: var(--s2-5) 0 0; }

@media (max-width: 620px) {
  .asst-wrap { height: calc(100vh - 176px); }
  .asst-bubble { max-width: 90%; }
  .asst-chips { justify-content: flex-start; }
}

/* ========================= Postfach ========================= */
.mail-wrap { display: grid; grid-template-columns: 340px 1fr; gap: 14px; height: calc(100dvh - 168px); min-height: 460px; }
.mail-glasspane { position: relative; isolation: isolate; border: 1px solid var(--border); border-radius: var(--r-card); background: linear-gradient(158deg, rgba(255,255,255,.072), rgba(255,255,255,.018) 46%, rgba(255,255,255,.042)), rgba(12,18,27,.58); -webkit-backdrop-filter: blur(22px) saturate(150%); backdrop-filter: blur(22px) saturate(150%); }
.mail-list, .mail-read { position: relative; isolation: isolate; border: 1px solid var(--border); border-radius: var(--r-card); background: linear-gradient(158deg, rgba(255,255,255,.072), rgba(255,255,255,.018) 46%, rgba(255,255,255,.042)), rgba(12,18,27,.58); -webkit-backdrop-filter: blur(22px) saturate(150%); backdrop-filter: blur(22px) saturate(150%); box-shadow: inset 0 1px 0 rgba(255,255,255,.05); }
.mail-list { display: flex; flex-direction: column; min-height: 0; overflow: hidden; }
.mail-list__head { display: flex; justify-content: space-between; align-items: center; padding: 13px var(--s4); border-bottom: 1px solid var(--border); font-size: var(--t-4); font-weight: 600; }
.mail-list__items { flex: 1; overflow-y: auto; min-height: 0; }
/* Suche und Ungelesen-Schalter ueber der Liste. Der frueher hier stehende Fuss mit
   "Postfach trennen" ist entfallen - die Aktion sitzt jetzt im Ueberlaufmenue. */
.mail-list__tools { display: flex; align-items: center; gap: var(--s2); padding: 9px var(--s2-5); border-bottom: 1px solid var(--border); }
.mail-list__tools .search--sm { flex: 1; min-width: 0; max-width: none; padding: 5px var(--s2-5); }
.mail-list__tools .search--sm input { font-size: var(--t-3); }
.mail-list__tools .tagchip { flex: 0 0 auto; gap: 5px; }
.mail-list__tools .tagchip svg { width: 12px; height: 12px; }
/* Reiter Posteingang / Gesendet. Nur da, wenn der Server einen Gesendet-Ordner nennt. */
.mail-tabs { display: flex; gap: var(--s0-5); padding: var(--s1-5) var(--s1-5) 0; border-bottom: 1px solid var(--border); }
.mail-tabs button {
  flex: 1 1 0; min-width: 0; display: inline-flex; align-items: center; justify-content: center; gap: var(--s1-5);
  padding: var(--s2) var(--s2) 9px; border: 0; background: none; color: var(--text-faint);
  font: inherit; font-size: var(--t-3); font-weight: 600; cursor: pointer;
  border-bottom: 2px solid transparent; margin-bottom: -1px; white-space: nowrap;
  transition: color var(--d-schnell) var(--ease), border-color var(--d-schnell) var(--ease);
}
.mail-tabs button:hover { color: var(--text); }
.mail-tabs button.is-active { color: var(--text); border-bottom-color: var(--accent); }
.mail-tabs svg { width: 14px; height: 14px; flex: 0 0 auto; }
.mail-tabs .n { font-size: var(--t-1); font-weight: 700; color: var(--accent); background: var(--accent-soft); border-radius: var(--r-sm); padding: 1px var(--s1-5); }
.mrow__an { color: var(--text-faint); font-weight: 500; margin-right: 5px; }
.mail-list__more { display: flex; flex-direction: column; align-items: center; gap: var(--s1-5); padding: var(--s2-5); border-top: 1px solid var(--border); text-align: center; }
.mail-list__more .faint { font-size: var(--t-2); line-height: var(--lh-text); }
.mrow { display: flex; align-items: flex-start; gap: var(--s2-5); width: 100%; text-align: left; padding: 11px 14px; background: transparent; border: 0; border-bottom: 1px solid var(--border); cursor: pointer; color: var(--text); font-family: inherit; }
.mrow:hover { background: rgba(255,255,255,.045); }
.mrow.is-active { background: rgba(61,119,187,.12); }
.mrow__dot { width: 8px; height: 8px; border-radius: var(--r-pill); background: transparent; margin-top: 5px; flex: none; }
.mrow.is-unread .mrow__dot { background: var(--accent-2); box-shadow: 0 0 0 3px rgba(127,178,238,.15); }   /* war rgba(90,147,214) - der Akzentton von VOR dem 27.08. */
.mrow.is-unread .mrow__from { font-weight: 700; color: var(--text); }
.mrow__main { min-width: 0; flex: 1; display: flex; flex-direction: column; gap: var(--s0-5); }
.mrow__from { font-size: var(--t-4); font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mrow__subj { font-size: var(--t-3); color: var(--text-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mrow__date { font-size: var(--t-2); color: var(--text-faint); flex: none; white-space: nowrap; margin-top: var(--s0-5); }
.mail-read { min-width: 0; overflow-y: auto; }
.mail-read__empty { height: 100%; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--s3); color: var(--text-faint); padding: 40px; }
.mail-read__empty .empty__ico, .mail-read__empty svg { width: 40px; height: 40px; opacity: .6; }
.mail-msg__head { padding: 22px 26px var(--s4); border-bottom: 1px solid var(--border); }
.mail-msg__head h2 { font-size: var(--t-6); margin-bottom: var(--s3); line-height: var(--lh-titel); }
.mail-msg__meta { display: flex; align-items: center; gap: var(--s3); flex-wrap: wrap; font-size: var(--t-4); color: var(--text-muted); }
.mail-msg__actions { margin-top: var(--s4); }
.mail-msg__body { padding: 22px 26px; }
.mail-html { width: 100%; border: 0; background: #fff; border-radius: var(--r-sm); min-height: 220px; display: block; }
.mail-text { white-space: pre-wrap; word-break: break-word; font-family: var(--font); font-size: var(--t-4); line-height: var(--lh-lesen); margin: 0; color: var(--text); }
.mail-att { padding: var(--s1) 26px 22px; display: flex; gap: var(--s2-5); flex-wrap: wrap; align-items: center; border-top: 1px solid var(--border); margin-top: var(--s1); padding-top: var(--s4); }
.mail-att__lbl { display: inline-flex; align-items: center; gap: var(--s1-5); font-size: var(--t-3); color: var(--text-faint); font-weight: 600; }
.mail-att__lbl svg { width: 15px; height: 15px; }
.mail-att__i { display: inline-flex; align-items: center; gap: var(--s1-5); font-size: var(--t-3); padding: 7px var(--s3); border: 1px solid var(--border); border-radius: var(--r-pill); color: var(--text); text-decoration: none; cursor: pointer; transition: background var(--d-schnell) var(--ease), border-color var(--d-schnell) var(--ease); }
.mail-att__i:hover { background: var(--accent-soft); border-color: var(--accent-line); color: var(--accent-2); }
.mail-att__i svg { width: 14px; height: 14px; flex: none; }
.mail-adv { margin: -2px 0 var(--s2); }
.mail-adv summary { cursor: pointer; font-size: var(--t-3); color: var(--text-muted); padding: var(--s1-5) 0; user-select: none; }
.mail-adv[open] summary { margin-bottom: var(--s2-5); }
@media (max-width: 900px) { .mail-wrap { grid-template-columns: 1fr; height: auto; } .mail-list { max-height: 340px; } .mail-read { min-height: 360px; } }
.mail-doc-note { display: flex; align-items: center; gap: 9px; font-size: var(--t-4); color: var(--accent-2); background: var(--accent-soft); border: 1px solid var(--accent-line); border-radius: var(--r-ctrl); padding: var(--s2-5) 13px; }
.mail-doc-note svg { width: 16px; height: 16px; flex: none; }
.panel--assist h2 svg { width: 18px; height: 18px; color: var(--accent-2); }



.loading-line { display: flex; align-items: center; gap: var(--s2-5); color: var(--text-muted); font-size: var(--t-4); }
.loading-dots { display: inline-flex; gap: var(--s1); }
.loading-dots i { width: 6px; height: 6px; border-radius: var(--r-pill); background: var(--accent-2); animation: dotbounce 1s infinite; }
.loading-dots i:nth-child(2) { animation-delay: .15s; }
.loading-dots i:nth-child(3) { animation-delay: .3s; }
@keyframes dotbounce { 0%,100% { transform: translateY(0); opacity: .5; } 50% { transform: translateY(-4px); opacity: 1; } }
.hint-box { display: flex; align-items: center; gap: var(--s2); padding: var(--s2-5) var(--s3); background: var(--danger-soft); border-radius: var(--r-sm); font-size: var(--t-4); color: var(--text); }
.hint-box svg { width: 16px; height: 16px; color: var(--danger); flex: none; }



/* ========================= Onboarding wizard ========================= */

/* ========================= Design & Branding view =========================
   .theme-toggle, .theme-opt, .swatches, .swatch, .looks, .look, .look-prev,
   .lp-bar und .look-name standen hier als Reste einer frueheren Fassung der
   Ansicht - kein einziges davon wurde von app.js noch erzeugt. Beim Aufraeumen
   am 27.08.2026 mitgegangen. Uebrig bleibt das, was die Ansicht wirklich
   benutzt: der Farbwaehler. */
input[type=color] { width: 46px; height: 34px; padding: var(--s0-5); border-radius: var(--r-sm); border: 1px solid var(--border-strong); background: var(--e1); cursor: pointer; }

/* ========================= NEXUP Studio im Hilfebereich =========================
   Die Website erzaehlt das Studio in vier Teilen: der Mensch, die drei
   direkten Wege, die drei Bereiche, der Ablauf. Alle vier stehen jetzt auch
   in der App, im selben Wortlaut und im selben Material. Was hier steht, ist
   die App-Fassung derselben Bauteile: gleiche Anmutung, aber auf den
   Groessenleitern der App (--t-*, --s-*) statt auf denen der Seite, weil eine
   Arbeitsflaeche dichter gesetzt ist als eine Startseite.

   Bis zum 27.08.2026 stand hier stattdessen .promo: eine einzelne Werbekachel
   mit vier Zeilen Text, blauer Rahmen, blauer Verlauf - das einzige Bauteil
   der App, das nirgends auf der Website vorkam.
   ============================================================================ */

/* Die Spalte des Hilfebereichs. Vorher 760px; der Mensch-Block (Bild neben
   Text), die drei Bereiche und die vierteilige Bahn brauchen mehr. */
.hilfe { max-width: 940px; }

/* Trennmarke: hier hoert die Hilfe auf und das Studio faengt an. */
.studio-marke { display: flex; align-items: center; gap: var(--s4); margin-top: var(--s5); color: var(--text-faint); }
.studio-marke::before, .studio-marke::after { content: ""; flex: 1; height: 1px; background: var(--border); }
.studio-marke span { display: inline-flex; align-items: center; gap: var(--s2); font-size: var(--t-1); letter-spacing: var(--ls-micro); text-transform: uppercase; font-weight: 600; white-space: nowrap; }
.studio-marke svg { width: 13px; height: 13px; }
.studio-marke svg polygon { fill: currentColor; }
.studio-marke svg polygon:first-child { fill: var(--accent-2); }

/* ---- Der Mensch ---------------------------------------------------------
   Das Bauteil, an dem am meisten haengt: es ist das einzige Gesicht im
   ganzen Produkt. Aufbau wie auf der Website - Foto links in eigener Spalte,
   das N gross dahinter, Text rechts, Signatur als Abschluss. */
.mensch {
  position: relative; overflow: hidden; isolation: isolate;
  --mensch-luft: var(--s6);
  display: grid;
  grid-template-columns: minmax(0, clamp(190px, 26vw, 280px)) minmax(0, 1fr);
  gap: clamp(24px, 4vw, 48px); align-items: center;
  padding: var(--mensch-luft) var(--s6) 0;
}
/* Der Schein in der Ecke. Er ist der Grund, warum die Karte leuchtet statt
   nur hell zu sein - dasselbe Prinzip wie die Lichthoefe hinter dem Glas. */
.mensch-schein {
  position: absolute; left: -14%; top: -42%; width: min(70%, 520px); aspect-ratio: 1;
  border-radius: 50%; pointer-events: none; z-index: 0;
  background: radial-gradient(circle, rgba(93,151,220,.42), rgba(61,119,187,.14) 44%, transparent 70%);
  filter: blur(28px);
}
/* align-self:stretch plus der negative Rand: die Spalte beginnt an der
   Oberkante der Karte statt unter dem Polster. Nur so ist top:50% wirklich
   die Mitte der Karte. Das Foto haengt weiter unten an der Kante. */
.mensch-bild {
  position: relative; z-index: 1; align-self: stretch;
  margin-top: calc(-1 * var(--mensch-luft)); padding-top: var(--s7);
  display: grid; place-items: end center; min-height: 0;
}
/* .zeichen ist die Auszeichnung fuer eine ABSICHTLICH grosse, rein dekorative
   Marke. Die Symbolwache der Pruefsuite meldet jedes SVG ueber 40px als
   Unfall - dreimal ist in diesem Projekt ein Symbol ohne Groessenangabe auf
   90, 142 und einmal 615 Pixel gewachsen. Diese eine Klasse ist die Ausnahme,
   und sie steht nur da, wo eine Groesse in CSS fest gesetzt ist.
   Wer sie irgendwo hinschreibt, um eine Meldung loszuwerden, hat den Fehler
   nicht behoben, sondern zugedeckt. */
.zeichen { pointer-events: none; }

/* Das Zeichen steht HINTER der Person, mittig zur Karte, nicht neben ihr. */
.mensch-zeichen { position: absolute; left: 52%; top: 50%; translate: -50% -50%; width: min(118%, 330px); max-width: none; height: auto; z-index: 0; pointer-events: none; }
.mensch-zeichen polygon { fill: rgba(255,255,255,.055); }
.mensch-zeichen polygon:first-child { fill: rgba(127,178,238,.26); }
/* Der Freisteller endet hart an der Unterkante. Ein kurzer Auslauf setzt ihn
   auf die Karte, statt ihn abzuschneiden. */
.mensch-bild img {
  position: relative; z-index: 1; width: min(100%, 280px); height: auto; display: block;
  -webkit-mask-image: linear-gradient(180deg, #000 88%, transparent);
  mask-image: linear-gradient(180deg, #000 88%, transparent);
}
.mensch-text { position: relative; z-index: 1; min-width: 0; padding-bottom: var(--s6); }
.mensch-text h2 { font-size: var(--t-7); letter-spacing: var(--ls-display); line-height: var(--lh-eng); font-weight: 600; }
.mensch-text h2 em { font-style: normal; color: var(--accent-2); }
.mensch-text p { margin: var(--s3) 0 0; color: var(--text-muted); font-size: var(--t-4); line-height: var(--lh-lesen); }
/* Der Merksatz ist eine Stufe fuer sich: heller als der Fliesstext, kleiner
   als die Ueberschrift. */
.mensch-text .mensch-satz { margin-top: var(--s2); color: var(--text); font-size: var(--t-5); font-weight: 600; letter-spacing: var(--ls-h3); }
/* Die Signatur schliesst den Block ab wie eine Unterschrift unter einem Brief.
   Der groessere Abstand setzt sie ab; eine Haarlinie waere die vierte
   waagerechte Kante in einer Karte, die schon Rahmen und Lichtkante traegt. */
.mensch-text .mensch-signatur { display: flex; align-items: center; gap: var(--s2-5); margin-top: var(--s6); color: var(--text); font-size: var(--t-4); font-weight: 600; letter-spacing: var(--ls-h3); }
.mensch-signatur svg { width: 18px; height: 18px; flex: none; }
.mensch-signatur svg polygon { fill: currentColor; opacity: .55; }
.mensch-signatur svg polygon:first-child { fill: var(--accent-2); opacity: 1; }
/* minmax(0,1fr) statt 1fr: 1fr traegt min-width:auto und sprengt schmal die
   Karte. Dieselbe Falle wie auf der Website. */
@media (max-width: 720px) {
  .mensch { grid-template-columns: minmax(0, 1fr); gap: var(--s5); padding: var(--s6) var(--s5) 0; }
  .mensch-bild { order: -1; justify-items: center; align-self: auto; margin-top: 0; padding-top: 0; }
  .mensch-bild img { width: min(74%, 240px); }
  .mensch-zeichen { width: min(86%, 240px); left: 50%; }
  .mensch-text { padding-bottom: var(--s5); text-align: center; }
  .mensch-signatur { justify-content: center; }
}

/* Zusaetze in einer Panel-Kopfzeile, die am Handy nur Platz wegnehmen. Die
   Kopfzeile ist eine Zeile ohne Umbruch; ein zweiter Text darin schiebt bei
   340px die Ueberschrift heraus. */
@media (max-width: 560px) { .nur-breit { display: none; } }

/* ---- Die drei direkten Wege --------------------------------------------- */
.direkt { display: flex; flex-direction: column; gap: var(--s1); }
.direkt a { display: flex; align-items: center; gap: var(--s3); padding: var(--s1) 0; font-size: var(--t-5); font-weight: 600; letter-spacing: var(--ls-h3); text-decoration: none; color: var(--text); }
.direkt a s {
  display: grid; place-items: center; width: 38px; height: 38px; flex: none;
  border-radius: var(--r-sm); text-decoration: none;
  background: rgba(255,255,255,.06); box-shadow: inset 0 0 0 1px var(--border);
  color: var(--accent-2); transition: background-color var(--d-schnell) var(--ease);
}
.direkt a s svg { width: 17px; height: 17px; }
.direkt a:hover s { background: rgba(61,119,187,.26); }
.direkt em { display: block; font-style: normal; font-size: var(--t-1); letter-spacing: var(--ls-micro); text-transform: uppercase; color: var(--text-faint); font-weight: 500; margin-bottom: 2px; }

/* ---- Die drei Bereiche --------------------------------------------------- */
.bereiche { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: var(--s4); }
.bereich { position: relative; isolation: isolate; display: flex; flex-direction: column; padding: var(--s5); border-radius: var(--r-md); background: rgba(255,255,255,.03); box-shadow: inset 0 0 0 1px var(--border); }
.bereich h3 { font-size: var(--t-5); line-height: var(--lh-titel); letter-spacing: var(--ls-h3); }
.bereich-lead { margin: var(--s3) 0 0; font-size: var(--t-4); font-weight: 600; color: var(--text); line-height: var(--lh-text); }
.bereich-lead em { font-style: normal; color: var(--accent-2); }
.bereich-text { margin: var(--s2) 0 0; color: var(--text-muted); font-size: var(--t-3); line-height: var(--lh-lesen); }
/* Die Schlagwoerter sind das, was ein Kunde sucht, wenn er nicht weiss, wie
   er seine Frage nennen soll. Deshalb stehen sie da und nicht im Fliesstext. */
.schlagwoerter { margin: auto 0 0; padding-top: var(--s3); margin-top: var(--s4); border-top: 1px solid var(--border); display: flex; flex-wrap: wrap; gap: var(--s1-5); list-style: none; }
.schlagwoerter li { font-size: var(--t-1); letter-spacing: var(--ls-versal); text-transform: uppercase; color: var(--text-muted); padding: 5px var(--s2-5); border-radius: var(--r-pill); box-shadow: inset 0 0 0 1px var(--border); }

/* ---- Die Bahn ------------------------------------------------------------
   Der einzige Abschnitt der Website OHNE Glas: sein Material kommt aus Licht
   statt aus Flaeche. Genau so hier. */
.bahn { position: relative; --kreis: 44px; --bahn-kopf: calc(var(--kreis) / 2); display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--s5); padding-top: var(--bahn-kopf); list-style: none; }
/* Die Linie laeuft an beiden Enden ins Nichts. Rechts wird sie schwaecher
   statt zu enden: der vierte Schritt heisst Betrieb und Ausbau, er hoert
   nicht auf. */
.bahn::before {
  content: ""; position: absolute; left: 0; right: 0; top: var(--bahn-kopf); height: 1px;
  background: linear-gradient(90deg, transparent, rgba(127,178,238,.58) 4%, rgba(127,178,238,.46) 38%, rgba(127,178,238,.28) 72%, rgba(127,178,238,.10) 93%, transparent);
}
.takt { position: relative; min-width: 0; padding-top: calc(var(--kreis) / 2 + var(--s4)); }
/* Der Kreis sitzt mit seiner LINKEN Kante auf der Textkante, nicht mittig
   darauf: sonst haengt die erste Spalte einen halben Kreis aus der Bahn.
   Der Grund unter der Toenung ist deckend, sonst laeuft die Haarlinie
   sichtbar durch die Zahl. */
.takt-nr {
  position: absolute; left: 0; top: 0; translate: 0 -50%;
  display: grid; place-items: center; width: var(--kreis); height: var(--kreis); border-radius: 50%;
  background: linear-gradient(rgba(61,119,187,.20), rgba(61,119,187,.08)), rgba(9,13,20,.94);
  box-shadow: inset 0 0 0 1px rgba(127,178,238,.28), 0 0 14px 0 rgba(127,178,238,.11);
  font-size: var(--t-5); font-weight: 700; line-height: 1; letter-spacing: var(--ls-h3);
  color: var(--accent-2); font-variant-numeric: tabular-nums;
}
.takt h3 { font-size: var(--t-5); line-height: var(--lh-titel); letter-spacing: var(--ls-h3); }
.takt p { margin: var(--s2) 0 0; color: var(--text-muted); font-size: var(--t-4); line-height: var(--lh-lesen); }
/* Vier Spalten brauchen Platz. Darunter kippt die Bahn in die Senkrechte -
   dieselbe Linie, dieselben Kreise, nur gedreht. */
@media (max-width: 860px) {
  .bahn { grid-template-columns: minmax(0, 1fr); gap: var(--s6); padding-top: 0; padding-left: calc(var(--kreis) + var(--s4)); }
  .bahn::before { left: calc(var(--kreis) / 2); right: auto; top: 0; bottom: 0; width: 1px; height: auto; background: linear-gradient(180deg, transparent, rgba(127,178,238,.58) 4%, rgba(127,178,238,.46) 38%, rgba(127,178,238,.28) 72%, rgba(127,178,238,.10) 93%, transparent); }
  .takt { padding-top: 0; }
  .takt-nr { left: calc(-1 * (var(--kreis) + var(--s4))); top: 50%; }
}

/* ---- Der Fuss ------------------------------------------------------------ */
.studio-fuss { display: flex; flex-direction: column; align-items: center; gap: var(--s4); text-align: center; padding: var(--s6) var(--s5); }
.studio-fuss img { width: 148px; height: auto; opacity: .9; }
.studio-fuss p { margin: 0; max-width: 46ch; color: var(--text-muted); font-size: var(--t-3); line-height: var(--lh-lesen); }

.powered { display: block; text-align: center; font-size: var(--t-2); color: var(--text-faint); text-decoration: none; padding: var(--s2) 0 var(--s0-5); }
.powered b { color: var(--text-muted); font-weight: 600; }
.powered:hover b { color: var(--accent-2); }
/* Stand bis zum 27.08.2026 als reinweiss gefuellter Knopf in der dunklen
   Seitenspalte - das lauteste Element der ganzen App und nirgends auf der
   Website zu finden. Er traegt jetzt dasselbe Rezept wie jeder andere
   Hauptknopf (`.tat`) und faellt trotzdem auf, weil er der einzige gefuellte
   Knopf in der Spalte ist. */
.install-btn {
  display: flex; align-items: center; gap: var(--s3); width: 100%;
  padding: var(--s2-5) var(--s3); border-radius: var(--r-pill); border: 0;
  background: linear-gradient(150deg, #3a72b4, #26527f); color: #fff;
  font-size: var(--t-4); font-weight: 600; cursor: pointer; font-family: inherit;
  box-shadow: inset 0 1px 0 rgba(255,255,255,.34), 0 10px 26px -14px rgba(61,119,187,.9);
  transition: transform var(--d-mittel) var(--ease), box-shadow var(--d-mittel) var(--ease), filter var(--d-schnell) var(--ease);
}
@media (hover: hover) {
  .install-btn:hover { transform: translateY(-2px); filter: brightness(1.06);
    box-shadow: inset 0 1px 0 rgba(255,255,255,.4), 0 18px 40px -16px rgba(61,119,187,.95); }
}
.install-btn:active { transform: scale(.97); transition-duration: var(--d-druck); }
.install-btn .nav__ico { color: #fff; }

/* ========================= FAQ ========================= */
.faq { display: flex; flex-direction: column; }
.faq-item { border-bottom: 1px solid var(--border); }
.faq-item:last-child { border-bottom: 0; }
.faq-q { width: 100%; display: flex; align-items: center; justify-content: space-between; gap: var(--s3); padding: 15px var(--s5); background: transparent; border: 0; color: var(--text); font-size: var(--t-4); font-weight: 600; cursor: pointer; text-align: left; font-family: inherit; }
.faq-q svg { width: 16px; height: 16px; color: var(--text-faint); transition: transform var(--d-mittel) var(--ease); flex: none; }
.faq-q.is-open svg { transform: rotate(90deg); color: var(--accent); }
.faq-a { padding: 0 var(--s5) var(--s4); color: var(--text-muted); font-size: var(--t-4); line-height: var(--lh-lesen); }
.faq-a p { margin: 0; }
.faq-a b { color: var(--text); font-weight: 600; }

/* Karten-Hover mit Akzent-Glow (wie NEXUP-Studio-Website) */
.ccard, .pcard { transition: transform var(--d-mittel) var(--ease), border-color var(--d-schnell) var(--ease), box-shadow var(--d-mittel) var(--ease), background var(--d-schnell) var(--ease); }
.ccard:hover, .pcard:hover {
  border-color: var(--accent-line);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.08), 0 18px 44px -24px rgba(0,0,0,.7), 0 0 0 1px var(--accent-line), 0 10px 34px -14px var(--accent-soft), 0 0 34px -4px var(--accent-soft);
}

/* ========================= Attachments / Belege ========================= */
.attach-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(94px, 1fr)); gap: var(--s3); }
.attach { position: relative; display: flex; flex-direction: column; gap: var(--s1-5); }
.attach__thumb { height: 72px; border-radius: var(--r-sm); background-color: var(--e4); background-size: cover; background-position: center; background-repeat: no-repeat; border: 1px solid var(--border); cursor: pointer; display: grid; place-items: center; color: var(--text-faint); transition: border-color var(--d-schnell) var(--ease); }
.attach__thumb:hover { border-color: var(--accent-line); }
.attach__file svg { width: 26px; height: 26px; }
.attach__name { font-size: var(--t-1); color: var(--text-faint); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.attach__del { position: absolute; top: -6px; right: -6px; width: 22px; height: 22px; border-radius: var(--r-pill); border: 1px solid var(--border-strong); background: var(--e3); color: var(--text-muted); display: grid; place-items: center; cursor: pointer; opacity: 0; transition: opacity var(--d-schnell) var(--ease); }
.attach:hover .attach__del { opacity: 1; }
.attach__del:hover { color: var(--danger); }
.attach__del svg { width: 12px; height: 12px; }

/* ========================= NEXUP mark (splash/lock) ========================= */
.nx-mark { color: var(--text); }
.nx-mark .b { fill: var(--accent); }
.nx-mark polygon:not(.b) { fill: currentColor; }


/* ========================= Lock screen ========================= */
/* Flex statt Grid mit margin:auto - so bleibt die Karte zentriert, laeuft bei kleinen
   Fenstern aber sauber in den Scroll statt oben aus dem Bild zu wandern. */
.lock-screen { position: fixed; inset: 0; z-index: 250; display: flex; align-items: center; justify-content: center; overflow-y: auto; overscroll-behavior: contain; padding: var(--s5); background: radial-gradient(58% 50% at 50% 42%, rgba(61,119,187,.12), transparent 70%); }
.lock-box, .auth-box { margin: auto; }
.lock-screen[hidden] { display: none; }
.lock-box {
  position: relative; isolation: isolate;
  display: flex; flex-direction: column; align-items: center; gap: var(--s3); text-align: center;
  padding: 40px 40px 34px; width: 100%; max-width: 380px;
  background:
    linear-gradient(158deg, rgba(255,255,255,.072), rgba(255,255,255,.018) 46%, rgba(255,255,255,.042)),
    rgba(12,18,27,.72);
  -webkit-backdrop-filter: blur(22px) saturate(150%); backdrop-filter: blur(22px) saturate(150%);
  border: 1px solid transparent; border-radius: var(--r-lg);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.16),
    0 2px 6px rgba(0,0,0,.36),
    0 44px 90px -54px rgba(0,0,0,.95);
}
.lock-box::before {
  content: ""; position: absolute; inset: 0; border-radius: inherit; padding: 1px;
  background: linear-gradient(152deg, rgba(255,255,255,.42), rgba(255,255,255,.05) 44%, rgba(127,178,238,.32));
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor; mask-composite: exclude; pointer-events: none; z-index: 0;
}
.lock-mark { width: 60px; height: 60px; }
.lock-mark svg { width: 60px; height: 60px; }
.lock-tile { width: 62px; height: 62px; margin-bottom: var(--s1); filter: drop-shadow(0 16px 30px rgba(0,0,0,.5)) drop-shadow(0 0 26px rgba(61,119,187,.25)); }
.lock-tile img { width: 62px; height: 62px; display: block; }
.lock-title { font-family: var(--font-display); font-size: var(--t-6); font-weight: 700; }
.lock-sub { color: var(--text-faint); font-size: var(--t-4); margin: 0; }
.lock-input { width: 210px; text-align: center; font-size: var(--t-6); letter-spacing: 8px; padding: var(--s3); margin-top: var(--s2); }
.lock-err { color: var(--danger); font-size: var(--t-3); min-height: 16px; }
.shake { animation: shake var(--d-lang); }
@keyframes shake { 0%,100%{transform:translateX(0)} 20%,60%{transform:translateX(-7px)} 40%,80%{transform:translateX(7px)} }

/* ========================= Konto & Anmeldung =========================
   Erbt die Glas-Optik des Lock-Screens, ist aber breiter und linksbuendig,
   weil hier Formulare stehen und keine einzelne PIN-Eingabe. */
.auth-box {
  position: relative; isolation: isolate;
  display: flex; flex-direction: column; gap: 14px;
  padding: 38px 38px 30px; width: 100%; max-width: 400px;
  background:
    linear-gradient(158deg, rgba(255,255,255,.072), rgba(255,255,255,.018) 46%, rgba(255,255,255,.042)),
    rgba(12,18,27,.72);
  -webkit-backdrop-filter: blur(22px) saturate(150%); backdrop-filter: blur(22px) saturate(150%);
  border: 1px solid transparent; border-radius: var(--r-lg);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.16),
    0 2px 6px rgba(0,0,0,.36),
    0 44px 90px -54px rgba(0,0,0,.95);
  animation: auth-in var(--d-lang) var(--ease) both;
}
.auth-box--wide { max-width: 520px; }
/* Zentriert fuer die kurzen Masken ohne Formular (PIN-Schnellzugriff) */
.auth-box--center { align-items: center; text-align: center; max-width: 340px; }
.auth-box--center .auth-sub { margin-bottom: var(--s0-5); }
.auth-box--center .lock-input { width: 100%; letter-spacing: 6px; }
.auth-box--center .btn--wide { width: 100%; }
.auth-box::before {
  content: ""; position: absolute; inset: 0; border-radius: inherit; padding: 1px;
  background: linear-gradient(152deg, rgba(255,255,255,.42), rgba(255,255,255,.05) 44%, rgba(127,178,238,.32));
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor; mask-composite: exclude; pointer-events: none; z-index: 0;
}
@keyframes auth-in { from { opacity: 0; transform: translateY(10px) scale(.985); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .auth-box { animation: none; } }

.auth-mark { width: 42px; height: 42px; margin-bottom: var(--s0-5); }
.auth-mark svg { width: 42px; height: 42px; }
.auth-title { font-family: var(--font-display); font-size: var(--t-7); font-weight: 600; line-height: var(--lh-eng); margin: 0; letter-spacing: var(--ls-display); }
.auth-sub { color: var(--text-muted); font-size: var(--t-4); line-height: var(--lh-text); margin: -6px 0 var(--s1); }
.auth-form { gap: var(--s3); }
.auth-foot { color: var(--text-faint); font-size: var(--t-2); line-height: var(--lh-text); margin: var(--s0-5) 0 0; }
.auth-loginhint { font-size: var(--t-3); color: var(--text-muted); padding: 9px var(--s3); border-radius: var(--r-ctrl); background: var(--accent-soft); border: 1px solid var(--accent-line); }
.auth-loginhint b { color: var(--text); font-weight: 600; }
.auth-rules { display: flex; flex-wrap: wrap; gap: var(--s1-5) 14px; font-size: var(--t-2); color: var(--text-faint); }
.auth-rules .rule.is-ok { color: var(--st-done); }
.btn--wide { width: 100%; justify-content: center; }
/* Fehlte bisher app-weit: ein deaktivierter Button sah aus wie ein klickbarer. */
.btn:disabled, .btn[disabled] { opacity: .45; cursor: not-allowed; filter: saturate(.5); pointer-events: none; }
.linkbtn { background: none; border: 0; color: var(--text-muted); font: inherit; font-size: var(--t-3); padding: var(--s1); cursor: pointer; text-align: center; }
.linkbtn:hover { color: var(--accent-2); text-decoration: underline; }

/* Passwortfeld mit Auge und Feststelltasten-Warnung */
.pw-wrap { position: relative; display: block; }
.pw-wrap input { width: 100%; padding-right: 40px; }
.pw-eye {
  position: absolute; right: 6px; top: 50%; transform: translateY(-50%);
  width: 30px; height: 30px; display: grid; place-items: center;
  background: none; border: 0; border-radius: var(--r-sm); cursor: pointer;
  color: var(--text-faint); transition: color var(--d-schnell) var(--ease), background var(--d-schnell) var(--ease);
}
.pw-eye svg { width: 17px; height: 17px; }
.pw-eye:hover { color: var(--text); background: var(--e3); }
.pw-eye.is-on { color: var(--accent); }
.pw-caps { font-size: var(--t-2); color: var(--st-waiting); margin-top: var(--s0-5); }
.pw-caps[hidden] { display: none; }

/* Passwortstaerke: vier Segmente, Farbe folgt dem Fortschritt */
.pw-meter { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--s1); }
.pw-meter span { height: 3px; border-radius: var(--r-xs); background: var(--e4); transition: background var(--d-schnell) var(--ease); }
.pw-meter span.is-on { background: var(--st-waiting); }
.pw-meter[data-level="3"] span.is-on { background: var(--accent); }
.pw-meter[data-level="4"] span.is-on { background: var(--st-done); }

/* Wiederherstellungsschluessel: bewusst gross und weit gesperrt, er wird abgeschrieben.
   Bis zum 27.08.2026 stand hier eine Monoschrift. Sie ist raus, weil das Produkt genau
   eine Schrift hat. Mehrdeutig wird der Schluessel dadurch nicht: sein Alphabet
   (RC_ALPHA in app.js) laesst I, L, O und U bewusst aus, und Tabellenziffern plus
   .06em Sperrung geben ihm dieselbe Spaltenordnung wie vorher. */
.rc-code {
  font-family: var(--font-zahl); font-variant-numeric: tabular-nums;
  font-size: var(--t-5); letter-spacing: var(--ls-versal); line-height: var(--lh-lesen);
  text-align: center; word-break: break-all;
  padding: var(--s4) 14px; border-radius: var(--r-card);
  background: var(--e2); border: 1px dashed var(--border-strong); color: var(--text);
  user-select: all;
}
.rc-input { font-family: var(--font-zahl); font-variant-numeric: tabular-nums; letter-spacing: var(--ls-versal); }

/* ===== Einrichtungs-Assistent (gleiche Karte wie die Anmeldung) ===== */
.ob-rail { display: flex; align-items: center; gap: var(--s1-5); margin: -2px 0 var(--s1); flex-wrap: wrap; }
.ob-rail__i { display: inline-flex; align-items: center; gap: var(--s1-5); font-size: var(--t-2); color: var(--text-faint); }
.ob-rail__i i { width: 16px; height: 2px; border-radius: var(--r-xs); background: var(--e4); display: block; transition: background var(--d-schnell) var(--ease), width var(--d-lang) var(--ease); }
.ob-rail__i.is-done i { background: var(--accent-line); }
.ob-rail__i.is-active { color: var(--text); font-weight: 600; }
.ob-rail__i.is-active i { background: var(--accent); width: 26px; }

/* Schrittwechsel: nur der Inhalt bewegt sich, die Karte bleibt ruhig stehen */
.ob-in { animation: ob-slide var(--d-mittel) var(--ease) both; }
.ob-in-back { animation: ob-slide-back var(--d-mittel) var(--ease) both; }
@keyframes ob-slide { from { opacity: 0; transform: translateX(14px); } to { opacity: 1; transform: none; } }
@keyframes ob-slide-back { from { opacity: 0; transform: translateX(-14px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .ob-in, .ob-in-back { animation: none; } }

/* Live-Briefkopf: verkleinerte Rechnung, die beim Tippen mitwaechst */
.ob-prev { margin-bottom: var(--s2); }
.ob-prev__label { font-size: var(--t-2); color: var(--text-faint); margin-bottom: var(--s1-5); letter-spacing: .04em; }
.ob-prev__sheet {
  background: #fff; color: #1a2230; border-radius: var(--r-sm); padding: 14px var(--s4) var(--s3);
  box-shadow: 0 18px 40px -22px rgba(0,0,0,.85), inset 0 0 0 1px rgba(0,0,0,.06);
  font-size: var(--t-1); line-height: 1.5;
}
/* Im Hellen steht das weisse Blatt auf einer weissen Karte - es braucht eine echte Kante
   statt des Schlagschattens, der nur gegen Dunkel funktioniert. */
.ob-prev__head { display: flex; justify-content: space-between; align-items: flex-start; gap: var(--s3); margin-bottom: var(--s3); }
.ob-prev__logo { width: 40px; height: 40px; border-radius: var(--r-sm); overflow: hidden; display: grid; place-items: center; background: #eef1f6; flex: 0 0 auto; }
.ob-prev__logo img { max-width: 100%; max-height: 100%; object-fit: contain; }
.ob-prev__ini { font-weight: 700; font-size: var(--t-5); color: var(--accent); letter-spacing: .02em; }
.ob-prev__ph { width: 18px; height: 18px; border-radius: var(--r-xs); background: #dbe1ea; }
.ob-prev__meta { text-align: right; display: flex; flex-direction: column; gap: 1px; color: #5a6678; }
.ob-prev__meta b { color: #1a2230; font-size: var(--t-3); }
.ob-prev__name { font-weight: 700; font-size: var(--t-3); color: #1a2230; margin-bottom: 1px; }
.ob-prev__from { color: #5a6678; }
.ob-prev__leer { color: #b3bcc9; font-style: italic; }
.ob-prev__body { display: flex; flex-direction: column; gap: 5px; margin: var(--s3) 0 var(--s2-5); }
.ob-prev__body span { height: 5px; border-radius: var(--r-xs); background: #eef1f6; }
.ob-prev__body span:nth-child(2) { width: 78%; }
.ob-prev__body span:nth-child(3) { width: 55%; }
.ob-prev__foot { border-top: 1px solid #eef1f6; padding-top: 7px; color: #8a94a3; font-size: var(--t-1); }

/* Auswahlkacheln statt Chips: die Entscheidung traegt eine Erklaerung */
.ob-choice { display: grid; gap: var(--s2); }
.ob-opt {
  text-align: left; display: flex; flex-direction: column; gap: var(--s0-5); width: 100%;
  padding: 11px 13px; border-radius: var(--r-ctrl); cursor: pointer;
  background: var(--e2); border: 1px solid var(--border); color: var(--text);
  font: inherit; transition: border-color var(--d-schnell) var(--ease), background var(--d-schnell) var(--ease);
}
.ob-opt b { font-size: var(--t-4); font-weight: 600; }
.ob-opt span { font-size: var(--t-2); color: var(--text-muted); line-height: var(--lh-text); }
.ob-opt:hover { border-color: var(--border-strong); }
.ob-opt.is-active { border-color: var(--accent); background: var(--accent-soft); }

.ob-logo { display: flex; gap: var(--s4); align-items: center; }
.ob-logo__box { width: 62px; height: 62px; border-radius: var(--r-sm); background: var(--e2); border: 1px dashed var(--border-strong); display: grid; place-items: center; overflow: hidden; flex: 0 0 auto; }
.ob-logo__box img { max-width: 88%; max-height: 88%; object-fit: contain; }
.ob-logo__box span { font-weight: 700; font-size: var(--t-6); color: var(--accent); }
.ob-logo__box em { font-size: var(--t-1); color: var(--text-faint); font-style: normal; }
.ob-logo__ok { display: flex; align-items: center; gap: var(--s1-5); font-size: var(--t-2); color: var(--st-done); }
.ob-logo__ok svg { width: 14px; height: 14px; flex: 0 0 auto; }
.ob-logo__ok span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 190px; }

/* Kurzes Aufleuchten, wenn ein Logo uebernommen wurde - sonst uebersieht man,
   dass sich der Briefkopf oben schon geaendert hat. */
.is-neu { animation: logo-neu 1.1s var(--ease); }
@keyframes logo-neu {
  0% { box-shadow: 0 0 0 0 var(--accent); }
  35% { box-shadow: 0 0 0 4px var(--accent-soft); }
  100% { box-shadow: 0 0 0 0 rgba(61,119,187,0); }
}
@media (prefers-reduced-motion: reduce) { .is-neu { animation: none; outline: 2px solid var(--accent); } }

.ob-done { padding: 13px 15px; border-radius: var(--r-ctrl); background: var(--accent-soft); border: 1px solid var(--accent-line); }
.ob-done__h { display: flex; align-items: center; gap: var(--s2); font-weight: 600; font-size: var(--t-4); margin-bottom: 5px; }
.ob-done__h svg { width: 17px; height: 17px; color: var(--st-done); }

.ob-foot { display: flex; align-items: center; gap: var(--s2); margin-top: var(--s2); }
@media (max-width: 560px) {
  .ob-foot { flex-wrap: wrap; }
  .ob-foot .btn { flex: 1 1 auto; justify-content: center; }
  .ob-logo { flex-direction: column; align-items: flex-start; }
}

/* ===== Kunden- und Auftragslisten ===== */
/* Engeres Raster: bei 340 px Mindestbreite passten auf 1440 px nur zwei Spalten. */
.card-grid--proj { grid-template-columns: repeat(auto-fill, minmax(310px, 1fr)); align-items: stretch; }
.card-grid--proj .pcard { display: flex; flex-direction: column; }
.card-grid--proj .pcard__foot { margin-top: auto; }
.card-grid--cust { grid-template-columns: repeat(auto-fill, minmax(268px, 1fr)); }
.card-grid--notes { grid-template-columns: repeat(auto-fill, minmax(284px, 1fr)); }
.card-grid--notes + .grouphead { margin-top: var(--s5); }

/* Abschnittsmarke ueber einem Raster (Angepinnt / Uebrige) */
/* Wiederkehrende Aufgabe: eine Vorlage, keine Aufgabe. Deshalb kein Haekchen-Kaestchen,
   sondern der Takt als das eine Merkmal, das diese Zeilen unterscheidet. */
.rtask { display: flex; align-items: center; gap: var(--s3); padding: 11px var(--s5); border-bottom: 1px solid var(--border); cursor: pointer; transition: background var(--d-schnell) var(--ease); }
.rtask:last-child { border-bottom: 0; }
.rtask:hover { background: var(--accent-soft); box-shadow: inset 3px 0 0 var(--accent); }
.rtask__main { flex: 1; min-width: 0; }
.rtask__title { font-size: var(--t-4); font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rtask__sub { font-size: var(--t-2); color: var(--text-faint); margin-top: var(--s0-5); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rtask__takt { flex: 0 0 auto; font-size: var(--t-2); font-weight: 600; color: var(--accent); background: var(--accent-soft); border: 1px solid var(--accent-line); border-radius: var(--r-pill); padding: 3px 9px; white-space: nowrap; }
.rtask__takt--aus { color: var(--text-faint); background: var(--e3); border-color: var(--border); }
.rtask.is-paused .rtask__title { color: var(--text-muted); }

/* ===== Einstellungs-Schalter =====
   Vorher standen hier nackte System-Kaestchen mit style="width:auto". Die sehen auf
   jedem Rechner anders aus und passen zu nichts. Eine Zeile traegt jetzt Titel,
   Erklaerung und einen Schalter - und kann zeigen, dass sie von einer anderen abhaengt. */
.optrow {
  display: flex; align-items: flex-start; gap: 14px;
  padding: 13px 15px; border: 1px solid var(--border); border-radius: var(--r-md);
  background: var(--e2); cursor: pointer;
  transition: border-color var(--d-schnell) var(--ease), background var(--d-schnell) var(--ease), opacity var(--d-schnell) var(--ease);
}
.optrow:hover { border-color: var(--border-strong); }
.optrow + .optrow { margin-top: var(--s2-5); }
.optrow__text { flex: 1; min-width: 0; }
.optrow__title { font-size: var(--t-4); font-weight: 600; display: flex; align-items: center; gap: 7px; flex-wrap: wrap; }
.optrow__desc { font-size: var(--t-3); color: var(--text-faint); line-height: var(--lh-text); margin-top: var(--s1); }
.optrow.is-on { border-color: var(--accent-line); background: var(--accent-soft); }
/* Die zweite Einstellung wirkt nur, wenn die erste an ist. Das muss man sehen,
   sonst hakt man sie an und wartet vergeblich. */
.optrow--sub { margin-left: 26px; position: relative; }
.optrow--sub::before {
  content: ""; position: absolute; left: -15px; top: -11px; bottom: 50%;
  width: 13px; border-left: 1px solid var(--border); border-bottom: 1px solid var(--border);
  border-bottom-left-radius: 8px;
}
.optrow.is-locked { opacity: .45; cursor: not-allowed; }
.optrow.is-locked:hover { border-color: var(--border); }
.optrow.is-danger.is-on { border-color: color-mix(in srgb, var(--st-waiting) 50%, transparent); background: color-mix(in srgb, var(--st-waiting) 8%, transparent); }
.optrow__warn { font-size: var(--t-2); font-weight: 700; color: var(--st-waiting); background: color-mix(in srgb, var(--st-waiting) 14%, transparent); border-radius: var(--r-xs); padding: 1px var(--s1-5); letter-spacing: var(--ls-versal); }

.switch { position: relative; flex: 0 0 auto; width: 40px; height: 23px; border-radius: var(--r-pill); background: var(--e4); border: 1px solid var(--border); transition: background var(--d-schnell) var(--ease), border-color var(--d-schnell) var(--ease); }
.switch input { position: absolute; inset: 0; opacity: 0; width: 100%; height: 100%; margin: 0; cursor: pointer; }
.switch input:disabled { cursor: not-allowed; }
.switch__knob { position: absolute; top: 2px; left: 2px; width: 17px; height: 17px; border-radius: var(--r-pill); background: var(--text-faint); pointer-events: none; transition: transform var(--d-mittel) var(--spring), background var(--d-schnell) var(--ease); }
.switch:has(input:checked) { background: var(--accent); border-color: var(--accent); }
.switch:has(input:checked) .switch__knob { transform: translateX(17px); background: #fff; }
.optrow.is-danger .switch:has(input:checked) { background: var(--st-waiting); border-color: var(--st-waiting); }
.switch input:focus-visible { border-radius: var(--r-pill); }

/* Zustand des Postfachs als eigene Zeile statt als Abzeichen mitten im Fliesstext */
.mailstatus { display: flex; align-items: center; gap: var(--s3); padding: var(--s3) 15px; border-radius: var(--r-md); background: var(--e2); border: 1px solid var(--border); margin-bottom: var(--s4); }
.mailstatus__dot { flex: 0 0 auto; width: 8px; height: 8px; border-radius: var(--r-pill); background: var(--text-faint); }
.mailstatus.is-on .mailstatus__dot { background: var(--st-done); box-shadow: 0 0 0 3px color-mix(in srgb, var(--st-done) 16%, transparent); }
.mailstatus__text { flex: 1; min-width: 0; }
.mailstatus__title { font-size: var(--t-4); font-weight: 600; }
.mailstatus__sub { font-size: var(--t-3); color: var(--text-faint); margin-top: var(--s0-5); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Was bei einer Loeschung erhalten bleibt - gehoert vor die Zustimmung, nicht danach */
.confirm-detail { margin-top: 14px; padding-top: var(--s3); border-top: 1px solid var(--border); }
.confirm-detail p { font-size: var(--t-3); line-height: var(--lh-lesen); color: var(--text-faint); margin: 0 0 var(--s2); }
.confirm-detail p:last-child { margin-bottom: 0; }

.grouphead { display: flex; align-items: center; gap: 7px; font-size: var(--t-2); text-transform: uppercase; letter-spacing: var(--ls-versal); color: var(--text-faint); margin: 0 0 var(--s2-5); }
.grouphead svg { width: 13px; height: 13px; color: var(--accent); }
.ncard__more { font-size: var(--t-2); color: var(--text-faint); margin-top: -4px; }
.note-read { white-space: pre-wrap; font-size: var(--t-4); line-height: var(--lh-lesen); color: var(--text-muted); max-height: 62vh; overflow: auto; }

.ccard__ident { min-width: 0; flex: 1 1 auto; }
.ccard__name, .crow__name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ccard__aktiv {
  flex: 0 0 auto; min-width: 22px; height: 22px; padding: 0 var(--s1-5); border-radius: var(--r-pill);
  display: grid; place-items: center; font-size: var(--t-2); font-weight: 600;
  background: color-mix(in srgb, var(--st-active) 16%, transparent); color: var(--st-active);
}
.ccard__stats .ccard__stat b.is-open { color: var(--st-waiting); }
.ccard__stats .ccard__stat b.is-over { color: var(--danger); }
.ccard__stats .ccard__stat b.is-null { color: var(--text-faint); font-weight: 500; }
.ccard__tags { display: flex; flex-wrap: wrap; gap: 5px; margin-top: var(--s2-5); }

.tagbar { display: flex; gap: var(--s1-5); flex-wrap: wrap; }
.tagchip {
  display: inline-flex; align-items: center; gap: var(--s1); font: inherit; font-size: var(--t-2);
  padding: 3px 9px; border-radius: var(--r-pill); cursor: pointer;
  background: var(--e3); border: 1px solid var(--border); color: var(--text-muted);
  transition: border-color var(--d-schnell) var(--ease), color var(--d-schnell) var(--ease);
}
.tagchip:hover { border-color: var(--border-strong); color: var(--text); }
.tagchip.is-active { background: var(--accent-soft); border-color: var(--accent-line); color: var(--text); }

.sortpick { display: inline-flex; align-items: center; gap: var(--s1-5); height: var(--h-ctrl); padding: 0 var(--s2-5) 0 var(--s3); border-radius: var(--r-ctrl); background: var(--e2); border: 1px solid var(--border); color: var(--text-faint); }
.sortpick svg { width: 15px; height: 15px; flex: 0 0 auto; }
.sortpick select { background: none; border: 0; color: var(--text); font: inherit; font-size: var(--t-4); min-height: 0; padding: 0; cursor: pointer; outline: none; }
/* Der Jahreswaehler in den Auswertungen schrumpfte in der engen Kopfzeile auf 20 px,
   "2026" braucht 32 - sichtbar stand dort "20". Aufgefallen ist es erst, als die
   Beispieldaten ein zweites Geschaeftsjahr hatten; den Waehler gibt es ueberhaupt
   erst ab zwei Jahren, also trifft es jeden echten Nutzer in seinem zweiten Jahr.
   Bewusst nur diese eine Auswahl und nicht alle .sortpick: ein Jahr ist immer vier
   Zeichen breit. Bei den Sortier-Auswahlen mit langen Beschriftungen koennte
   dieselbe Regel die Kopfzeile am Handy aufreissen. */
#repYear { flex: 0 0 auto; min-width: max-content; }

/* Summenzeile ueber der Liste: was steckt in der sichtbaren Auswahl? */
.listsum { font-size: var(--t-3); color: var(--text-muted); margin: 0 0 var(--s3); padding: 0 var(--s0-5); }
/* In der Tabellenflaeche sitzt dieselbe Zeile als Kopfzeile des Blocks statt als
   schwebender Text davor. Sie bekommt die Polsterung der Zeilen, damit sie in einer
   Flucht mit ihnen steht. */
.listpanel .listsum { margin: 0; padding: 14px var(--s5) var(--s2-5); border-bottom: 1px solid var(--hairline); }
/* Haftender Spaltenkopf. Bei sechs Zeilen unnoetig, bei sechzig entscheidend: sonst
   scrollt man Zahlenspalten ohne zu wissen, welche Spalte welche ist. Der Kopf braucht
   eine deckende Flaeche, sonst scheinen die Zeilen durch ihn hindurch. */
.listpanel .crow--head, .listpanel .prow--head {
  position: sticky; top: 0; z-index: 2;
  background: var(--e2);
  border-bottom: 1px solid var(--hairline);
}
.listsum b { font-weight: 600; }
.listsum b.is-open { color: var(--st-waiting); }
.listsum b.is-over { color: var(--danger); }

/* Dichte Kundenliste */
.rowlist--head { padding-top: 0; }
/* Eine Tabellenzeile, zwei Spaltensaetze. .crow (Kunden) und .prow (Auftraege) sind
   bewusst dasselbe Bauteil: gleiche Hoehe, gleicher Kopf, gleiche Zahlenbehandlung.
   Vorher war die Auftragsliste ein Kartenraster und sprach eine andere Sprache als
   die Kundenliste - zwei Gestaltungen fuer dieselbe Sache. */
.prow { display: grid; grid-template-columns: minmax(0,2.6fr) 1fr .9fr .9fr .8fr; gap: var(--s3); align-items: center; padding: 11px var(--s5); border-bottom: 1px solid var(--hairline); cursor: pointer; transition: background var(--d-schnell) var(--ease), box-shadow var(--d-mittel) var(--ease); }
.prow:last-child { border-bottom: 0; }
.prow:hover { background: var(--accent-soft); box-shadow: inset 3px 0 0 var(--accent); }
.prow--head { font-size: var(--t-2); text-transform: uppercase; letter-spacing: var(--ls-versal); color: var(--text-faint); cursor: default; padding-top: 14px; padding-bottom: var(--s2); }
.prow--head:hover { background: none; box-shadow: none; }
.prow__main { min-width: 0; }
.prow__name { font-weight: 600; font-size: var(--t-4); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.prow__sub { font-size: var(--t-2); color: var(--text-faint); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.prow__status { display: flex; align-items: center; gap: var(--s2); font-size: var(--t-3); color: var(--text-muted); min-width: 0; }
.prow__dot { width: 7px; height: 7px; border-radius: var(--r-pill); flex: 0 0 auto; }
.prow .num { text-align: right; font-size: var(--t-4); color: var(--text-muted); font-variant-numeric: tabular-nums; }
.prow .is-null { color: var(--text-faint); }
.prow .is-over { color: var(--danger); font-weight: 600; }
.prow .is-warn { color: var(--st-waiting); }
.prow__prog { display: flex; align-items: baseline; justify-content: flex-end; gap: var(--s2); }
.prow__steps { font-size: var(--t-2); color: var(--text-faint); }
.prow__pct { font-weight: 600; letter-spacing: var(--track-tight); }
.prow__wert { font-weight: 600; color: var(--text); }

.crow { display: grid; grid-template-columns: minmax(0,2.4fr) .8fr 1fr 1fr .9fr; gap: var(--s3); align-items: center; padding: 11px var(--s5); border-bottom: 1px solid var(--border); cursor: pointer; transition: background var(--d-schnell) var(--ease); }
.crow:last-child { border-bottom: 0; }
.crow:hover { background: var(--accent-soft); box-shadow: inset 3px 0 0 var(--accent); }
.crow--head { font-size: var(--t-2); text-transform: uppercase; letter-spacing: var(--ls-versal); color: var(--text-faint); cursor: default; padding-top: 14px; padding-bottom: var(--s2-5); }
.crow--head:hover { background: none; box-shadow: none; }
/* min-width:0 muss BIS zum Textcontainer durchgereicht werden, sonst greift
   die Ellipse nicht und die Zeile laeuft innen ueber. */
.crow__main { display: flex; align-items: center; gap: var(--s2-5); min-width: 0; }
.crow__main > div { min-width: 0; }
.crow__main .avatar { flex: 0 0 auto; }
.crow__name { font-weight: 600; font-size: var(--t-4); }
.crow__sub { font-size: var(--t-2); color: var(--text-faint); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.crow .num { text-align: right; font-size: var(--t-4); color: var(--text-muted); font-variant-numeric: tabular-nums; }
.crow .num.is-open { color: var(--st-waiting); font-weight: 600; }
.crow .num.is-over { color: var(--danger); font-weight: 600; }
.crow .num.is-null { color: var(--text-faint); }
.crow__aktiv { font-size: var(--t-2); color: var(--st-active); }
.crow__last { font-size: var(--t-3); }

/* Vertragszeile. minmax(0,…) statt blossem fr, sonst waechst die Titelspalte
   mit dem laengsten Titel und schiebt Wert und Stand aus der Zeile. */
.ctrow { display: grid; grid-template-columns: minmax(0,2.6fr) minmax(0,.9fr) minmax(0,.9fr) minmax(0,.8fr); gap: var(--s3); align-items: center; padding: 11px var(--s5); border-bottom: 1px solid var(--border); cursor: pointer; transition: background var(--d-schnell) var(--ease); }
.ctrow:last-child { border-bottom: 0; }
.ctrow:hover { background: var(--accent-soft); box-shadow: inset 3px 0 0 var(--accent); }
.ctrow--head { font-size: var(--t-2); text-transform: uppercase; letter-spacing: var(--ls-versal); color: var(--text-faint); cursor: default; padding-top: 14px; padding-bottom: var(--s2-5); }
.ctrow--head:hover { background: none; box-shadow: none; }
.ctrow__main { min-width: 0; }
.ctrow__title { font-weight: 600; font-size: var(--t-4); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ctrow__sub { font-size: var(--t-2); color: var(--text-faint); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ctrow .num { text-align: right; font-size: var(--t-4); color: var(--text-muted); font-variant-numeric: tabular-nums; }
.ctrow .num.is-null { color: var(--text-faint); }
/* Statt eines geratenen Standes eine Einladung, ihn zu setzen */
.ctrow__setstand { display: inline-flex; align-items: center; gap: var(--s1); font-size: var(--t-2); color: var(--text-faint); background: none; border: 1px dashed var(--border); border-radius: var(--r-ctrl); padding: 3px 9px; cursor: pointer; font-family: inherit; }
.ctrow__setstand:hover { color: var(--text); border-color: var(--border-strong); }
.ctrow__setstand svg { width: 12px; height: 12px; }

/* Statt eines leeren Balkens, der wie Untaetigkeit aussieht */
.pcard__stepsadd {
  display: inline-flex; align-items: center; gap: var(--s1-5); margin: var(--s2-5) 0 var(--s0-5);
  background: none; border: 0; padding: 0; cursor: pointer;
  font: inherit; font-size: var(--t-3); color: var(--text-faint);
}
.pcard__stepsadd svg { width: 13px; height: 13px; }
.pcard__stepsadd:hover { color: var(--accent-2); }
.row__nosteps { font-size: var(--t-2); color: var(--text-faint); width: 110px; text-align: right; }
/* Verstrichener Wunschtermin bei Anfrage/Angebot: Hinweis, keine Alarmfarbe */
.meta.is-kalt { color: var(--text-faint); }

/* Ueberlaufmenue in der Kopfzeile */
.ovmenu { position: relative; display: inline-flex; }
.ovmenu__btn { padding-left: 9px; padding-right: 9px; }
.ovmenu__list {
  position: absolute; top: calc(100% + 6px); right: 0; z-index: 60; min-width: 210px;
  border-radius: var(--r-card); padding: 5px; display: flex; flex-direction: column;
  background:
    linear-gradient(158deg, rgba(255,255,255,.072), rgba(255,255,255,.018) 46%, rgba(255,255,255,.042)),
    rgba(12,18,27,.9);
  -webkit-backdrop-filter: blur(22px) saturate(150%); backdrop-filter: blur(22px) saturate(150%);
  border: 1px solid transparent;
  box-shadow: inset 0 1px 0 rgba(255,255,255,.16), 0 2px 6px rgba(0,0,0,.36), var(--sh-3);
}
.ovmenu__list[hidden] { display: none; }
.ovmenu__item {
  display: flex; align-items: center; gap: 9px; width: 100%; text-align: left;
  padding: 9px 11px; border: 0; border-radius: var(--r-ctrl); background: none;
  font: inherit; font-size: var(--t-4); color: var(--text); cursor: pointer;
}
.ovmenu__item svg { width: 15px; height: 15px; color: var(--text-faint); flex: 0 0 auto; }
.ovmenu__item:hover { background: var(--e3); }
.ovmenu__item:hover svg { color: var(--accent-2); }
/* Loeschen im Menue: erreichbar, aber sichtbar abgesetzt. */
.ovmenu__item--gefahr { color: var(--danger); border-top: 1px solid var(--hairline); margin-top: var(--s1); padding-top: var(--s2-5); }
.ovmenu__item--gefahr svg { color: var(--danger); }
.ovmenu__item--gefahr:hover { background: var(--danger-soft); }
.ovmenu__item--gefahr:hover svg { color: var(--danger); }

@media (max-width: 720px) {
  /* Auftragszahl und Kontaktdatum entfallen, der Name bekommt ihren Platz. */
  .crow { grid-template-columns: minmax(0,2.1fr) .8fr .8fr; gap: var(--s2); padding-left: var(--s4); padding-right: var(--s4); }
  .crow > :nth-child(2), .crow > :nth-child(5) { display: none; }
  .crow__name { font-size: var(--t-4); }
  .crow .num { font-size: var(--t-3); }
  /* Die Auftragstabelle nach derselben Regel: fuenf Spalten passen bei 375 px nicht.
     Es bleiben Auftrag, Frist und Wert - also wer, bis wann und wieviel. Status und
     Fortschritt fallen weg; der Status steht auf der Detailseite und der Fortschritt
     ist am Handy die unwichtigste der fuenf Angaben. */
  .prow { grid-template-columns: minmax(0,2.1fr) .8fr .8fr; gap: var(--s2); padding-left: var(--s4); padding-right: var(--s4); }
  .prow > :nth-child(2), .prow > :nth-child(3) { display: none; }
  .prow .num { font-size: var(--t-3); }
  .sortpick { flex: 1 1 auto; }

  /* Vier Spalten passen hier nicht: Wert, Datum und Stand schoben sich uebereinander.
     Der Titel bekommt die volle Breite, der Rest ruecht als Zeile darunter. */
  .ctrow { grid-template-columns: 1fr auto; gap: var(--s1) var(--s2-5); padding-left: var(--s4); padding-right: var(--s4); }
  .ctrow--head { display: none; }
  .ctrow__main { grid-column: 1; }
  .ctrow > :nth-child(4) { grid-column: 2; grid-row: 1; justify-self: end; }
  .ctrow > .num { grid-row: 2; text-align: left; font-size: var(--t-3); }
  .ctrow > :nth-child(2) { grid-column: 1; }
  .ctrow > :nth-child(3) { grid-column: 2; text-align: right; }
  .ctrow__title { font-size: var(--t-4); }

  /* Der Ansichtsumschalter braucht am Handy keine 34 px pro Symbol. Das gibt der
     Knopfreihe echten Spielraum, statt sie auf zwei Pixel genau aufgehen zu lassen.
     Muss HIER stehen und nicht im 620er-Block weiter oben: die Grundregel kommt in
     der Datei danach und haette bei gleicher Gewichtung gewonnen. */
  .view-toggle button { width: 28px; }

  /* Knoepfe in der Kopfzeile am Handy kompakter. Vorher habe ich das je Ansicht
     nachgerechnet und bin bei den Finanzen drei Pixel, bei den Auftraegen sechs
     Pixel zu breit gelandet - das ist zu knapp, um zu halten. Weniger Polsterung
     und ein etwas engerer Abstand zum Symbol geben rund 18 px je Knopf; damit
     passen auch drei Knoepfe in eine Reihe, statt auf Kante zu stehen. */
  .topbar__actions .btn--sm { padding: var(--s1-5) 9px; font-size: var(--t-3); gap: 5px; }
  .topbar__actions .btn--sm svg { width: 14px; height: 14px; }
  /* Beschriftung, die am Handy entfallen darf, weil das Symbol allein traegt.
     Nur dort einsetzen, wo das Symbol wirklich eindeutig ist. */
  .topbar__actions .btn__label { display: none; }
  .topbar__actions .btn--sm:has(.btn__label) { gap: 0; }
}

/* Konto-Karte in den Einstellungen */
.acc-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: var(--s4); }
.acc-lbl { display: block; font-size: var(--t-2); color: var(--text-faint); margin-bottom: 3px; }
.acc-val { display: block; font-size: var(--t-4); font-weight: 600; color: var(--text); }
.acc-sep { border: 0; border-top: 1px solid var(--border); margin: var(--s4) 0; }
.rc-actions { display: flex; gap: var(--s2); }
.rc-actions .btn { flex: 1; justify-content: center; }
.rc-confirm { display: flex; gap: var(--s2-5); align-items: flex-start; font-size: var(--t-3); color: var(--text-muted); line-height: var(--lh-text); cursor: pointer; }
.rc-confirm input { margin-top: var(--s0-5); flex: 0 0 auto; }

@media (max-width: 560px) {
  .auth-box, .auth-box--wide { padding: 30px 22px var(--s5); max-width: 100%; }
  .auth-title { font-size: var(--t-6); }
  .rc-actions { flex-direction: column; }
  .rc-code { font-size: var(--t-5); }
}

/* ========================= Lightbox ========================= */
.lightbox { position: fixed; inset: 0; z-index: 260; display: grid; place-items: center; padding: 40px; }
.lightbox[hidden] { display: none; }
.lightbox .lb-scrim { position: absolute; inset: 0; background: rgba(6,8,12,.85); backdrop-filter: blur(2px); }
.lightbox img { position: relative; max-width: 90vw; max-height: 88vh; border-radius: var(--r-sm); box-shadow: var(--sh-3); }
.lb-close { position: absolute; top: 20px; right: 20px; }

/* ========================= Pipeline / Notes / Report / Forecast ========================= */
.board--5 { grid-template-columns: repeat(5, 1fr); }
.board--6 { grid-template-columns: repeat(6, 1fr); }
@media (max-width: 1280px) { .board--6 { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 1200px) { .board--5 { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 760px) { .board--5, .board--6 { grid-template-columns: 1fr; } }

.ncard { padding: var(--s5); background: linear-gradient(158deg, rgba(255,255,255,.072), rgba(255,255,255,.018) 46%, rgba(255,255,255,.042)), rgba(12,18,27,.58); -webkit-backdrop-filter: blur(22px) saturate(150%); backdrop-filter: blur(22px) saturate(150%); box-shadow: inset 0 1px 0 rgba(255,255,255,.16), 0 2px 6px rgba(0,0,0,.36), 0 44px 90px -54px rgba(0,0,0,.95); border: 1px solid transparent; border-radius: var(--r-card); cursor: pointer; display: flex; flex-direction: column; gap: var(--s2-5); min-height: 130px; transition: border-color var(--d-schnell) var(--ease), background var(--d-schnell) var(--ease); }
.ncard:hover { border-color: var(--accent-line); background: linear-gradient(158deg, rgba(255,255,255,.10), rgba(255,255,255,.026) 46%, rgba(255,255,255,.06)), rgba(16,23,34,.62); }
.ncard.is-pinned { border-color: var(--accent-line); }
.ncard__head { display: flex; align-items: flex-start; gap: var(--s2); }
.ncard__head h3 { font-size: var(--t-5); font-weight: 600; flex: 1; }
.ncard__pin { color: var(--accent); } .ncard__pin svg { width: 15px; height: 15px; }
.ncard__body { font-size: var(--t-4); color: var(--text-muted); line-height: var(--lh-text); white-space: pre-wrap; margin: 0; flex: 1; overflow: hidden; }
.ncard__foot { display: flex; flex-wrap: wrap; gap: var(--s1-5); }

.avatar--img { background-size: cover; background-position: center; background-color: var(--e4); }

.rep-h { font-size: 11px; text-transform: uppercase; letter-spacing: .06em; color: #999; font-weight: 700; margin-bottom: 10px; }
.rep-cols { display: grid; grid-template-columns: 1fr 1fr; gap: 24px; }
.rep-step { font-size: 13px; color: #333; padding: 6px 0 6px 20px; position: relative; border-bottom: 1px solid #f2f2f2; }
.rep-step::before { content: ""; position: absolute; left: 2px; top: 12px; width: 8px; height: 8px; border-radius: 50%; border: 1.5px solid #bbb; }
.rep-step.is-done { color: #888; } .rep-step.is-done::before { background: #3fb950; border-color: #3fb950; }
.rep-step.is-muted { color: #aaa; } .rep-step.is-muted::before { display: none; }

.fc-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: var(--s3); }
.fc { padding: 14px var(--s4); background: var(--e1); border: 1px solid var(--border); border-radius: var(--r-md); }
.fc--hl { border-color: var(--accent-line); background: var(--accent-soft); }
.fc__l { display: block; font-size: var(--t-3); color: var(--text-muted); margin-bottom: var(--s1-5); }
.fc__v { font-size: var(--t-6); font-weight: 700; }
/* Die Pipeline steht bewusst neben der Rechnung, nicht in ihr */
.fc-aside { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--s1) var(--s3); margin-top: 14px; padding-top: var(--s3); border-top: 1px solid var(--border); font-size: var(--t-3); color: var(--text-muted); }
.fc-aside > span:first-child { display: inline-flex; align-items: center; gap: var(--s1-5); }
.fc-aside svg { width: 14px; height: 14px; color: var(--text-faint); }
.fc-aside .faint { font-size: var(--t-3); line-height: var(--lh-text); }

/* ========================= Angebots-Pakete & Verträge ========================= */
.pkg-block { border: 1px solid var(--border); border-radius: var(--r-md); padding: 14px; background: var(--e1); }
.pkg-head { display: flex; gap: var(--s2); align-items: center; margin-bottom: var(--s2-5); }
.pkg-name-input { font-weight: 600; }
.pkg-total { font-size: var(--t-3); color: var(--text-muted); white-space: nowrap; }
.pkg-total b { color: var(--text); }
/* Paket auf dem Dokument (helles Blatt) */
.is-package { border: 1px solid #e8e8e8; border-radius: var(--r-sm); padding: 12px 16px 4px; margin-bottom: 14px; }
.is-pkg-name { font-weight: 700; color: #111; font-size: 15px; margin-bottom: 6px; }
.is-package .is-table { margin-bottom: 6px; }
.is-package .is-totals { width: 240px; }
/* Vertrags-Unterschriften */
.ct-sign { display: grid; grid-template-columns: 1fr 1fr; gap: 40px; margin-top: 54px; font-size: 12px; color: #555; }
.ct-line { border-top: 1px solid #999; margin-bottom: 6px; height: 1px; }

/* ========================= Warn-Banner (Kleinunternehmer-Grenze) ========================= */
.warn-banner { display: flex; align-items: flex-start; gap: 14px; padding: 14px 18px; border-radius: var(--r-card); margin-bottom: var(--s5); border: 1px solid color-mix(in srgb, var(--st-waiting) 40%, transparent); background: color-mix(in srgb, var(--st-waiting) 10%, transparent); }
.warn-banner.is-over { border-color: color-mix(in srgb, var(--danger) 50%, transparent); background: var(--danger-soft); }
.warn-ico { color: var(--st-waiting); flex: none; }
.warn-banner.is-over .warn-ico { color: var(--danger); }
.info-banner { display: flex; align-items: flex-start; gap: 14px; padding: 14px 18px; border-radius: var(--r-card); margin-bottom: var(--s5); border: 1px solid var(--accent-line); background: var(--accent-soft); }
.info-banner .warn-ico { color: var(--accent); flex: none; }
.info-banner .warn-ico svg { width: 20px; height: 20px; }
.warn-ico svg { width: 20px; height: 20px; }

/* ========================= Print ========================= */
@media print {
  /* Beide Hintergrundschichten raus: die Lichthoefe (::before) und das Korn
     (::after). Das Korn ist am 27.08.2026 dazugekommen; ohne diese Zeile laege
     ein Rauschraster ueber jedem gedruckten Beleg. */
  body::before, body::after { display: none !important; }
  .sidebar, .topbar, .toasts, .modal-host, .demobar, .no-print { display: none !important; }
  .app { display: block !important; }
  .main, .view { padding: 0 !important; margin: 0 !important; display: block !important; max-width: none !important; }
  .sheet-wrap { gap: 0 !important; }
  /* Das Blatt bringt seine Raender selbst mit. Deshalb bekommt die Seite KEINE
     eigenen Raender - sonst haetten Vorschau und Ausdruck verschiedene Masse,
     und genau das war vorher der Fall. */
  @page { size: A4; margin: 0; }
  .sheet-stage, .sheet-stage__inner { overflow: visible !important; display: block !important; }
  .sheet-stage__inner { transform: none !important; width: auto !important; height: auto !important; }
  .invoice-sheet {
    box-shadow: none !important; border-radius: 0 !important; margin: 0 !important;
    width: 210mm !important; min-height: 297mm !important;
  }
  /* Nichts darf mitten in einer Position oder in den Summen umbrechen. */
  .is-table tbody tr, .is-totals, .is-paywrap, .is-package, .is-briefbogen { break-inside: avoid; page-break-inside: avoid; }
  .is-table thead { display: table-header-group; }
  .is-meta, .is-head { break-inside: avoid; page-break-inside: avoid; }
}

/* Offener Rest in der Belegzeile: bei Teilzahlung sonst unsichtbar */
.doc-row__open { color: var(--st-waiting); font-weight: 600; }

/* Verschieben direkt in der Aufgabenzeile, erscheint beim Darueberfahren */
.task__later { display: inline-flex; gap: var(--s1); opacity: 0; transition: opacity var(--d-schnell) var(--ease); flex: 0 0 auto; }
.task:hover .task__later, .task__later:focus-within { opacity: 1; }
.task__later button {
  font: inherit; font-size: var(--t-1); padding: 3px 7px; border-radius: var(--r-pill); cursor: pointer;
  background: var(--e3); border: 1px solid var(--border); color: var(--text-muted);
  white-space: nowrap;
}
.task__later button:hover { border-color: var(--accent-line); color: var(--accent-2); }
@media (hover: none) { .task__later { opacity: 1; } }

/* Vergangene Tage im laufenden Monat leicht zuruecknehmen */
.cal__day.is-past { background: transparent; }
.cal__day.is-past .cal__daynum { color: var(--text-faint); }
/* Kompakte Segmentleiste, passt in einen Panel-Kopf */
.segmented--sm button { font-size: var(--t-2); padding: var(--s1) var(--s2-5); }

/* ========================= Demo-Leiste =========================
   Nur in der oeffentlichen Demo-Fassung vorhanden; die Kundenfassung erzeugt sie
   nicht. Dasselbe Glas wie Seitenspalte und Topleiste: 158 Grad, dieselbe Fuellung,
   dieselbe Lichtkante. Eine Leiste in einer fremden Machart haette ausgesehen wie
   ein Cookie-Banner, das jemand ueber die App gelegt hat.
   Sie liegt UNTER dem Modal-Wirt (z-index 90 gegen 100), damit eine Rueckfrage sie
   verdeckt und nicht umgekehrt. */
.demobar {
  position: fixed; inset: auto 0 0 0; z-index: 90;
  display: flex; align-items: center; gap: var(--s4);
  padding: var(--s3) var(--s5);
  background:
    linear-gradient(158deg, rgba(255,255,255,.085), rgba(255,255,255,.022) 46%, rgba(255,255,255,.05)),
    rgba(9,14,22,.86);
  -webkit-backdrop-filter: blur(22px) saturate(150%);
  backdrop-filter: blur(22px) saturate(150%);
  border-top: 1px solid var(--border);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.2), 0 -1px 60px -40px rgba(0,0,0,.95);
}
.demobar__mark {
  flex: none; align-self: flex-start;
  padding: var(--s1) var(--s2-5);
  font-size: var(--t-2); font-weight: 600; letter-spacing: .06em; text-transform: uppercase;
  color: var(--accent-2); background: var(--accent-soft);
  border: 1px solid var(--accent-line); border-radius: var(--r-sm);
}
.demobar__text {
  flex: 1; min-width: 0; margin: 0;
  font-size: var(--t-3); line-height: 1.45; color: var(--text-muted);
}
.demobar__acts { flex: none; display: flex; align-items: center; gap: var(--s2); }
/* Solange der Anmeldebildschirm oben liegt, hat die Leiste dort nichts zu suchen.
   `body.is-locked .app { visibility:hidden }` blendet die App aus - die Leiste haengt
   aber am body und nicht in .app, also blieb sie stehen. Der Anmeldebildschirm ist
   nur ein Verlauf und nicht deckend, dadurch schob sie sich mitten hinein.
   In der Demo faellt das normalerweise nicht auf, weil dort kein Gate kommt; sichtbar
   wurde es, als der Registrierbildschirm zum Pruefen von Hand geoeffnet wurde. */
body.is-locked .demobar { display: none; }
/* Der letzte Eintrag einer langen Liste darf nicht unter der Leiste liegen. Die Hoehe
   ist bewusst grosszuegig geschaetzt statt gemessen: gemessen waere sie erst nach dem
   ersten Anstrich richtig, und ein Sprung beim Laden faellt mehr auf als etwas Luft. */
.has-demobar .view { padding-bottom: calc(var(--s6) + 76px); }
@media (max-width: 720px) {
  .demobar { flex-wrap: wrap; gap: var(--s2-5); padding: var(--s3) var(--s4); }
  .demobar__text { flex: 1 1 100%; order: 2; font-size: var(--t-2); }
  .demobar__acts { order: 1; margin-left: auto; }
  .has-demobar .view { padding-bottom: calc(var(--s6) + 132px); }
}
/* Die Meldungen sitzen unten rechts, also genau dort, wo in der Demo die Leiste
   liegt - und mit z-index 200 darueber. Ohne das verdeckt jede Bestaetigung den
   Zuruecksetzen-Knopf. */
.has-demobar .toasts { bottom: calc(var(--s5) + 64px); }
@media (max-width: 720px) { .has-demobar .toasts { bottom: calc(var(--s5) + 120px); } }
