/* ==========================================================================
   Funck IT — Kundenportal: Arbeitsflaeche (CRM-Schale)
   --------------------------------------------------------------------------
   Kopfzeile oben, Seitenmenue links, Inhalt rechts — dasselbe Grundmuster wie
   im LMS (dash-layout / dash-sidebar / dash-main), hier aber mit den Tokens
   des Portals statt denen des LMS.

   Wird NACH base.css und theme.css geladen und gewinnt deshalb bei gleicher
   Spezifitaet. base.css bleibt die geteilte Demo-Basis — hier nicht anfassen.

   Warum eine eigene Datei: Das Portal ist ein Arbeitswerkzeug, die Demoseiten
   sind Schaufenster. Beides in einer Datei zu mischen faellt beim naechsten
   Abgleich der Basis auf die Fuesse.
   ========================================================================== */

:root{
  --kp-side:264px;
  /* Gemeinsame Hoehe von Klappmenue und Fusszeile. Beide sitzen unten und
     tragen eine Oberkante — stehen sie unterschiedlich hoch, laufen die
     beiden Linien auseinander. Eine Variable haelt sie zusammen. */
  --kp-fussleiste:63px;
  --kp-side-bg:#eef0f4;
  --kp-tile-bg:#f4f6f9;
  /* 🔴 Deckende Fläche für alles, was ÜBER dem Inhalt schwebt (Filterkästen
     im Spaltenkopf). Nicht `--card` benutzen: Bei eingeschalteter Glasoptik
     ist das `rgba(255,255,255,.06)`, und durch einen Filterkasten scheinen
     dann die Tabellenzeilen darunter durch — unlesbar. Dieser Ton bleibt in
     jeder Darstellung deckend. */
  --kp-flyout:#ffffff;
  /* 🔴 Dieselbe Falle beim Diagramm-Tooltip (gefunden 10.08.2026). Dort stand
     `background:var(--text); color:var(--card)` — gemeint war „umgekehrte
     Farben". Mit eingeschalteter Glasoptik ist `--card` im Dunkeln aber
     `rgba(255,255,255,.06)`, also fast durchsichtiges Weiss auf hellem Grund:
     Die Beschriftung war unlesbar. Deshalb ein eigenes, deckendes Paar.
     ⚠️ `--card` ist eine FLAECHE, keine Schriftfarbe — sobald Glasoptik im
     Spiel ist, taugt sie fuer Text grundsaetzlich nicht. */
  --kp-tip-bg:#1f2937;
  --kp-tip-text:#ffffff;
  /* 🔴 Hinweisfarbe in ZWEI Tönen (11.08.2026). `--kp-warn` ist das Bernstein
     der Ampelpunkte und taugt als Fläche und als Symbol. Als kleine SCHRIFT
     taugt es nur im Dunkeln: Auf Weiß bringt #e0a12a rund 2:1 Kontrast, das
     ist für 0,8-rem-Text zu wenig. Deshalb ein zweiter Ton nur für Text —
     dieselbe Überlegung wie beim Tooltip-Paar darüber. */
  --kp-warn:#e0a12a;
  --kp-warn-text:#8a5300;
  /* 🔴 „Hat geklappt" ist eine AUSSAGE, keine Marke (16.08.2026).
     `.meldung.erfolg` lief bis dahin über `--brand-soft`/`--brand`. Bei einem
     Mandanten mit rotem Branding war die Erfolgsmeldung damit von der
     Fehlermeldung (`--danger`, ebenfalls rot) kaum zu unterscheiden — und
     ausgerechnet diese beiden dürfen nie zu verwechseln sein.
     Dieselbe Überlegung wie bei den Diagrammfarben: Sie folgen dem Branding
     bewusst nicht, weil ihre Bedeutung an der Farbe hängt.
     ⚠️ Zwei Töne wie bei `--kp-warn`: #3fae6b ist die Fläche und der
     Ampelpunkt, für Text auf Weiß reicht sein Kontrast nicht. */
  --kp-gut:#3fae6b;
  --kp-gut-text:#1c6b40;
  --kp-gut-soft:rgba(63,174,107,.12);
}
html[data-theme="dark"]{
  --kp-side-bg:#111726;
  --kp-tile-bg:#141a28;
  --kp-flyout:#161d2d;
  --kp-tip-bg:#e2e8f0;
  --kp-tip-text:#0f172a;
  --kp-warn-text:#e8b75a;
  --kp-gut-text:#6dd39b;
  --kp-gut-soft:rgba(63,174,107,.16);
}

/* --------------------------------------------------------------------------
   1. Kopfzeile — schlank, nur Marke und Konto
   Die Abschnittsnavigation sitzt im Seitenmenue, nicht mehr hier oben.
   -------------------------------------------------------------------------- */
body.kp header.site{border-bottom:1px solid var(--line)}
body.kp .brand-logo{height:36px}

/* Marke bündig zum Seitenmenü — wie im LMS.
   Der Kopf läuft dafür über die volle Breite (kein zentrierter Container),
   und der Markenblock ist exakt so breit wie das Menü darunter. Dadurch
   fluchten Logo, „Kundenportal" und die Menüpunkte auf einer Kante. */
body.kp header.site .container.nav{
  max-width:none;
  width:100%;
  padding:10px 0;
  gap:0;
}
/* 🔴 MINDESTbreite, nicht feste Breite (25.08.2026). Vorher stand hier
   `width:var(--kp-side); flex:0 0 var(--kp-side)` — ein Kasten von 264 px, aus
   dem laengere Inhalte einfach herausliefen (`overflow` ist `visible`).
   Gemessen in der Demo bei 1440 px: „servuno Demo" + „CRM mit Service Desk"
   brauchen 284 px, der Zusatz ragte also 20 px heraus und stand nur noch 6 px
   vor dem Reiter „Mein Portal" — Meldung des Users: „im header oben ragt CRM
   mit Servicedesk in den Mein Portal Button".

   Mit `min-width` bleibt die Ausrichtung an der Seitenleiste erhalten, solange
   der Inhalt hineinpasst; ist er breiter, waechst der Kasten und schiebt die
   Reiter mit. Kuerzen waere die Alternative gewesen — dann steht dort ein
   abgeschnittener Name des Mandanten, und der Zusatz ist seine Angabe. */
body.kp .brand{
  width:auto;
  min-width:var(--kp-side);
  flex:0 0 auto;
  box-sizing:border-box;
  padding:0 18px;
  gap:12px;
}
/* Der Zusatz bleibt einzeilig: In einer Kopfzeile von 64 px Hoehe waere ein
   Umbruch kein Gewinn, sondern zwei halb sichtbare Zeilen. */
body.kp .brand .brand-claim{padding-left:12px;white-space:nowrap}

/* Kopfmenü: Bereichswechsel Portal ↔ Administration. Sitzt direkt neben der
   Marke, also am linken Rand des Inhaltsbereichs. */
.kp-kopfnav{margin-left:26px}
.kp-kopfnav ul{gap:6px}
.kp-kopfnav a{
  display:block;padding:7px 14px;border-radius:8px;
  font-size:.9rem;font-weight:600;opacity:1;text-decoration:none;
  color:var(--muted);transition:background .12s,color .12s;
}
.kp-kopfnav a:hover{background:var(--kp-tile-bg);color:var(--text);text-decoration:none}
.kp-kopfnav a.aktiv{background:var(--brand-soft);color:var(--brand)}

.kp-kopf-rechts{display:flex;align-items:center;gap:10px;margin-left:auto;padding-right:24px}

@media (max-width:980px){
  /* Ohne festes Menü darf die Marke wieder mitwachsen, sonst drückt sie den
     Umschalter auf schmalen Geräten aus dem Bild. */
  /* 🔴 Die Marke rückt an den RECHTEN Rand (Wunsch des Users, 15.08.2026:
     „kriegen wir mobil das hinterlegte logo nach rechts statt links neben den
     button?"). Im Markup steht der Menüknopf vor der Marke; ohne diese Regel
     kleben beide links aneinander. `margin-left:auto` schiebt die Marke ans
     Ende der Zeile, der Knopf bleibt links — die beiden Ecken, an denen der
     Daumen ohnehin liegt. */
  /* 🔴 Die Kopfzeile wird hier AUSDRÜCKLICH gesetzt (15.08.2026, im schmalen
     Chrome-Fenster des Users nachgemessen). Vorher hing die Anordnung daran,
     welches Geschwister gerade wie breit ist — die Marke stand dadurch
     „irgendwo über dem Papierkorb-Symbol" statt an der Kante.

     Zeile 1 trägt NUR den Menüknopf und die Marke, alles andere bekommt
     `flex-basis:100%` und damit eine eigene Zeile. Damit ist die Marke das
     letzte Element der ersten Zeile, und `margin-left:auto` schiebt sie
     zuverlässig an den rechten Rand — unabhängig davon, ob Suche oder
     Bereichsnavigation gerade sichtbar sind.
     ⚠️ Auch `padding-right:0`: Die 18 px der Desktopfassung hielten sie
     sonst von der Kante fern. */
  /* ⚠️ `justify-content:flex-start` statt des geerbten `space-between`
     aus `base.css`: Bei drei Elementen in der Zeile setzt `space-between`
     das mittlere in die MITTE — genau dort stand die Marke („irgendwo
     über dem Papierkorb-Symbol"). Mit `flex-start` zählt allein der
     automatische Rand der Marke, und der schiebt sie an die Kante. */
  body.kp header.site .container.nav{align-items:center;justify-content:flex-start}
  /* 🔴 JEDES weitere Kind bekommt eine eigene Zeile — nicht nur die, die ich
     namentlich kenne. Gemessen im schmalen Fenster: In der ersten Zeile lag
     noch ein unsichtbares Element von rund 150 px hinter der Marke und hielt
     sie von der Kante fern. Welches es ist, spielt für die Regel keine Rolle;
     entscheidend ist, dass die Marke das LETZTE Element ihrer Zeile ist. */
  body.kp header.site .container.nav > *{order:5;flex-basis:100%}
  /* ⚠️ Die Ausnahmen brauchen DIESELBE Selektorentiefe wie die Regel darüber.
     Kurz geschrieben (`body.kp .brand`) verlieren sie gegen sie — und dann
     steht auch der Menüknopf über die volle Breite. Einmal so passiert. */
  body.kp header.site .container.nav > .kp-side-btn{order:1;flex:0 0 auto}
  /* 🔴 `margin-right:0` ist der eigentliche Punkt. `theme.css` gibt der Marke
     unter 860 px ein `margin-right:auto` — dort steht das Logo LINKS und der
     Menüknopf rechts. Im Portal ist es umgekehrt, und zwei automatische
     Ränder teilen den freien Platz zu gleichen Teilen: Das Logo landete
     mittig, „irgendwo über dem Papierkorb-Symbol".
     ⚠️ Merksatz: Ein `margin-left:auto` wirkt nur, wenn auf der anderen Seite
     KEIN zweites `auto` steht. Beim Suchen nach so einer Verschiebung immer
     beide Seiten prüfen — und alle drei Stilvorlagen, nicht nur `crm.css`. */
  /* Die Suche teilt sich die erste Zeile mit Knopf und Marke. `flex:1 1 0`
     laesst ihr genau den Rest — auf 360 px sind das noch rund 120 px, genug
     fuer das Feld samt Lupe.
     ⚠️ `margin-left:0`: Ihre Grundregel traegt `margin-left:auto` (Desktop:
     sie schiebt sich dort selbst nach rechts). Hier waere das ein zweiter
     automatischer Rand neben dem der Marke — dieselbe Falle wie beim Logo. */
  body.kp header.site .container.nav > .kp-such-kopf{
    display:block;order:2;flex:1 1 0;min-width:0;
    margin:0 0 0 12px;
  }
  /* ⚠️ `min-width:0` muss hier ausdrücklich stehen. Die Grundregel gibt der
     Marke seit dem 25.08.2026 `min-width:var(--kp-side)` (264 px), damit der
     Zusatz nicht in die Reiter läuft. In dieser schmalen Anordnung teilt sich
     die Marke die erste Zeile mit Menüknopf und Suche — 264 px Mindestbreite
     würden der Suche den Platz nehmen, und auf 360 px bliebe von ihr nichts
     übrig. Hier zählt die Marke also wieder nur so viel, wie sie braucht. */
  body.kp header.site .container.nav > .brand{
    order:3;width:auto;flex:0 0 auto;min-width:0;
    margin-left:12px;margin-right:0;padding:0;
  }
  body.kp header.site .container.nav > .kp-kopf-rechts{
    order:4;flex-basis:100%;margin-left:0;
  }
  /* Das Benutzermenue ans rechte Ende seiner Zeile (Wunsch des Users) — es
     ist das einzige Symbol mit einem Namen daneben und schliesst die Reihe
     damit sauber ab, statt mitten in der Zeile zu enden. */
  body.kp .kp-kopf-rechts > .kp-benutzer{margin-left:auto}
  body.kp header.site .container.nav{padding:10px 16px;flex-wrap:wrap}
  .kp-kopf-rechts{padding-right:0}

  /* base.css klappt nav.main normalerweise hinter den Menüknopf. Den gibt es
     hier nicht — es sind nur zwei Einträge, die bleiben sichtbar und rutschen
     bei Bedarf in die zweite Zeile. */
  .kp-kopfnav{order:9;flex-basis:100%;margin:8px 0 0}
  .kp-kopfnav ul{display:flex;flex-direction:row;gap:6px;padding:0}
  .kp-kopfnav ul li{border-top:0}
  .kp-kopfnav ul li a{padding:7px 12px}
}

/* 🔴 Der Zusatz neben dem Logo entfällt auf dem Handy (15.08.2026). Er stünde
   RECHTS vom Logo und wäre damit genau das, was das Logo von der Kante
   fernhält — und er wiederholt nur, was das Logo schon sagt. Auf dem Tablet
   bleibt er, dort ist Platz. */
@media (max-width:700px){
  body.kp .brand .brand-claim{display:none}
}

/* Umschalter fuer das Seitenmenue — nur schmal sichtbar */
.kp-side-btn{
  display:none;align-items:center;gap:8px;
  background:var(--brand);color:#fff;border:0;border-radius:10px;
  padding:7px 12px;font-size:.88rem;font-weight:600;cursor:pointer;
}
.kp-side-btn:hover{background:var(--accent)}

/* --------------------------------------------------------------------------
   1b. Band der Kundenansicht
   Muss auffallen: Wer das übersieht, hält die Ansicht für sein eigenes Portal
   und wundert sich, warum Daten fehlen.
   -------------------------------------------------------------------------- */
.kp-band{
  background:#8f231d;color:#fff;
  z-index:80;
  box-shadow:0 2px 10px rgba(0,0,0,.2);
}
.kp-band-inner{
  padding:9px 24px;
  display:flex;align-items:center;gap:16px;flex-wrap:wrap;
  font-size:.88rem;line-height:1.35;
}
.kp-band-text{flex:1;min-width:220px}
.kp-band strong{font-weight:700}
.kp-band-meta{
  display:inline-block;margin-left:8px;padding:1px 9px;border-radius:999px;
  background:rgba(255,255,255,.18);font-size:.78rem;white-space:nowrap;
}
/* Mehrere Knöpfe am rechten Rand des Bandes (13.08.2026: „Mandant verlassen"
   neben „Abmelden"). Ohne eigene Regel bricht das Formular als Blockelement in
   die nächste Zeile und der zweite Knopf sitzt unter dem ersten. */
.kp-band-aktionen{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.kp-band .btn{background:#fff;color:#8f231d;border-color:#fff}
.kp-band .btn:hover{background:#f1f1f1;color:#8f231d}

/* Der Rand macht auch dann klar, dass etwas anders ist, wenn man weit
   nach unten gescrollt hat und das Band verlassen hat. */
body.kp-in-ansicht{box-shadow:inset 0 0 0 3px #8f231d}

/* Supportzugriff: eigene Farbe, NICHT die des Mandanten.
   🔴 Zwei Klassen im Selektor (.kp-band.kp-band-support), damit die Regel die
   Markenfarbe schlaegt — die kommt aus einem <style>-Block im Kopf und stuende
   sonst als spaetere Regel gleicher Staerke daueber. Ein Band in der Farbe des
   Kunden saehe nach seinem Auftritt aus; es ist aber eine Aussage ueber die
   Sitzung, nicht ueber ihn. */
.kp-band.kp-band-support{background:#7a4708;color:#fff}
.kp-band.kp-band-support .btn{background:#fff;color:#7a4708;border-color:#fff}
.kp-band.kp-band-support .btn:hover{background:#f1f1f1;color:#7a4708}

/* Mandanten-Kennung („M3 · kramm") im Seitenmenue und im Fuss.
   Schreibmaschinenschrift: Es ist eine Nummer, kein Name — und man liest sie
   vor oder tippt sie ab. */
.kp-side-kennung,.kp-fuss-kennung{
  font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
  font-size:.72rem;letter-spacing:.02em;
}
.kp-side-kennung{
  display:inline-block;margin:8px 0 0;padding:2px 8px;border-radius:6px;
  background:var(--kp-tile-bg,var(--hover,rgba(0,0,0,.05)));
  border:1px solid var(--line);color:var(--muted);
  cursor:default;
}
.kp-fuss-kennung{
  margin-right:10px;padding:1px 7px;border-radius:5px;
  border:1px solid var(--line);color:var(--muted);cursor:default;
}

/* --------------------------------------------------------------------------
   2. Schale
   -------------------------------------------------------------------------- */
/* App-Schale: Die Seite ist genau fensterhoch, Kopf und Band sind feste
   Zeilen, der Rest teilt sich den Platz. Vorher war .kp-side auf 100vh
   gesetzt, begann aber UNTER der Kopfzeile — sie ragte also um genau deren
   Höhe unten aus dem Bild, und das jeweils unterste Element verschwand.
   Erst war das die Fußzeile, dann das Klappmenü. Mit dieser Schale gibt es
   keine geratene Kopfhöhe mehr: Der Browser rechnet selbst. */
body.kp{height:100vh;display:flex;flex-direction:column;overflow:hidden}
body.kp > header.site,
body.kp > .kp-band{flex:0 0 auto}

/* Der „nach oben"-Knopf hört seit dem 08.08.2026 auf den aktiven
   Scrollbereich (in der App-Schale .kp-main-scroll, darunter das Fenster) und
   ist deshalb nicht mehr abgeschaltet — siehe zurueckNachOben() in portal.js.
   In der Schale klebt die Fußzeile am unteren Rand; der Knopf sitzt darüber,
   sonst deckt er sie ab. */
body.kp .to-top{bottom:calc(var(--kp-fussleiste) + 16px)}

.kp-shell{
  flex:1;min-height:0;          /* min-height:0 — sonst schrumpft es nicht */
  display:flex;align-items:stretch;
}

.kp-side{
  width:var(--kp-side);flex:0 0 var(--kp-side);
  background:var(--kp-side-bg);
  border-right:1px solid var(--line);
  height:100%;
  display:flex;flex-direction:column;
  /* NICHT overflow:hidden — das Untermenü von „Neu" fährt rechts aus der
     Spalte heraus und würde sonst abgeschnitten. Gescrollt wird ohnehin nur
     .kp-nav, die Spalte selbst läuft nie über.
     position/z-index, damit das Untermenü über dem Inhalt liegt: .kp-main
     kommt später im Dokument und würde sonst darüber gezeichnet. */
  overflow:visible;
  position:relative;z-index:10;
}

.kp-side-kopf{padding:20px 18px 16px;border-bottom:1px solid var(--line)}
.kp-side-label{
  font-size:.68rem;font-weight:700;letter-spacing:.12em;text-transform:uppercase;
  color:var(--muted);margin:0 0 6px;
}
.kp-side-name{font-weight:700;line-height:1.3;margin:0;word-break:break-word}
.kp-side-meta{font-size:.8rem;color:var(--muted);margin:4px 0 0}

.kp-nav{
  flex:1;padding:10px 0;
  overflow-y:auto;
  /* Ohne min-height:0 weigert sich ein Flex-Kind zu schrumpfen und wächst
     stattdessen über den Container hinaus — der Klassiker. */
  min-height:0;
}
.kp-nav-gruppe{
  font-size:.68rem;font-weight:700;letter-spacing:.12em;text-transform:uppercase;
  color:var(--muted);padding:14px 18px 6px;margin:0;
}
.kp-nav a{
  display:flex;align-items:center;gap:10px;
  padding:10px 18px;
  border-left:3px solid transparent;
  color:var(--text);text-decoration:none;
  font-size:.9rem;font-weight:500;line-height:1.3;
  transition:background .12s,border-color .12s;
}
.kp-nav a:hover{background:rgba(0,0,0,.05);text-decoration:none}
html[data-theme="dark"] .kp-nav a:hover{background:rgba(255,255,255,.05)}
.kp-nav a.aktiv{
  background:var(--card);border-left-color:var(--brand);
  font-weight:700;color:var(--brand);
}
.kp-nav-icon{width:18px;flex:0 0 18px;text-align:center;font-size:1rem;line-height:1}
.kp-nav-zahl{
  margin-left:auto;font-size:.72rem;font-weight:700;
  background:var(--line);color:var(--muted);
  border-radius:999px;padding:1px 8px;
}
.kp-nav a.aktiv .kp-nav-zahl{background:var(--brand-soft);color:var(--brand)}

/* Gesperrt: sichtbar, aber erkennbar nicht benutzbar (11.08.2026) --------
   🔴 Nicht ausblenden (Ansage des Users): Wer den Punkt sieht, weiß, dass es
   ihn gibt, und die Sperrseite erklärt den Rest. `pointer-events` wird NICHT
   abgeschaltet — der Klick soll zur Erklärung führen, nicht ins Leere. */
.kp-nav a.gesperrt{opacity:.45}
.kp-nav a.gesperrt:hover{opacity:.7}
.kp-nav-schloss{margin-left:auto;font-size:.9rem;line-height:1}
.kp-neu-liste a.gesperrt{opacity:.5}

/* Wochentage im Arbeitszeitkontingent (Punkt 26, 13.08.2026) --------------
   🔴 EIGENES Raster, nicht `.kp-felder`: Das dort ordnet nach Platz
   (`auto-fit`, mindestens 230 px je Spalte) — sieben Zahlenfelder rutschten
   damit je nach Fensterbreite in zwei oder drei Zeilen, und der Stichtag stand
   mitten zwischen ihnen. Eine Woche hat sieben Tage in EINER Reihe; das ist
   die Reihenfolge, in der man sie liest und ausfüllt. */
.az-woche{
  display:grid;gap:10px;
  grid-template-columns:repeat(7,minmax(58px,84px));
  justify-content:start;
}
.az-woche label{
  display:block;margin:0 0 5px;text-align:center;
  font-size:.74rem;font-weight:700;letter-spacing:.08em;text-transform:uppercase;
  color:var(--muted);
}
.az-woche input{width:100%;text-align:right;padding-left:6px;padding-right:6px}
/* Samstag und Sonntag stehen an derselben Stelle wie im Kalender, aber leiser:
   Sie sind der seltene Fall und sollen nicht wie ein leeres Pflichtfeld
   aussehen. */
.az-woche .az-frei label{opacity:.6}
.az-woche .az-frei input{background:var(--hover)}
.az-summe{margin:14px 0 0;font-size:.92rem;color:var(--muted)}
.az-summe strong{color:var(--text);font-size:1.05rem}
/* Auf schmalen Geräten zwei Reihen — vier Werktage, dann der Rest. Sieben
   Spalten à 58 px passen unter 460 px nicht mehr ohne Querlauf. */
@media (max-width:560px){
  .az-woche{grid-template-columns:repeat(4,minmax(58px,1fr))}
}

/* Anwesenheitsball in der Teamliste (Punkt 26b, 13.08.2026) ---------------
   🔴 Der Ball steht NIE allein: Rot und Grün liegen unter Deuteranopie dicht
   beieinander (ΔE 4,1) — daneben gehört das Wort. Dieselbe Regel wie beim
   Stimmungsbild der Betreuung, dort schon einmal teuer gelernt.
   Kein Emoji: `🟢` wird von jedem System anders und immer farbig gezeichnet
   → [[feedback_portal_oberflaeche_regeln]]. */
.kp-ball{
  display:inline-block;width:10px;height:10px;border-radius:50%;
  margin-right:8px;vertical-align:baseline;
  /* Ein Rand, damit der Ball auch auf gleichfarbigem Grund eine Kante hat. */
  box-shadow:0 0 0 1px rgba(0,0,0,.18) inset;
}
.kp-ball-gruen{background:#1f9d55}
.kp-ball-gelb {background:#d9a400}
.kp-ball-rot  {background:#c0392b}
.kp-ball-grau {background:#9aa3ad}
.kp-ball-wort{font-size:.92rem}
.kp-klein{font-size:.82rem}
/* Dieselbe Behandlung in der Kopfleiste (Briefumschlag, Papierkorb) —
   13.08.2026. Der Papierkorb hat seit dem 10.08. keinen anderen Einstieg mehr,
   ausblenden hieße hier: Die Funktion gibt es gar nicht. */
.kp-kopf-msg.gesperrt{opacity:.45}
.kp-kopf-msg.gesperrt:hover{opacity:.7}
/* Abgeblendeter Absendeknopf: sichtbar, erkennbar tot. Hängt an `:disabled`
   und nicht an einer eigenen Klasse — die Knöpfe tragen schon `class="btn"`,
   und zwei class-Attribute im selben Tag vertragen sich nicht. */
.btn:disabled,
.btn[disabled]{opacity:.45;cursor:not-allowed;filter:grayscale(.4)}
.btn:disabled:hover,
.btn[disabled]:hover{opacity:.45}

/* Klappmenü „Neu" ------------------------------------------------------- */
/* 🔴 Leerer Rahmen auf Reitern ohne Formularinhalt (vom User beanstandet,
   11.08.2026: leerer Bereich unten bei den Ticketeinstellungen). Die
   Einstellungen sind EIN grosses Formular; Reiter wie Tickets bringen aber
   eigene Formulare mit und liegen deshalb ausserhalb. Dann blieb der
   gestylte Rahmen leer stehen.
   Bedingung mit Bedacht: nur ausblenden, wenn das Formular ueberhaupt Reiter
   enthaelt UND keiner davon aktiv ist. Ohne den ersten Teil verschwaende
   jedes Formular ohne Reiter. */
/* 🔴 Am 15.08.2026 von `:has()` auf eine Klasse umgestellt (Fund des Users:
   „einstellungen öffnen -> zugänge öffnen -> super admin link Firma & Kontakt
   anklicken. die tabs bleiben leer … erst nach f5").

   Die alte Regel lautete
   `.kp-form:has(.kp-reiter-inhalt):not(:has(.kp-reiter-inhalt.aktiv))`.
   Sie musste neu greifen, sobald ein NACHFAHRE seine Klasse ändert — und zwar
   auch dann, wenn dieser Nachfahre gerade in einem `display:none`-Teilbaum
   liegt. Genau das passiert bei diesem Weg: Die vier Pflegereiter liegen
   AUSSERHALB des grossen Formulars, die neun Einstellungsreiter darin. Wer von
   aussen nach innen wechselt, setzt `aktiv` auf ein Element in einem
   ausgeblendeten Formular. Ob der Browser die `:has()`-Bedingung dann neu
   auswertet, ist nichts, worauf man bauen sollte.

   Jetzt setzt `portal.js` die Klasse selbst — dieselbe Stelle, die auch die
   Reiter umschaltet. Kein Ratespiel mehr über Stil-Invalidierung. */
.kp-form.kp-form-leer{display:none}

.kp-neu{
  position:relative;flex:0 0 auto;
  min-height:var(--kp-fussleiste);
  display:flex;align-items:center;
  padding:0 18px;border-top:1px solid var(--line);
}
.kp-neu > summary,
.kp-neu > .kp-neu-solo{flex:1}
.kp-neu > summary,
.kp-neu > .kp-neu-solo{
  display:flex;align-items:center;justify-content:space-between;gap:8px;
  list-style:none;cursor:pointer;
  padding:9px 14px;border-radius:10px;
  background:var(--brand);color:#fff;
  font-size:.9rem;font-weight:700;
}
.kp-neu > summary::-webkit-details-marker{display:none}
.kp-neu > summary::after{content:"⌃";font-size:.9rem;transform:translateY(2px)}
.kp-neu[open] > summary::after{content:"⌄";transform:translateY(-2px)}
.kp-neu > summary:hover,
.kp-neu > .kp-neu-solo:hover{background:var(--accent)}
/* Einzelner Eintrag: derselbe Knopf, nur ohne Klappzeichen. Deshalb mittig
   statt space-between — sonst klebte die Beschriftung ohne Gegenstück links. */
.kp-neu > .kp-neu-solo{
  justify-content:center;text-decoration:none;text-align:center;
}
.kp-neu > .kp-neu-solo:hover{color:#fff;text-decoration:none}

.kp-neu-liste{
  position:absolute;bottom:calc(100% - 6px);left:18px;right:18px;
  /* deckend — siehe .kp-benutzer-klapp */
  background:var(--kp-flyout);
  border:1px solid var(--line);border-radius:var(--radius-sm);
  box-shadow:0 -6px 24px rgba(0,0,0,.16);
  /* Ebenfalls kein overflow:hidden: Es lag hier nur wegen der runden Ecken,
     hätte aber das seitlich ausfahrende Untermenü gekappt. Die Ecken
     erledigen jetzt die Ränder der ersten und letzten Gruppe. */
  overflow:visible;z-index:20;
}
.kp-neu-liste > .kp-neu-gruppe:first-child > summary{border-radius:var(--radius-sm) var(--radius-sm) 0 0}
.kp-neu-liste > .kp-neu-gruppe:last-child > summary{border-radius:0 0 var(--radius-sm) var(--radius-sm)}
/* Gruppen im Klappmenue. Die Untereintraege fahren nach RECHTS aus dem Menue
   heraus — nach unten waere am Fussende kein Platz, und nach oben wuerde die
   Gruppenliste selbst verdeckt. */
.kp-neu-gruppe{position:relative;border-bottom:1px solid var(--line)}
.kp-neu-gruppe:last-child{border-bottom:0}
.kp-neu-gruppe > summary{
  display:flex;align-items:center;justify-content:space-between;gap:10px;
  list-style:none;cursor:pointer;
  padding:11px 14px;font-size:.9rem;font-weight:600;color:var(--text);
}
.kp-neu-gruppe > summary::-webkit-details-marker{display:none}
.kp-neu-gruppe > summary::after{content:"\203A";font-size:1.1rem;color:var(--muted);line-height:1}
.kp-neu-gruppe > summary:hover{background:var(--brand-soft);color:var(--brand)}
.kp-neu-gruppe[open] > summary{background:var(--brand-soft);color:var(--brand)}
.kp-neu-gruppe[open] > summary::after{color:var(--brand)}

/* Punkt ohne Untermenue — sieht aus wie eine Gruppe, nur ohne Pfeil. */
.kp-neu-direkt{
  display:block;padding:11px 14px;
  font-size:.9rem;font-weight:600;color:var(--text);text-decoration:none;
  border-bottom:1px solid var(--line);
}
.kp-neu-liste > .kp-neu-direkt:last-child{
  border-bottom:0;border-radius:0 0 var(--radius-sm) var(--radius-sm);
}
.kp-neu-direkt:hover{background:var(--brand-soft);color:var(--brand);text-decoration:none}

.kp-neu-unter{
  position:absolute;left:calc(100% + 6px);bottom:0;
  min-width:210px;
  /* deckend — siehe .kp-benutzer-klapp */
  background:var(--kp-flyout);
  border:1px solid var(--line);border-radius:var(--radius-sm);
  box-shadow:0 6px 24px rgba(0,0,0,.2);
  overflow:hidden;z-index:30;
}
.kp-neu-unter a{
  display:block;padding:10px 14px;white-space:nowrap;
  color:var(--text);text-decoration:none;font-size:.9rem;
  border-bottom:1px solid var(--line);
}
.kp-neu-unter a:last-child{border-bottom:0}
.kp-neu-unter a:hover{background:var(--brand-soft);color:var(--brand);text-decoration:none}

/* --------------------------------------------------------------------------
   3. Inhaltsflaeche
   -------------------------------------------------------------------------- */
.kp-main{
  flex:1;min-width:0;
  background:var(--bg);
  /* Zwei Zeilen: scrollender Inhalt oben, feste Fußzeile unten. Das Polster
     sitzt deshalb am Scrollbereich, nicht mehr hier. */
  display:flex;flex-direction:column;
  overflow:hidden;
}
.kp-main-scroll{
  flex:1;min-height:0;overflow-y:auto;
  padding:28px 34px 36px;
}
/* Keine Deckelung: Die Verwaltung zeigt breite Formulare und Tabellen, da ist
   Platz die knappe Ressource — nicht die Zeilenlänge. */
.kp-main > .kp-inner{max-width:none}

.kp-titel{font-size:1.55rem;line-height:1.2;margin:0 0 4px}
.kp-unter{color:var(--muted);margin:0 0 26px}

/* Auch .muted war überall in Gebrauch und nirgends definiert — base.css
   kennt nur .hint und .lead. */
.muted{color:var(--muted)}
small.muted{font-size:.85em}

.kp-abschnitt{margin-top:34px}
.kp-abschnitt > h2{font-size:1.12rem;margin:0 0 14px}
/* 🔴 Ohne eigene Überschrift ist es kein neuer Abschnitt, sondern eine
   Fortsetzung — dann gelten dieselben 20px wie zwischen den Spaltenblöcken
   (03.09.2026, Meldung des Users: „den abstand … angleichen, nach oben sieht
   doppelt so hoch aus"). Die 34px sind für den Fall gedacht, dass eine
   Überschrift den Abstand ausfüllt; fehlt sie, steht dort nur Luft. */
.kp-abschnitt:not(:has(> h2)){margin-top:20px}

/* --------------------------------------------------------------------------
   4. Karten — die fehlende Klasse aus dashboard.php und leistungen.php
   -------------------------------------------------------------------------- */
.karte{
  background:var(--card);
  border:1px solid var(--line);
  border-radius:var(--radius);
  padding:20px 22px;
  box-shadow:var(--shadow);
}
.karte > :first-child{margin-top:0}
.karte > :last-child{margin-bottom:0}
.karte h2,.karte h3{margin:0 0 10px;line-height:1.25}
.karte h2{font-size:1.1rem}
.karte h3{font-size:1rem}

.kp-karten{
  display:grid;gap:18px;
  grid-template-columns:repeat(auto-fit,minmax(min(300px,100%),1fr));
}

/* Preiszeile auf der Leistungskarte des Kunden. Der Betrag traegt die Zeile,
   Turnus und Steuerhinweis bleiben bewusst klein — sonst liest sich die Karte
   wie eine Rechnung. */
.kp-preis{
  margin:0 0 10px;display:flex;align-items:baseline;gap:8px;flex-wrap:wrap;
  font-size:1.15rem;
}
.kp-preis .muted{font-size:.9rem}
/* 🔴 `align-items:stretch` (der Vorgabewert des Rasters), NICHT `start`
   (21.08.2026, Ansage des Users: „ich hätte die dashboard elemente gern so,
   dass wir keine freien Bereiche ohne Inhalt haben" — „bei Überblick z.B. Mein
   Konto und Hilfe gleich hoch").

   Mit `start` endete jede Spalte dort, wo ihr Inhalt aufhört, und neben der
   kürzeren stand ein Loch. Gemessen am 21.08.2026: Überblick 47 px, Umsatz
   151 px, Accounts 174 px, Betreuung 109 px, Betrieb 75 px — und Kündigungen
   880 px.

   Damit das wirkt, müssen zwei Dinge zusammenkommen: Die Spalte streckt sich
   (Raster), UND die letzte Karte darin füllt den Rest (Flex unten). Ohne den
   zweiten Teil wäre nur der unsichtbare Spaltenkasten hoch, die Karte bliebe
   kurz und das Loch sähe genauso aus wie vorher. */
.kp-zweispalt{display:grid;gap:20px;grid-template-columns:1.6fr 1fr;align-items:stretch}
.kp-zweispalt > div{display:flex;flex-direction:column}
/* ⚠️ Nur die LETZTE Karte wächst. Wachsen alle, verteilt sich der Rest über
   die ganze Spalte und jede Karte bekommt etwas Leerraum — dann sieht keine
   mehr nach ihrem Inhalt aus. Unten anzuwachsen ist die einzige Stelle, an der
   zusätzlicher Platz nicht wie ein Fehler wirkt. */
.kp-zweispalt > div > .karte:last-child{flex:1 1 auto}
/* ⚠️ Das gilt auch für Karten mit Diagramm — beide Spalten sollen unten
   bündig abschliessen (03.09.2026: „Portalzugänge bitte bündig mit neueste
   accounts ende lassen").
   Am selben Tag stand hier kurz eine Ausnahme für Diagrammkarten, weil die
   gestreckte Karte Leerraum zeigte. Das war die falsche Stelle: Die Ursache
   lag in den ungleich langen Spalten, und die sind seither anders aufgeteilt
   (Listen links, Zahlen rechts).
   📌 Ein Rest Luft bleibt in der Karte, weil das SVG seine Höhe aus
   `data-hoehe` bekommt und nicht mitwächst. Wer das ändern will, muss ans
   Diagramm-JS (viewBox statt fester Höhe) — nicht ans Kartenlayout. */
/* Gestapelte Karten in einer Spalte brauchen Luft dazwischen — sonst kleben
   sie aneinander, sobald eine Spalte mehr als eine Karte traegt. */
.kp-zweispalt > div > .karte + .karte,
.kp-zweispalt > div > .karte + [class^="kp-"]{margin-top:18px}
/* Eine Karte über die VOLLE Breite unter den beiden Spalten (21.08.2026, die
   Gewinnprognose im Umsatzreiter). `.karte` bringt selbst keinen Rand mit —
   ohne diese Regel klebt sie an den Spalten darüber. Der Wert ist bewusst
   derselbe wie der `gap` des Rasters: Sonst sieht der Abstand zur Karte anders
   aus als der zwischen den Spalten, und die Seite wirkt schief. */
.kp-zweispalt + .karte{margin-top:20px}

/* 🔴🔴 ABSTAND ZWISCHEN DEN BLÖCKEN EINER REGISTERKARTE — die eine Regel,
   die JEDE Nachbarschaft abdeckt (02.09.2026).

   Frage des Users: „ich möchte immer einen abstand zwischen den kacheln,
   warum passiert das denn immer?" — und die Antwort steht in den Zeilen
   darüber: `.karte` trägt selbst keinen Rand. Jeder Abstand im Portal war
   ein EINZELFALL („Karte auf Karte in einer Spalte", „Karte unter den
   Spalten", dazu ein eigener Satz für den Arbeitsplatz). Sobald eine neue
   Anordnung entstand, gab es dafür keinen Fall — und heraus kam 0.

   Genau das ist beim Dreizeilen-Umbau des Umsatzreiters passiert: Für
   „Rasterzeile folgt auf Rasterzeile" existierte keine Regel, und die zweite
   Zeile klebte an der ersten. Eine weitere Einzelregel hätte den nächsten
   Fall wieder offen gelassen.

   `:is()` deckt alle Kombinationen der beiden Blockarten ab. Kommt eine dritte
   dazu, gehört ihr Name in BEIDE Klammern — dann stimmt es wieder für alles.
   ⚠️ `.kp-kacheln` steht bewusst NICHT drin: Die Kennzahlenreihe bringt ihren
   eigenen, kleineren Rand mit (`margin-bottom:8px`), und beides zusammen wäre
   zu viel Luft.
   📌 Spezifität 0-3-0 — schlägt die 20 px der Regel darüber, die damit nur
   noch außerhalb einer Registerkarte gilt. */
.kp-reiter-inhalt > :is(.karte, .kp-zweispalt)
  + :is(.karte, .kp-zweispalt){margin-top:32px}

/* --------------------------------------------------------------------------
   4b. Schaltflaechen
   Waren im ganzen Portal in Gebrauch (21 Stellen), aber nirgends definiert:
   base.css kennt nur .cta aus den Demoseiten. Deshalb sahen Formulare und
   Verwaltung bis 06.08.2026 nach unformatiertem HTML aus.
   -------------------------------------------------------------------------- */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:8px;
  padding:9px 18px;border:1px solid transparent;border-radius:10px;
  background:var(--brand);color:#fff;
  font:inherit;font-size:.92rem;font-weight:600;line-height:1.2;
  text-decoration:none;cursor:pointer;white-space:nowrap;
  transition:background .15s,border-color .15s,color .15s;
}
.btn:hover{background:var(--accent);color:#fff;text-decoration:none}
.btn:focus-visible{outline:2px solid var(--brand);outline-offset:2px}
.btn[disabled],.btn.aus{opacity:.5;pointer-events:none}

.btn-outline{
  background:transparent;color:var(--text);border-color:var(--line);
}
.btn-outline:hover{background:var(--brand-soft);color:var(--brand);border-color:var(--brand)}

.btn-klein{padding:5px 11px;font-size:.82rem;border-radius:8px}

.btn-gefahr{background:var(--danger);border-color:var(--danger)}
.btn-gefahr:hover{background:var(--danger);filter:brightness(.9)}

/* Mehrere Schaltflaechen nebeneinander bekommen Luft, ohne dass jede Seite
   das per style-Attribut regeln muss. */
.btn + .btn{margin-left:8px}

/* 🔴 …ABER NICHT DORT, WO DER CONTAINER SEINEN ABSTAND SCHON PER `gap` REGELT.
   Die Regel darüber ist für Knöpfe gedacht, die einfach nebeneinander im Text
   stehen. In einem Flex- oder Rasterkasten mit `gap` kommt sie ein zweites Mal
   obendrauf — und richtet dort zwei Schäden an:

     * Nebeneinander: 8 px `gap` + 8 px Rand = 16 px. Nur unschön.
     * ⚠️ NACH EINEM UMBRUCH: Der erste Knopf der zweiten Zeile ist immer noch
       ein `.btn + .btn` und trägt den Rand — er schiebt die GANZE zweite Zeile
       um 8 px nach rechts. Auf dem Handy, wo jede Knopfreihe umbricht, steht
       dann Zeile 1 bündig und alles darunter eingerückt.

   Genau so gemeldet: 14.08.2026 an `.kp-stammliste` („abteilungen ist weiter
   links als alle anderen"), 21.08.2026 an `.kp-sichtwahl` („die filter bubbels
   sind nicht bündig, die erste reihe weicht ab auf dem handy" — „zieht sich
   durch alle seiten mit diesen elementen"). Zweimal derselbe Fehler, weil beim
   ersten Mal nur der eine Kasten geflickt wurde.

   📌 WER EINEN NEUEN CONTAINER MIT `gap` BAUT, DER KNÖPFE ENTHÄLT, TRÄGT IHN
   HIER EIN. Das ist die eine Stelle dafür; CSS kann nicht selbst erkennen, ob
   ein Elternteil `gap` gesetzt hat. */
.btn-row > .btn + .btn,
.kal-kopf > .btn + .btn,
.kp-aktionen > .btn + .btn,
.kp-ansicht-knopf > .btn + .btn,
.kp-ansicht-liste > .btn + .btn,
.kp-ansicht-name > .btn + .btn,
.kp-ansicht-pfeile > .btn + .btn,
.kp-ansicht-zeile > .btn + .btn,
.kp-band-aktionen > .btn + .btn,
.kp-band-inner > .btn + .btn,
.kp-blaettern > .btn + .btn,
.kp-check > .btn + .btn,
.kp-hinweis-aktionen > .btn + .btn,
.kp-hinweis-filter > .btn + .btn,
.kp-hinweis-leiste > .btn + .btn,
.kp-kopfleiste > .btn + .btn,
.kp-listenfuss > .btn + .btn,
/* ⚠️ Nachgetragen am 21.08.2026: `.kp-listenkopf` fehlte in dieser Liste, weil
   sie aus einer Markup-Suche entstand — der Listenkopf wird aber in PHP
   erzeugt (`Liste::steuerung()`) und stand deshalb in keiner Vorlage. Folge:
   Export und Zahnrad hatten 16 px Abstand statt 8, und das Knopfpaar war
   genau diese 8 px breiter als der Suchknopf darueber. */
.kp-listenkopf > .btn + .btn,
.kp-msg-kopf > .btn + .btn,
.kp-news-kopf > .btn + .btn,
/* Nachgetragen am 26.08.2026 zusammen mit der Einrichtungscheckliste — beide
   Kaesten setzen `gap`. Eingetragen, obwohl heute je nur EIN `.btn` darin
   steht: Die Liste ist die Stelle, an der man es sonst erst nach dem zweiten
   Knopf merkt, und dann ueber ein schiefes Layout. */
.kp-onb-fuss > .btn + .btn,
.kp-onb-tat > .btn + .btn,
.kp-recht-zeichen > .btn + .btn,
.kp-reiter > .btn + .btn,
.kp-schnellsuche > .btn + .btn,
.kp-sichtwahl > .btn + .btn,
.kp-spf > .btn + .btn,
.kp-spf-fuss > .btn + .btn,
.kp-stammliste > .btn + .btn,
.kp-stimmung > .btn + .btn,
.kp-suchleiste > .btn + .btn,
.kp-suchseite-form > .btn + .btn,
.kp-wahl-fuss > .btn + .btn,
.kp-wahl-knoepfe > .btn + .btn,
.kp-woche > .btn + .btn,
.kp-woche-kopf > .btn + .btn,
.kp-woche-nav > .btn + .btn{margin-left:0}

/* --------------------------------------------------------------------------
   4c. Formulare in der Verwaltung
   -------------------------------------------------------------------------- */

/* 🔴 base.css setzt input{width:100%} — das trifft auch Kästchen und
   Auswahlknöpfe. Die Box wird dann auf volle Spaltenbreite gedehnt, das
   Häkchen sitzt mittig darin und der Text rutscht weit nach rechts. base.css
   hat dafür zwar eine Ausnahme (.check-row), die greift aber nur dort, wo
   jemand daran gedacht hat. Deshalb hier global. */
input[type="checkbox"],
input[type="radio"]{
  width:auto;min-width:0;flex:0 0 auto;
  accent-color:var(--brand);
}

.kp-form{max-width:none;padding:24px 26px}

.kp-fieldset{border:0;padding:0;margin:0 0 28px}
/* ⚠️ Der Umkreisblock haengt hinter einer fremden Karte und nicht zwischen
   zwei Fieldsets — dort gibt es kein voriges Element, dessen unteres Mass den
   Abstand traegt. Er bringt ihn deshalb selbst mit (21.08.2026). */
.kp-umkreis-block{margin-top:24px}
.kp-fieldset > legend{
  font-size:.72rem;font-weight:700;letter-spacing:.1em;text-transform:uppercase;
  color:var(--muted);padding:0;margin-bottom:12px;
  width:100%;border-bottom:1px solid var(--line);padding-bottom:7px;
}

/* Felder in gleich breiten Spalten, aber mit Obergrenze.
   Ohne die Obergrenze (früher 1fr) zog ein breiter Bildschirm jedes Feld auf
   über 500 px — auch das für eine einstellige Zahl. Jetzt bleiben die Spalten
   bei 340 px stehen und der Rest der Zeile bleibt leer; das sieht aufgeräumt
   aus, statt Platz zu füllen, nur weil er da ist. */
/* 🔴 `min(230px,100%)` und nicht `230px` (15.08.2026, Fund des Users: „beim
   account anlegen ragen diverse felder aus dem bereich heraus in dem sie
   liegen"). Ein Raster mit fester Mindestspalte wird NICHT schmaler als diese
   Zahl — ist der Kasten darum enger (Overlay auf dem Handy: 360 px minus
   Fenster-, Karten- und Feldsatzrand), läuft die Spalte über den Rand hinaus.
   Mit `min()` ist die Untergrenze bei engem Platz die Kastenbreite selbst. */
/* 🔴 `1fr` als OBERE Grenze, nicht `340px` (vom User beanstandet, 25.08.2026:
   „wieso ist die checkbox hauptkontakt richtig bis zum rand und die textboxen
   nicht?"). Gemessen bei 1181px Innenbreite: Die Spalten standen auf
   `340px 340px 340px`, macht mit den Abstaenden 1060px — **121px blieben
   rechts liegen**, waehrend die Kaestchenreihe daneben mit `584.5px 584.5px`
   sauber bis an den Rand ging.

   Der Grund steckt in `auto-fit`: Ist die obere Grenze eine feste Laenge,
   rechnet der Browser die SPALTENZAHL daraus (1181+20 durch 340+20 = 3) und
   laesst die Spalten dann auch auf 340px stehen. Der Rest bleibt uebrig.
   Mit `1fr` als oberer Grenze zaehlt die UNTERE fuer die Spaltenzahl, deshalb
   steht dort jetzt 340px: So kommen genau dieselben Spalten heraus wie vorher
   — sie dehnen sich nur bis zum Rand.

   ⚠️ `justify-content:start` bleibt bedeutungslos, sobald die Spalten die
   Breite ausfuellen; es steht nur noch fuer den Fall, dass eine einzelne
   Spalte auf einem sehr schmalen Fenster uebrigbleibt.
   → Grundsatz: „liegt am Rand" heisst verschenkter Platz, nicht Abstand. */
.kp-felder{
  display:grid;gap:16px 20px;
  grid-template-columns:repeat(auto-fit,minmax(min(340px,100%),1fr));
  justify-content:start;
  align-items:start;
}
.kp-felder > div{min-width:0}
.kp-felder label{margin-top:0}
.kp-felder small{display:block;margin-top:5px;font-size:.78rem;line-height:1.35}

/* 🔴 Engeres Raster für Gruppen aus lauter kurzen Feldern (28.08.2026,
   Ansage des Users zum Buchungsformular: „die felder sind nicht schön
   angeordnet und teilweise gibt es zuviel freiraum neben den feldern").

   `.kp-felder` gibt jeder Spalte mindestens 340 px. Das ist für Text und
   Auswahlfelder richtig, für Betrag (Eingabe max. 130 px) und Datumsfelder
   (max. 190 px) aber viel zu viel — daneben stand jeweils die halbe Spalte
   leer. Hier sind es 180 px, damit vier bis fünf kurze Felder in eine Reihe
   passen.

   ⚠️ Nur zusätzlich zu `.kp-felder` verwenden, nicht anstelle: Gap,
   `align-items` und die Regeln für `label`/`small` kommen von dort. */
.kp-felder-schmal{
  grid-template-columns:repeat(auto-fit,minmax(min(180px,100%),1fr));
}

/* Für Inhalte, die zwei Spalten brauchen — vor allem URLs. */
.kp-feld-breit{grid-column:span 2}
/* 🔴 Unter 700 px gibt es nur EINE Spalte. Ein Element, das zwei überspannt,
   erzeugt dann eine zweite Spalte, die es gar nicht geben soll — das Raster
   wird doppelt so breit wie sein Kasten.
   ⚠️ Genau deshalb darf `span 2` NIE als `style="…"` im Markup stehen: Eine
   Auszeichnung am Element schlägt jede Regel hier, auch diese. Neun solcher
   Stellen sind am 15.08.2026 auf die Klasse umgestellt worden. */
@media (max-width:700px){ .kp-feld-breit{grid-column:auto} }

/* 🔴 Datums- und Zeitfelder (15.08.2026, zweiter Anlauf).
   `min-width:0` allein genügte NICHT — der User meldete „Account seit ragt
   noch immer heraus" und dasselbe bei „Fällig am". Ursache ist die
   Standarddarstellung von WebKit: Solange `-webkit-appearance` auf dem
   eigenen Bedienelement steht, bemisst iOS das Feld nach seinem inneren
   Aufbau (Kalendersymbol plus TT.MM.JJJJ) und lässt `width:100%` links
   liegen. Erst `appearance:none` macht daraus ein gewöhnliches Feld, das sich
   an seine Spalte hält.
   ⚠️ Danach steht der Wert auf iOS mittig — `::-webkit-date-and-time-value`
   holt ihn nach links, wie in jedem anderen Eingabefeld auch. */
input[type="date"],
input[type="month"],
input[type="time"],
input[type="datetime-local"]{
  -webkit-appearance:none;appearance:none;
  display:block;box-sizing:border-box;
  width:100%;min-width:0;max-width:100%;
}
input[type="date"]::-webkit-date-and-time-value,
input[type="month"]::-webkit-date-and-time-value,
input[type="time"]::-webkit-date-and-time-value,
input[type="datetime-local"]::-webkit-date-and-time-value{
  text-align:left;
}

/* Und für das Gegenteil: Zahlen brauchen keine 340 px. */
.kp-feld-kurz input{max-width:130px}

/* 🔴 …ein DATUM aber schon (17.08.2026, Meldung des Users: „die datums box ist
   viel zu schmal ich kann das jahr nicht richtig tippen", Formular „Leistung
   erfassen").
   Die 130 px oben sind für Zahlenfelder gedacht. Ein Datumsfeld zeigt seit dem
   `appearance:none`-Fix darüber „31.12.2026" als gewöhnlichen Text plus
   Kalendersymbol — das sind rund 145 px, der Jahresblock wird also
   abgeschnitten und lässt sich nicht mehr sauber tippen.
   ⚠️ `min()` statt eines festen Wertes: Auf einem schmalen Schirm gilt wieder
   die Spaltenbreite, sonst ragt das Feld dort heraus — dieselbe Falle wie bei
   `minmax(<px>,…)` in den Rastern. */
.kp-feld-kurz input[type="date"],
.kp-feld-kurz input[type="month"],
.kp-feld-kurz input[type="time"],
.kp-feld-kurz input[type="datetime-local"]{max-width:min(190px,100%)}

/* Kästchen: Box links, fette Bezeichnung, Erklärung darunter. Vorher stand
   die Erklärung in einer Zeile neben der Box und trieb die Zeile auseinander. */
.kp-checks{
  display:grid;gap:12px;
  grid-template-columns:repeat(auto-fit,minmax(min(300px,100%),1fr));
  margin-bottom:20px;
}
.kp-check{
  display:flex;align-items:flex-start;gap:11px;
  margin:0;font-weight:400;
  padding:13px 15px;
  background:var(--kp-tile-bg);
  border:1px solid var(--line);border-radius:var(--radius-sm);
  cursor:pointer;
}
.kp-check:hover{border-color:var(--brand)}
.kp-check input{margin-top:2px}
.kp-check > span{display:block;min-width:0}
.kp-check b{display:block;font-weight:700;font-size:.92rem;margin-bottom:3px}
.kp-check small{display:block;color:var(--muted);font-size:.8rem;line-height:1.4}
.kp-check:has(input:checked){border-color:var(--brand);background:var(--brand-soft)}

/* 🔴 Einzeilige Kästchen mittig ausrichten (vom User beanstandet, 10.08.2026:
   „die checkbox bei moderne ansicht sitzt höher als der text").
   `align-items:flex-start` oben ist für die KACHELN gedacht — dort stehen
   eine fette Überschrift und ein Erklärtext, und das Kästchen gehört auf die
   erste Zeile. Wo nur eine Zeile steht (kein <b>), ist genau das falsch: Das
   Kästchen klebt an der Oberkante einer höheren Zeilenbox.
   Erkannt am fehlenden <b> statt an einer neuen Klasse — so greift es
   automatisch bei jedem einzeiligen Kästchen, auch bei künftigen. */
.kp-check:not(:has(b)){align-items:center}
.kp-check:not(:has(b)) input{margin-top:0}

.kp-aktionen{
  display:flex;gap:10px;flex-wrap:wrap;align-items:center;
  padding-top:6px;
}

/* Typ der Beziehung: kompakte Schalter in einer Reihe, keine Erklärkacheln —
   „Kunde" und „Lieferant" erklären sich selbst. */
.kp-feldlabel{font-weight:600;margin:0 0 8px;font-size:.9rem}
/* Feldüberschrift mit Knopf ganz rechts (etwa „Neu" beim Beziehungstyp). */
.kp-feldlabel-mit-knopf{
  display:flex;align-items:center;justify-content:space-between;gap:12px;
}
.kp-typen{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:20px}
.kp-typ{
  display:inline-flex;align-items:center;gap:8px;margin:0;
  padding:7px 14px;font-weight:600;font-size:.88rem;
  background:var(--kp-tile-bg);
  border:1px solid var(--line);border-radius:999px;cursor:pointer;
}
.kp-typ:hover{border-color:var(--brand)}
.kp-typ:has(input:checked){background:var(--brand-soft);border-color:var(--brand);color:var(--brand)}

/* „Neu" als eigene Bubble in derselben Reihe (11.08.2026, Ansage des Users:
   „vielleicht einfach neben die auswahl bubbels eine farblich abgesetzte
   bubbel mit Neu"). Vorher saß der Knopf am rechten Rand der Label-Zeile —
   getrennt von dem, was er anlegt, mit einer breiten Lücke dazwischen.
   Gestrichelter Rand: Es ist kein Wert, den man auswählt, sondern ein Weg
   hinaus. */
.kp-typ-neu{
  border-style:dashed;border-color:var(--brand);color:var(--brand);
  background:transparent;text-decoration:none;
}
.kp-typ-neu:hover{background:var(--brand-soft);text-decoration:none}

/* Rechtematrix: Auge = sehen, Auge+Stift = bearbeiten (11.08.2026) --------
   Der Haken war irreführend — in einer Tabelle liest er sich als „erledigt".
   Zwei Arten von Zugriff brauchen zwei unterscheidbare Zeichen. */
.kp-recht-zeichen{
  display:inline-flex;align-items:center;gap:4px;color:var(--muted);
  vertical-align:-3px;
}
.kp-recht-zeichen.darf{color:var(--brand)}

/* Kästchen in der Rechtematrix: ohne Kachelrahmen. `.kp-check` ist für
   Einstellungskacheln gedacht und füllt die Spalte — bei zwei verschieden
   breiten Spalten sah man zwei verschieden breite Rahmen. */
.kp-recht-box{
  display:inline-flex;align-items:center;justify-content:center;
  margin:0;padding:6px;cursor:pointer;
}
.kp-recht-box input{width:17px;height:17px;margin:0;cursor:pointer}
.kp-recht-box input:disabled{cursor:not-allowed;opacity:.5}

/* Suchleiste über der Liste
   --------------------------------------------------------------------------
   🔴 EINE Zeile: Auswahlfeld, Suchfeld, Knöpfe (28.08.2026, Ansage des Users:
   „ich möchte gern alles in einer zeile: dropdown, suchtextfeld und buttons,
   mobil bricht es bitte um und richtig ausgerichtet und bündig").

   ⚠️ Die Zeile war schon vorher Flex — der Bruch kam daher, dass einzelne
   Listen ihre Leiste von Hand mit `style="display:flex;…"` gebaut haben, mit
   eigenen Abständen und ohne Regeln fürs Handy. Solche Auszeichnungen am
   Element schlagen jede Regel hier. Wer eine neue Liste baut, nimmt diese
   Klasse und nichts Eigenes. */
.kp-suchleiste{display:flex;gap:10px;flex-wrap:wrap;margin-bottom:18px;align-items:center}
/* Steht eine Karte direkt ueber der Suchleiste, klebten beide aneinander:
   `.karte` traegt bewusst keinen Aussenabstand (sie liegt meist im Raster
   `.kp-karten` mit eigenem `gap`), und die Suchleiste bringt nur einen unteren
   mit. Gemeldet am 03.09.2026 an der Demoverwaltung. Die Regel greift genau
   in dieser Reihenfolge und aendert an den Rasterfaellen nichts. */
.karte + .kp-suchleiste{margin-top:18px}
.kp-suchleiste input{max-width:380px}
.kp-suchleiste select{max-width:190px}
.kp-suchleiste input,.kp-suchleiste select{padding:9px 12px}
/* 🔴 Bündig heisst: gleiche Höhe. Eingabefelder rechnen ihre Höhe aus Polster
   und Schriftgrösse, Knöpfe aus ihren eigenen Werten — ohne gemeinsames Mass
   sitzt der Knopf ein bis zwei Pixel höher als das Feld daneben, und genau das
   sieht man in einer Zeile. */
.kp-suchleiste input,
.kp-suchleiste select,
.kp-suchleiste > .btn{height:40px;min-height:40px}
/* ⚠️ `height` und nicht nur `min-height`: Ein Auswahlfeld rechnet seine Höhe
   aus Polster PLUS Zeilenhöhe und kam damit auf 42 px, während Feld und Knopf
   auf 40 standen. Nachgemessen an der Accountliste — zwei Pixel, aber in einer
   Zeile nebeneinander sieht man sie. */
.kp-suchleiste > .btn{display:inline-flex;align-items:center}
/* Das Suchfeld nimmt den freien Platz, die Knöpfe behalten ihre Breite —
   sonst stehen sie mitten in der Zeile statt am Ende der Bedienelemente. */
.kp-suchleiste input[type="search"],
.kp-suchleiste input[name="q"]{flex:1 1 220px}

/* 🔴 Die Filterreihe wird zum Auswahlfeld IN der Suchleiste (28.08.2026).
   `portal.js` baut aus der Knopfreihe ein Auswahlfeld — bisher nur fürs Handy,
   jetzt immer, und es steht in derselben Zeile wie Suchfeld und Knöpfe.
   Die Knopfreihe selbst bleibt im Markup und wird nur ausgeblendet: Ohne
   JavaScript ist sie der einzige Weg zum Filter, und dann muss sie da sein.

   ⚠️ Ausgeblendet wird sie von `portal.js` selbst (`hidden`), NICHT per Regel
   hier: Eine CSS-Regel gälte auch ohne JavaScript, und dann wäre der Filter
   gar nicht mehr erreichbar. Eine Regel, die etwas ausblendet, braucht einen
   Ausfallmodus in Richtung „sichtbar". */
.kp-sichtwahl-feld{max-width:230px}

/* 🔴 AM SCHREIBTISCH GIBT ES NUR DIE KNÖPFE (28.08.2026, Entscheidung des
   Users: „die dropdown können wir generell am pc deaktivieren und mobile
   anzeigen, die knöpfe mobil weg und die dropdown zeigen").

   Vorher standen beide gleichzeitig da — nachgemessen an den Erinnerungen und
   den Aufgaben: Knopfreihe auf top=237, Auswahlfeld auf 279. Zweimal derselbe
   Filter untereinander. Das war kein neuer Fehler, sondern fiel nur nicht auf,
   solange niemand hinsah.

   ⚠️ Beide Fassungen bleiben im DOM — `portal.js` baut sie einmal, die Breite
   entscheidet. Beim Drehen des Geräts muss so nichts umgebaut werden.
   ⚠️ Es sind ZWEI Selektoren: `.kp-sichtwahl-klein` ist die eigene Hülle auf
   Seiten ohne Suchleiste (Erinnerungen, Aufgaben), `.kp-sichtwahl-feld` das
   Feld, das auf allen anderen Seiten in die Suchleiste gewandert ist. Wer nur
   einen davon ausblendet, sieht das Feld weiterhin auf der halben Portalseite. */
.kp-sichtwahl-klein,
.kp-suchleiste .kp-sichtwahl-feld{display:none}

/* 🔴 Am Handy untereinander und volle Breite. `flex-wrap` allein genügt nicht:
   Es bricht zwar um, lässt die Felder aber auf ihrer Maximalbreite stehen —
   dann steht ein 190 px breites Auswahlfeld allein in einer Zeile und daneben
   bleibt der halbe Bildschirm leer. Breite statt Abstand, wie überall. */
@media (max-width:640px){
  .kp-suchleiste{align-items:stretch}
  .kp-suchleiste input,
  .kp-suchleiste select,
  .kp-suchleiste > .btn,
  .kp-suchleiste .kp-feld-symbolisch{max-width:none;width:100%;flex:1 1 100%}
}
/* 🔴 Ein Feld MIT Symbol behält seinen Einzug (13.08.2026, vom User beanstandet:
   „die suchtextbox ist gequetscht, der text ragt unter die lupe"). Die Regel
   darüber ist mit `.kp-suchleiste input` stärker als `.kp-feld-eingerueckt`
   und setzte den linken Abstand auf 12 px zurück — der Text lief unter das
   Symbol. Gilt für JEDE Suchleiste mit Symbolfeld, nicht nur für die eine. */
.kp-suchleiste .kp-feld-eingerueckt{padding-left:38px}
.kp-suchleiste .kp-feld-symbolisch{max-width:380px;flex:1 1 220px}

/* --------------------------------------------------------------------------
   5. Kennzahlen-Kacheln
   -------------------------------------------------------------------------- */
.kp-kacheln{
  display:grid;gap:14px;
  grid-template-columns:repeat(auto-fit,minmax(min(190px,100%),1fr));
  margin-bottom:8px;
}
.kp-kachel{
  background:var(--kp-tile-bg);
  border:1px solid var(--line);
  border-radius:var(--radius-sm);
  padding:16px 18px;
}
.kp-kachel-wert{font-size:1.7rem;font-weight:800;line-height:1.1;color:var(--text)}
.kp-kachel-wert.klein{font-size:1.12rem;font-weight:700}
.kp-kachel-lbl{font-size:.78rem;color:var(--muted);margin-top:7px}
a.kp-kachel{display:block;color:inherit;text-decoration:none;transition:border-color .15s,transform .15s}
a.kp-kachel:hover{text-decoration:none;border-color:var(--brand);transform:translateY(-2px)}

/* Ampel fuer den Vertrags- bzw. Datenstand */
.kp-ampel{display:inline-flex;align-items:center;gap:7px}
.kp-ampel::before{content:"";width:9px;height:9px;border-radius:50%;flex:0 0 auto;background:var(--muted)}
.kp-ampel.gut::before{background:var(--kp-gut)}
.kp-ampel.warn::before{background:var(--kp-warn)}
.kp-ampel.stop::before{background:var(--danger)}

/* --------------------------------------------------------------------------
   6. Listen und Tabellen
   -------------------------------------------------------------------------- */
.kp-liste{list-style:none;margin:0;padding:0}
.kp-liste li{
  display:flex;align-items:baseline;gap:12px;flex-wrap:wrap;
  padding:11px 0;border-bottom:1px solid var(--line);
}
.kp-liste li:last-child{border-bottom:0;padding-bottom:0}
.kp-liste li:first-child{padding-top:0}
.kp-liste-name{font-weight:600}
.kp-liste-meta{margin-left:auto;font-size:.84rem;color:var(--muted);white-space:nowrap}

/* Die Leistungsliste auf der Übersicht des Kunden (03.09.2026).
   Ansage des Users: „die kategorie bitte IMMER in die nächste zeile
   umbrechen und nicht aufgrund der textlänge vorher".

   🔴 Deshalb ein RASTER statt Flex mit Umbruch. Vorher entschied die Länge
   des Leistungsnamens, wo die Kategorie landet: Bei „Hosting & Betreuung
   Statisch/OnePager" rutschte sie in die zweite Zeile, bei „Erstellung
   Website WordPress" stand sie daneben — und dann schob sie das Datum
   hinunter. Vier Einträge, drei verschiedene Zeilenbilder. Das Raster legt
   beides fest: Name oben über die volle Breite, darunter Kategorie links und
   Datum rechts.

   ⚠️ `justify-self` statt `margin-left:auto` beim Datum — im Raster hat die
   automatische Marge keine Wirkung, und ohne sie stünde das Datum an der
   Kategorie geklebt. */
.kp-leistungsliste li{
  display:grid;
  grid-template-columns:1fr auto;
  grid-template-areas:"name name" "marke meta";
  align-items:baseline;
  gap:6px 12px;
}
.kp-leistungsliste .kp-liste-name{grid-area:name}
.kp-leistungsliste .kp-marke{grid-area:marke;justify-self:start}
.kp-leistungsliste .kp-liste-meta{grid-area:meta;justify-self:end;margin-left:0}

/* Auf schmalen Schirmen darf ein langer Leistungsname umbrechen, statt die
   Karte zu sprengen — die Marke bleibt trotzdem in ihrer eigenen Zeile. */
@media (max-width:560px){
  .kp-leistungsliste li{gap:4px 10px;padding:9px 0}
  .kp-leistungsliste .kp-liste-name{line-height:1.3}
  .kp-leistungsliste .kp-liste-meta{font-size:.8rem}
}

/* --------------------------------------------------------------------------
   Diagramme

   🔴 Die Serienfarbe ist NICHT die Markenfarbe des Mandanten — bewusst.
   --brand ist je Mandant frei einstellbar; eine hellgelbe oder blassgraue
   Marke ergaebe unlesbare Balken, und unser eigenes Rot ist von der
   Warnfarbe kaum zu unterscheiden. Deshalb ein festes, geprueftes Blau.
   Geprueft heisst: gegen die echten Kartenfarben (#ffffff hell, #1a2030
   dunkel) durch den Palettenvalidator gelaufen — Helligkeitsband, Chroma,
   Kontrast alle bestanden.

   Ebenfalls geprueft und deshalb VERWORFEN: ein gestapelter Balken in den
   Statusfarben. Status-Rot und Status-Gruen liegen unter Deuteranopie nur
   4,1 auseinander (noetig waeren 8) — fuer Rotgrunblinde nicht zu trennen.
   Alle Verteilungen tragen daher EINE Farbe; die Aussage steckt in der
   Laenge, nicht im Farbton.
   -------------------------------------------------------------------------- */
/* ⚠️ Diese Werte sind nur die VORGABE. Hat der Mandant einen Farbsatz gewählt,
   überschreibt `_layout.php` sie im Kopf → src/Diagrammfarben.php.
   `--viz-serie-2` ist die zweite KATEGORIE (nicht dieselbe Farbe heller): Sie
   trägt dort, wo zwei Dinge nebeneinanderstehen, etwa im Vollkreis. */
:root{
  --viz-serie:#2a78d6;
  --viz-serie-2:#eb6834;
  --viz-serie-hell:#5598e7;
  --viz-flaeche:rgba(42,120,214,.10);
  --viz-grid:#e5e7eb;
  --viz-achse:#c3c2b7;
  --viz-text:#6b7280;
}
html[data-theme="dark"]{
  --viz-serie:#3987e5;
  --viz-serie-2:#d95926;
  --viz-serie-hell:#6da7ec;
  --viz-flaeche:rgba(57,135,229,.14);
  --viz-grid:rgba(255,255,255,.10);
  --viz-achse:rgba(255,255,255,.20);
  --viz-text:#94a3b8;
}

.kp-chart{margin:0;position:relative}
.kp-chart-flaeche{position:relative;min-height:40px}
.kp-chart svg{display:block;overflow:visible}
/* Beschriftung traegt Text-, nie Datenfarben. */
.kp-chart-tick{font-size:.72rem;font-variant-numeric:tabular-nums}
.kp-chart-name{font-size:.82rem}
.kp-chart-wert{font-size:.78rem;font-variant-numeric:tabular-nums}
.kp-chart-stab{transition:fill .15s}
.kp-chart-stab.hell{fill:var(--viz-serie-hell)}
.kp-chart rect[tabindex]:focus-visible{outline:2px solid var(--viz-serie);outline-offset:1px}

.kp-chart-tip{
  position:absolute;z-index:5;pointer-events:none;
  background:var(--kp-tip-bg);color:var(--kp-tip-text);
  padding:7px 10px;border-radius:8px;font-size:.8rem;line-height:1.35;
  box-shadow:0 6px 20px rgba(0,0,0,.22);white-space:nowrap;
}
.kp-chart-tip strong{display:block;font-variant-numeric:tabular-nums}
.kp-chart-tip span{opacity:.75;font-size:.74rem}

.kp-chart-fuss{
  margin:10px 0 0;font-size:.78rem;color:var(--muted);
}

/* Gesamtzahl unter einem Diagramm. Gebraucht beim VOLLKREIS: Beim Ring steht
   sie in der freien Mitte, beim Kreis gibt es die nicht — und im Fließtext
   ginge sie unter. Absichtlich allgemein benannt, nicht „umsatz". */
.kp-chart-summe{
  display:flex;align-items:baseline;gap:9px;flex-wrap:wrap;
  margin:14px 0 0;padding-top:12px;border-top:1px solid var(--line);
}
.kp-chart-summe strong{
  font-size:1.3rem;font-weight:700;color:var(--text);
  font-variant-numeric:tabular-nums;line-height:1.2;
}
.kp-chart-summe span{color:var(--muted);font-size:.85rem}

/* Ueberschrift ueber einer einzelnen Flaeche — noetig, sobald zwei kleine
   Diagramme nebeneinander stehen: Ohne Beschriftung waere nicht zu sehen,
   welche Reihe welche ist. */
.kp-chart-titel{
  margin:0 0 6px;font-size:.82rem;font-weight:600;color:var(--muted);
  text-transform:none;
}

/* Die Tabelle unter den Diagrammen — zugleich die barrierefreie Zweitfassung:
   jeder Wert aus einer Grafik ist hier als Text zu lesen. */
.kp-tabelle-klapp summary{
  cursor:pointer;font-size:.84rem;color:var(--muted);
  padding:8px 0;list-style:none;
}
.kp-tabelle-klapp summary::-webkit-details-marker{display:none}
.kp-tabelle-klapp summary::before{content:"▸ ";display:inline-block;transition:transform .15s}
.kp-tabelle-klapp[open] summary::before{content:"▾ "}
.kp-tabelle-klapp summary:hover{color:var(--text)}

/* Ringdiagramm (Stimmungsbarometer).
   🔴 Die Legende ist hier keine Zugabe, sondern Pflicht: Status-Rot und
   Status-Gruen sind fuer Rotgruenblinde kaum zu trennen, und im Kreis
   beruehren sich alle Segmente. Wort und Zahl tragen die Aussage. */
.kp-ring-box{display:flex;gap:22px;align-items:center;flex-wrap:wrap}
.kp-ring-summe{font-size:1.5rem;font-weight:800}
.kp-ring-lbl{font-size:.72rem}
.kp-ring-teil{cursor:pointer;transition:stroke-width .15s}
.kp-ring-teil:focus-visible{outline:2px solid var(--brand);outline-offset:2px}

.kp-ring-legende{list-style:none;margin:0;padding:0;flex:1 1 190px;min-width:180px}
.kp-ring-legende li{
  display:flex;align-items:center;gap:9px;
  padding:7px 0;border-bottom:1px solid var(--line);font-size:.9rem;
}
.kp-ring-legende li:last-child{border-bottom:0}
.kp-ring-punkt{width:10px;height:10px;border-radius:50%;flex:0 0 auto}
.kp-ring-name{flex:1 1 auto}
.kp-ring-wert{font-weight:700;font-variant-numeric:tabular-nums;white-space:nowrap}
.kp-ring-anteil{
  font-weight:400;color:var(--muted);font-size:.8rem;margin-left:7px;
}

/* Stimmungsmarke in Listen und Tabellen */
.kp-stimmung{display:inline-flex;align-items:center;gap:7px;white-space:nowrap}
.kp-stimmung::before{content:"";width:9px;height:9px;border-radius:50%;flex:0 0 auto}
.kp-stimmung.gruen::before{background:#0ca30c}
.kp-stimmung.gelb::before {background:#fab219}
.kp-stimmung.rot::before  {background:#d03b3b}
.kp-stimmung.ohne::before {background:#9ca3af}

/* --------------------------------------------------------------------------
   Nachrichten — Aufbau nach dem Vorbild des LMS: Gespraechsliste links,
   Verlauf als Sprechblasen, eigene rechts in der Markenfarbe.
   -------------------------------------------------------------------------- */
/* Avatarkreis fuer Personen, aus Profil::avatar().
   Groesse und Farbe kommen als Inline-Stil mit: Sie haengen an der Person und
   an der Stelle, nicht am Thema. Hier steht nur, was immer gilt. */
.kp-avatar-kreis{
  display:inline-flex;align-items:center;justify-content:center;
  border-radius:50%;overflow:hidden;flex:0 0 auto;vertical-align:middle;
  background:var(--kreis,var(--brand));color:#fff;
  font-weight:700;letter-spacing:.02em;line-height:1;
  user-select:none;
}
.kp-avatar-kreis img{width:100%;height:100%;object-fit:cover;display:block}

/* Gespraechsliste: Bild und Name in einer Zeile. */
.kp-msg-eintrag .kp-liste-name{display:flex;align-items:center;gap:10px;min-width:0}
.kp-msg-eintrag .kp-liste-name > span{
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}

/* Benutzermenue oben rechts (Vorbild LMS).
   <details>/<summary> statt eigener Klapplogik: schliesst beim Klick nach
   aussen von selbst und ist ohne JavaScript bedienbar. */
.kp-benutzer{position:relative}
.kp-benutzer > summary{
  display:flex;align-items:center;gap:9px;cursor:pointer;
  padding:5px 10px 5px 5px;border-radius:999px;
  /* Der Rahmen steht IMMER (Ansage des Users 08.08.2026): Ohne ihn sieht der
     Knopf nicht nach Bedienelement aus, und beim Ueberfahren sprang vorher
     die Umrandung ins Bild. */
  border:1px solid var(--line);list-style:none;
  transition:background .15s ease, border-color .15s ease;
}
.kp-benutzer > summary::-webkit-details-marker{display:none}
.kp-benutzer > summary::marker{content:""}
.kp-benutzer > summary:hover{background:var(--brand-soft);border-color:var(--brand)}
.kp-benutzer > summary:focus-visible{outline:2px solid var(--brand);outline-offset:2px}

/* Aufgeklappt deutlich abgesetzt — der Knopf gehoert dann sichtbar zum
   Kasten darunter. */
.kp-benutzer[open] > summary{
  background:var(--brand-soft);
  border-color:var(--brand);
}

.kp-benutzer-bild{
  width:30px;height:30px;border-radius:50%;flex:0 0 auto;
  display:flex;align-items:center;justify-content:center;overflow:hidden;
  background:var(--kreis,var(--brand));color:#fff;
  font-size:.72rem;font-weight:700;letter-spacing:.02em;
}
.kp-benutzer-bild img{width:100%;height:100%;object-fit:cover;display:block}
.kp-benutzer-name{
  font-size:.86rem;font-weight:600;max-width:190px;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.kp-benutzer-pfeil{color:var(--muted);flex:0 0 auto;transition:transform .15s}
.kp-benutzer[open] .kp-benutzer-pfeil{transform:rotate(180deg)}

.kp-benutzer-klapp{
  position:absolute;right:0;top:calc(100% + 8px);z-index:60;
  min-width:230px;padding:6px;
  /* 🔴 `--kp-flyout`, nicht `--card` (vom User beanstandet, 10.08.2026:
     „abmelden ist so schlechter lesbar"). Bei eingeschalteter Glasoptik ist
     `--card` = `rgba(255,255,255,.06)`; der Kasten war fast durchsichtig und
     der Seiteninhalt las sich hindurch. Dieselbe Falle wie beim Filterkasten
     und beim Diagramm-Tooltip. **Merksatz: Jeder Kasten, der ÜBER dem Inhalt
     schwebt, braucht eine deckende Fläche.** */
  background:var(--kp-flyout);border:1px solid var(--line);border-radius:12px;
  box-shadow:0 14px 40px rgba(0,0,0,.22);
}
.kp-benutzer-kopf{
  margin:0;padding:8px 10px 10px;border-bottom:1px solid var(--line);
  display:flex;flex-direction:column;gap:2px;
}
.kp-benutzer-kopf strong{font-size:.88rem}
.kp-benutzer-kopf span{
  font-size:.76rem;color:var(--muted);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.kp-benutzer-klapp a{
  display:flex;align-items:center;gap:10px;
  padding:9px 11px;border-radius:8px;
  font-size:.88rem;color:var(--text);text-decoration:none;
  /* Der Streifen links entsteht aus dem Rahmen — so springt beim Ueberfahren
     nichts, weil die Breite von Anfang an steht. */
  border-left:2px solid transparent;
  transition:background .14s ease, color .14s ease, border-color .14s ease;
}
.kp-benutzer-symbol{
  color:var(--muted);flex:0 0 auto;
  transition:color .14s ease, transform .14s ease;
}
.kp-benutzer-klapp a > span{flex:1 1 auto}

.kp-benutzer-klapp a:hover,
.kp-benutzer-klapp a:focus-visible{
  background:var(--brand-soft);
  color:var(--brand);
  border-left-color:var(--brand);
  outline:none;
}
.kp-benutzer-klapp a:hover .kp-benutzer-symbol,
.kp-benutzer-klapp a:focus-visible .kp-benutzer-symbol{
  color:var(--brand);
  transform:translateX(1px);
}

/* Zahl der ungelesenen Nachrichten in der Zeile. */
.kp-benutzer-zahl{
  flex:0 0 auto;min-width:20px;padding:1px 6px;border-radius:999px;
  background:var(--brand);color:#fff;
  font-size:.7rem;font-weight:700;text-align:center;
}

/* Abmelden abgesetzt: Es ist die einzige Zeile mit Folgen. */
.kp-benutzer-aus{
  margin-top:5px;padding-top:11px !important;
  border-top:1px solid var(--line);
  color:var(--danger) !important;
}
.kp-benutzer-aus .kp-benutzer-symbol{color:var(--danger);opacity:.7}
.kp-benutzer-aus:hover,
.kp-benutzer-aus:focus-visible{
  background:color-mix(in srgb, var(--danger) 10%, transparent);
  border-left-color:var(--danger);
}
.kp-benutzer-aus:hover .kp-benutzer-symbol,
.kp-benutzer-aus:focus-visible .kp-benutzer-symbol{
  color:var(--danger);opacity:1;
}

/* Wer die Bewegung abbestellt hat, bekommt nur den Farbwechsel. */
@media (prefers-reduced-motion:reduce){
  .kp-benutzer-klapp a,
  .kp-benutzer-symbol{transition:none}
  .kp-benutzer-klapp a:hover .kp-benutzer-symbol{transform:none}
}

/* Auf schmalen Schirmen bleibt nur das Bild — der Name frisst die Kopfzeile. */
@media (max-width:640px){
  .kp-benutzer-name{display:none}
  .kp-benutzer-klapp{min-width:200px}
}

/* Profil: Bild, Initialen und die Vorlagen.
   Der Initialenkreis bekommt seine Farbe ueber --kreis aus dem Markup — sie
   haengt an der Person, nicht am Thema. */
.kp-profil-bild{display:flex;align-items:center;gap:16px;margin-bottom:14px}
.kp-profil-bild img{
  width:96px;height:96px;border-radius:50%;object-fit:cover;
  border:2px solid var(--line);flex:0 0 auto;
}
.kp-initialen{
  width:96px;height:96px;border-radius:50%;flex:0 0 auto;
  display:flex;align-items:center;justify-content:center;
  background:var(--kreis,#2a5c8f);color:#fff;
  font-size:2rem;font-weight:700;letter-spacing:.02em;
  /* Die Palette in Profil::farbe() ist auf weisse Schrift ausgelegt. */
}

/* 🔴 Fünf je Reihe statt freiem Umbruch (Ansage des Users, 11.08.2026:
   „jetzt sind erste reihe 7 zweite reihe 3 bilder"). Mit `flex-wrap` hing die
   Zahl je Reihe an der Fensterbreite, und die letzte Reihe blieb angebrochen.
   Ein Raster mit fester Spaltenzahl bricht immer gleich. */
.kp-avatare{
  display:grid;grid-template-columns:repeat(5, max-content);
  gap:10px;margin-top:6px;justify-content:start;
}
@media (max-width:520px){
  .kp-avatare{grid-template-columns:repeat(4, max-content)}
}
.kp-avatar{
  padding:0;border:2px solid transparent;border-radius:50%;
  background:none;cursor:pointer;line-height:0;
}
.kp-avatar img{width:48px;height:48px;border-radius:50%;object-fit:cover;display:block}
.kp-avatar:hover{border-color:var(--line)}
.kp-avatar.aktiv{border-color:var(--brand)}
.kp-avatar:focus-visible{outline:2px solid var(--brand);outline-offset:2px}

/* Eingabefelder mit Symbol (Vorbild LMS).
   Der Wrapper ist die Bezugsflaeche fuer beide Overlays; das Symbol nimmt
   keine Klicks an, sonst laesst sich das Feld an seiner linken Kante nicht
   fokussieren. */
.kp-feld-symbolisch{position:relative;display:block}
.kp-feld-symbol{
  position:absolute;left:12px;top:50%;transform:translateY(-50%);
  color:var(--muted);pointer-events:none;display:flex;align-items:center;
}
.kp-feld-eingerueckt{padding-left:38px}
.kp-feld-mit-auge{padding-right:40px}

/* Fehlende Angabe (11.08.2026) — dasselbe Feld mit Symbol wie bei der Suche,
   nur in der Warnfarbe. Der Kunde kommt vom Dashboard („Für Ihre Rechnungen
   fehlt noch: …") hierher und muss sehen, WELCHES Feld gemeint ist; eine
   Meldung allein über dem Formular beantwortet das nicht.
   Der Rahmen ist bewusst nur getönt und nicht rot wie ein Fehler: Es ist
   nichts falsch eingegeben, es steht nur noch nichts drin. */
.kp-feld-fehlt .kp-feld-symbol{color:var(--kp-warn)}
.kp-feld-fehlt input{border-color:var(--kp-warn)}
.kp-feld-fehlt input:focus{border-color:var(--brand)}
.kp-felder small.kp-feld-fehlt-text,
small.kp-feld-fehlt-text{
  display:block;margin-top:5px;color:var(--kp-warn-text);
  font-size:.8rem;line-height:1.35;
}

/* Abwesenheitskalender, Monatsansicht (13.08.2026) ------------------------
   Der erste Entwurf war ein Jahresraster mit 6-px-Spalten — technisch dicht,
   praktisch unlesbar (vom User beanstandet). Jetzt Wochen als Zeilen, Tage als
   Kacheln, Namen im Klartext. */
.kal-kopf{
  display:flex;gap:16px;flex-wrap:wrap;align-items:center;
  justify-content:space-between;margin-bottom:14px;
}
.kal-wahl{display:flex;gap:10px;align-items:center;margin:0}
.kal-wahl .kp-auswahl{width:auto;min-width:140px}
.kal-titel{margin:0 0 12px;font-size:1.15rem}

.kal-monat{
  display:grid;grid-template-columns:repeat(7,minmax(0,1fr));gap:6px;
}
.kal-wt{
  font-size:.72rem;font-weight:700;letter-spacing:.08em;text-transform:uppercase;
  color:var(--muted);padding:0 0 4px 2px;
}
.kal-tag{
  min-height:104px;padding:6px;
  border:1px solid var(--line);border-radius:8px;
  background:var(--card);
  display:flex;flex-direction:column;gap:3px;
}
.kal-leer{background:transparent;border-color:transparent}
.kal-zahl{
  font-weight:700;font-size:.9rem;line-height:1;
  display:flex;align-items:center;justify-content:space-between;gap:4px;
}
/* Klappmenü in der Kachel: „＋" erscheint erst beim Überfahren, sonst stünden
   31 Pluszeichen im Raster und der Blick fände die Namen nicht mehr.
   ⚠️ Beim Tastaturfokus und im geöffneten Zustand bleibt es sichtbar — sonst
   wäre es ohne Maus unauffindbar. */
.kal-menu{position:relative}
.kal-menu > summary{
  list-style:none;cursor:pointer;line-height:1;
  padding:1px 5px;border-radius:5px;color:var(--muted);
  opacity:0;transition:opacity .12s;
}
.kal-menu > summary::-webkit-details-marker{display:none}
.kal-tag:hover .kal-menu > summary,
.kal-menu[open] > summary,
.kal-menu > summary:focus-visible{opacity:1}
.kal-menu > summary:hover{background:var(--hover);color:var(--text)}
.kal-menu-liste{
  position:absolute;z-index:30;top:calc(100% + 4px);right:0;min-width:190px;
  padding:6px;border:1px solid var(--line);border-radius:var(--radius);
  background:var(--kp-flyout);box-shadow:0 14px 40px rgba(0,0,0,.35);
  font-weight:400;
}
.kal-menu-liste a{
  display:block;padding:7px 10px;border-radius:6px;
  font-size:.85rem;text-decoration:none;color:var(--text);white-space:nowrap;
}
.kal-menu-liste a:hover{background:var(--hover)}
/* Betriebsfrei: eigene Kennzeichnung neben dem gesetzlichen Feiertag. */
.kal-tag.kal-betriebsfrei{background:rgba(224,161,42,.16);border-color:#e0a12a}
.kal-betrieb{
  font-size:.72rem;line-height:1.2;color:var(--kp-warn-text);font-weight:600;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.kal-legende .kal-betriebsfrei{background:rgba(224,161,42,.5);border-color:#e0a12a}
.kal-tag.kal-frei{background:var(--hover)}
/* Feiertag eigen gekennzeichnet — er ist eine Auskunft, kein bloßes „frei",
   und er gilt je nach Bundesland verschieden. */
.kal-tag.kal-feier{background:rgba(138,180,216,.22);border-color:#8ab4d8}
.kal-tag.kal-heute{box-shadow:inset 0 0 0 2px var(--brand)}
.kal-feiername{
  font-size:.72rem;line-height:1.2;color:var(--muted);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
/* Ein Name je Zeile, abgeschnitten statt umgebrochen: Sonst wachsen die
   Kacheln je nach Namenslänge unterschiedlich hoch und das Raster wackelt. */
.kal-person{
  font-size:.76rem;line-height:1.25;padding:2px 5px;border-radius:5px;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:#fff;
}
.kal-person.kal-weg{background:#c0392b}
.kal-person.kal-offen{
  background:repeating-linear-gradient(45deg,#c0392b 0 5px,#a33328 5px 10px);
}
.kal-legende{
  display:flex;gap:18px;flex-wrap:wrap;align-items:center;
  margin:0 0 14px;font-size:.85rem;color:var(--muted);
}
.kal-legende i{
  display:inline-block;width:12px;height:12px;margin-right:6px;
  vertical-align:-2px;border:1px solid var(--line);border-radius:3px;
}
.kal-legende .kal-weg{background:#c0392b}
.kal-legende .kal-offen{background:repeating-linear-gradient(45deg,#c0392b 0 3px,#a33328 3px 6px)}
.kal-legende .kal-feier{background:rgba(138,180,216,.5);border-color:#8ab4d8}
.kal-legende .kal-frei{background:var(--hover)}

/* Auf schmalen Geräten kippt die Woche in zwei Blöcke — sieben Kacheln
   nebeneinander sind unter 700 px nicht mehr lesbar. */
@media (max-width:700px){
  .kal-monat{grid-template-columns:repeat(4,minmax(0,1fr))}
  .kal-wt{display:none}
  .kal-tag{min-height:86px}
  .kal-leer{display:none}
}

/* Urlaubsanträge: Liste links, Detail rechts (13.08.2026) -----------------
   Der erste Entwurf war eine breite Tabelle — dort war ausgerechnet die
   wichtigste Angabe (wer sonst noch weg ist) die schmalste Spalte. */
.an-zwei{display:grid;grid-template-columns:minmax(260px,340px) 1fr;gap:20px;align-items:start}
.an-liste{padding:16px}
.an-eintrag{
  display:block;padding:10px 12px;border-radius:var(--radius);
  text-decoration:none;color:var(--text);border:1px solid transparent;
}
.an-eintrag:hover{background:var(--hover)}
/* Der gewählte Eintrag trägt einen Balken in der Markenfarbe UND einen Rahmen:
   Auf der Fläche allein wäre er bei eingeschalteter Glasoptik kaum zu sehen. */
.an-eintrag.aktiv{
  background:var(--hover);border-color:var(--line);
  box-shadow:inset 3px 0 0 var(--brand);
}
.an-name{display:block;font-weight:600}
.an-zeit{display:block;font-size:.84rem}
.an-art{display:block;font-size:.78rem}

.an-fakten,
.an-konto{display:grid;gap:12px 22px;grid-template-columns:repeat(auto-fit,minmax(min(130px,100%),1fr));margin:0 0 16px}
.an-fakten span,
.an-konto span{display:block;font-size:.76rem;letter-spacing:.04em;text-transform:uppercase}
.an-fakten strong,
.an-konto strong{font-size:1rem}
.an-konto strong{font-size:1.25rem}
.an-plus{color:var(--text)}
.an-minus{color:var(--danger)}
.an-notiz{margin:0 0 16px}
.an-koll{list-style:none;margin:0;padding:0;display:grid;gap:8px}
.an-koll li{line-height:1.35}

@media (max-width:900px){
  .an-zwei{grid-template-columns:1fr}
}

/* Onlinestatus in der Kopfleiste (13.08.2026) — NUR das Symbol, kein Text
   (Ansage des Users). Der Ball ist etwas größer als in Listen: Er steht allein
   zwischen zwei Strichzeichnungen und wäre mit 10 px kaum zu treffen.
   Das Wort liegt in `title` und `aria-label`. */
.kp-kopf-status{display:inline-flex;align-items:center;justify-content:center}
.kp-kopf-status .kp-ball{
  width:14px;height:14px;margin:0;
  box-shadow:0 0 0 1px rgba(0,0,0,.18) inset, 0 0 0 3px var(--hover);
}

/* Stempeluhr auf dem Dashboard, zweigeteilt (13.08.2026) ------------------
   Links „Zeit erfassen", rechts „Nächste Abwesenheit" (Ansage des Users).
   Eine Trennlinie statt zweier Karten: Es bleibt eine Auskunft über den
   eigenen Stand, nur mit zwei Fragen darin. */
.kp-stempel-zwei{
  display:grid;grid-template-columns:1fr 1fr;gap:0;
}
.kp-stempel-halb{padding:0 22px}
.kp-stempel-halb:first-child{padding-left:0}
.kp-stempel-halb:last-child{padding-right:0;border-left:1px solid var(--line)}
.kp-stempel-halb > h2{margin:0 0 10px;font-size:1rem}
.kp-stempel-gross{font-size:1.6rem;font-weight:700;line-height:1;color:var(--text)}
.kp-stempel-naechste{margin:0 0 4px}
/* ⚠️ Unter 720 px gestapelt: Zwei Spalten mit Knöpfen nebeneinander sind auf
   dem Handy unbedienbar, und die Trennlinie läge quer. */
@media (max-width:720px){
  .kp-stempel-zwei{grid-template-columns:1fr}
  .kp-stempel-halb{padding:0}
  .kp-stempel-halb:last-child{
    border-left:0;border-top:1px solid var(--line);margin-top:16px;padding-top:16px;
  }
}

/* Band bei laufender Pause (13.08.2026) — eigene Farbe, damit es nicht mit
   dem Kundenansichts-Band (Markenfarbe) und nicht mit dem Supportband
   verwechselt wird. Bernstein wie die Ampel: Es ist kein Fehler, nur ein
   Zustand, den man beenden sollte.
   ⚠️ ZWEI Klassen im Selektor, wie beim Supportband: Die Markenfarbe kommt aus
   einem <style>-Block im Kopf und stünde sonst als spätere Regel gleicher
   Stärke darüber. */
.kp-band.kp-band-pause{background:#7a5a08}
.kp-band.kp-band-pause .btn{color:#7a5a08}

/* Pflicht-Auswahlfeld ohne Wert (13.08.2026) — dieselbe Farbe wie ein leeres
   Pflicht-Eingabefeld. Die Hülle liegt AUSSERHALB von `.kp-auswahl`, weil
   `portal.js` dessen Klassenattribut beim Bauen überschreibt. Getroffen werden
   beide Fassungen: das native <select> (ohne JavaScript) und der eigene Knopf. */
.kp-pflicht-leer select,
.kp-pflicht-leer .kp-auswahl-knopf{border-color:var(--kp-warn)}
.kp-pflicht-leer select:focus,
.kp-pflicht-leer .kp-auswahl-knopf:focus-visible{border-color:var(--brand)}

.kp-feld-auge{
  position:absolute;right:10px;top:50%;transform:translateY(-50%);
  background:none;border:0;padding:4px;cursor:pointer;color:var(--muted);
  display:flex;align-items:center;line-height:1;border-radius:6px;
  transition:color .15s;
}
.kp-feld-auge:hover{color:var(--text)}
.kp-feld-auge:focus-visible{outline:2px solid var(--brand);outline-offset:1px}

/* Chromes und Edges eigene Passwort-Symbole doppeln unser Auge. */
.kp-feld-mit-auge::-ms-reveal,
.kp-feld-mit-auge::-ms-clear{display:none}

/* Tickets: Prioritaet und Verlauf.
   Die Prioritaet traegt Farbe UND Wort — Farbe allein waere fuer
   Rotgruenblinde nicht lesbar. */
.kp-prio{
  display:inline-block;padding:2px 9px;border-radius:20px;
  font-size:.75rem;font-weight:700;border:1px solid;
}
.kp-prio.niedrig {color:var(--muted); border-color:var(--line)}
.kp-prio.normal  {color:#2a78d6; border-color:#2a78d6}
.kp-prio.hoch    {color:#c07800; border-color:#e0a12a}
.kp-prio.dringend{color:#d03b3b; border-color:#d03b3b; background:rgba(208,59,59,.08)}

.kp-verlauf{list-style:none;margin:0;padding:0}
.kp-verlauf li{
  padding:12px 0 12px 14px;border-left:2px solid var(--line);
  margin-bottom:2px;
}
.kp-verlauf li.intern{border-left-color:var(--brand);background:rgba(127,127,127,.05)}
.kp-verlauf-kopf{
  display:flex;gap:10px;align-items:baseline;flex-wrap:wrap;
  font-size:.8rem;color:var(--muted);margin-bottom:5px;
}
.kp-verlauf-kopf strong{color:var(--text);font-size:.86rem}
.kp-verlauf-text{font-size:.92rem;line-height:1.55}

/* reCAPTCHA-Kaestchen: Googles iframe ist 302px breit und laesst sich nicht
   verkleinern — auf schmalen Anmeldekarten deshalb zentrieren statt strecken. */
.kp-captcha{margin:16px 0 0;display:flex;justify-content:center}
.kp-captcha > div{max-width:100%}

/* Dezenter Verweis auf die Mitarbeiteranmeldung — soll nicht mit dem
   Kundenzugang konkurrieren. */
.kp-mitarbeiter-link{color:var(--muted);text-decoration:none;font-size:.84rem}
.kp-mitarbeiter-link:hover{color:var(--brand);text-decoration:underline}

/* Briefumschlag in der Kopfzeile, mit Zaehler wie im LMS. */
.kp-kopf-msg{
  position:relative;display:inline-flex;align-items:center;justify-content:center;
  width:38px;height:38px;border-radius:10px;color:var(--text);
  border:1px solid var(--line);text-decoration:none;transition:border-color .15s,color .15s;
}
.kp-kopf-msg:hover{color:var(--brand);border-color:var(--brand);text-decoration:none}
.kp-kopf-msg:focus-visible{outline:2px solid var(--brand);outline-offset:2px}
.kp-kopf-msg-zahl{
  position:absolute;top:-6px;right:-6px;
  background:var(--brand);color:#fff;border-radius:20px;
  min-width:18px;height:18px;padding:0 5px;
  font-size:.68rem;font-weight:700;line-height:18px;text-align:center;
  border:2px solid var(--card);
}

.kp-msg-layout{display:grid;gap:20px;grid-template-columns:300px 1fr;align-items:start}
@media (max-width:900px){ .kp-msg-layout{grid-template-columns:1fr} }

.kp-msg-liste .kp-liste-name.aktiv{color:var(--brand)}
.kp-msg-zahl{
  background:var(--brand);color:#fff;border-radius:20px;
  padding:1px 8px;font-size:.72rem;font-weight:700;
}
.kp-msg-kopf{display:flex;align-items:center;gap:12px;flex-wrap:wrap;
  padding-bottom:14px;margin-bottom:14px;border-bottom:1px solid var(--line)}

.kp-msg-verlauf{
  display:flex;flex-direction:column;gap:12px;
  min-height:180px;max-height:56vh;overflow-y:auto;margin-bottom:18px;
}
.kp-msg-leer{color:var(--muted);text-align:center;padding:36px 0;font-size:.88rem}

.kp-msg-zeile{display:flex;gap:9px;align-items:flex-end;max-width:74%}
/* Der Textblock in der Zeile bleibt eine Spalte — Blase ueber Zeitangabe. */
.kp-msg-zeile > div{display:flex;flex-direction:column;min-width:0}
.kp-msg-bild{flex:0 0 auto;margin-bottom:18px}   /* auf Hoehe der Blase, nicht der Meta */
.kp-msg-zeile.meine{align-self:flex-end}
.kp-msg-zeile.meine > div{align-items:flex-end}
.kp-msg-zeile.fremde{align-self:flex-start}
.kp-msg-zeile.fremde > div{align-items:flex-start}
.kp-msg-blase{
  padding:10px 14px;border-radius:16px;font-size:.92rem;line-height:1.5;
  word-break:break-word;
}
.kp-msg-zeile.meine .kp-msg-blase{
  background:var(--brand);color:#fff;border-bottom-right-radius:4px;
}
.kp-msg-zeile.fremde .kp-msg-blase{
  background:var(--bg);border:1px solid var(--line);border-bottom-left-radius:4px;
}
.kp-msg-meta{font-size:.72rem;color:var(--muted);margin-top:4px}
.kp-msg-antwort{border-top:1px solid var(--line);padding-top:16px}
.kp-msg-antwort textarea{resize:vertical;min-height:72px}

/* Schnellerfassung: Suchzeile und Trefferliste */
.kp-schnellsuche{display:flex;gap:10px;align-items:center;flex-wrap:wrap}
.kp-schnellsuche input{flex:1 1 260px;min-width:200px}
.kp-schnellliste li{padding:12px 0}
.kp-schnellliste .kp-liste-name{font-size:1rem}
/* Der ganze Eintrag ist ein Ziel — die Zeile lädt sich sonst zum Danebentippen ein. */
.kp-schnellliste li:hover{background:var(--hover, rgba(127,127,127,.06))}
.kp-schnellliste li:hover .kp-liste-name{text-decoration:underline}

/* Jahresfilter ueber dem Gesamtumsatz */
.kp-jahrfilter{display:flex;align-items:center;gap:10px;margin:0 0 16px}
.kp-jahrfilter label{margin:0;font-size:.84rem;color:var(--muted)}
.kp-jahrfilter select{width:auto;min-width:120px}

/* Der Zeitraum ueber dem ganzen Umsatzreiter (18.08.2026). Ein eigener Kasten,
   damit er nicht wie die Ueberschrift der ersten Karte darunter aussieht — er
   steuert ja alle.
   ⚠️ `flex-wrap` ist Pflicht: Auf dem Telefon steht der erklaerende Satz sonst
   in derselben Zeile wie die Auswahl und drueckt sie aus dem Bild. */
.kp-jahrfilter-oben{
  flex-wrap:wrap;
  margin:0 0 18px;padding:12px 16px;
  background:var(--kp-flyout);border:1px solid var(--line);
  border-radius:var(--radius);
}
.kp-jahrfilter-oben small{flex:1 1 240px;font-size:.8rem;line-height:1.45}

/* Die grosse Summe. Proportionale Ziffern, nicht tabular — bei einer einzelnen
   grossen Zahl laesst tabular-nums die Ziffern auseinanderfallen. */
.kp-summe{margin:0 0 16px}
.kp-summe-wert{font-size:2rem;font-weight:800;line-height:1.1;color:var(--text)}
.kp-summe-lbl{font-size:.8rem;color:var(--muted);margin-top:5px}

/* Hilfeartikel: Klapptexte. <details> statt JavaScript — die Seite muss auch
   dann bedienbar sein, wenn sonst nichts laedt. */
.kp-hilfe-artikel{border-bottom:1px solid var(--line)}
.kp-hilfe-artikel:last-of-type{border-bottom:0}
.kp-hilfe-artikel summary{
  cursor:pointer;padding:12px 0;font-weight:600;list-style:none;
  display:flex;align-items:baseline;gap:9px;
}
.kp-hilfe-artikel summary::-webkit-details-marker{display:none}
.kp-hilfe-artikel summary::before{
  content:"+";color:var(--brand);font-weight:700;flex:0 0 auto;width:12px;
}
.kp-hilfe-artikel[open] summary::before{content:"–"}
.kp-hilfe-artikel summary:hover{color:var(--brand)}
.kp-hilfe-artikel summary:focus-visible{outline:2px solid var(--brand);outline-offset:2px}
.kp-hilfe-text{padding:0 0 14px 21px;font-size:.94rem;line-height:1.62}
.kp-hilfe-text p{margin:0 0 10px}
.kp-hilfe-text ul{margin:0 0 10px;padding-left:20px}
.kp-hilfe-text li{margin-bottom:5px}
.kp-hilfe-text > :last-child{margin-bottom:0}

/* Sortierbare Spaltenkoepfe */
.kp-sort-kopf{cursor:pointer;user-select:none;white-space:nowrap}
.kp-sort-kopf:hover{color:var(--brand)}
.kp-sort-kopf::after{content:"";opacity:.35;margin-left:6px}
.kp-sort-kopf.sort-auf::after{content:"▲";opacity:.8}
.kp-sort-kopf.sort-ab::after{content:"▼";opacity:.8}
.kp-sort-kopf:focus-visible{outline:2px solid var(--brand);outline-offset:-2px}

@media (prefers-reduced-motion:reduce){
  .kp-chart-stab{transition:none}
}

/* Handlungsbedarf auf der Uebersicht: Der Punkt traegt die Dringlichkeit, die
   Zahl steht rechts. Eigene Klasse statt .kp-ampel, weil der Punkt hier VOR
   einem Link steht und nicht Teil seines Textes ist. */
.kp-ampel-punkt{
  width:9px;height:9px;border-radius:50%;flex:0 0 auto;
  background:var(--muted);align-self:center;
}
.kp-ampel-punkt.gut{background:var(--kp-gut)}
.kp-ampel-punkt.warn{background:var(--kp-warn)}
.kp-ampel-punkt.stop{background:var(--danger)}
.kp-tuwas li{gap:10px}
.kp-tuwas .kp-liste-meta strong{
  font-size:1rem;color:var(--text);
  font-variant-numeric:tabular-nums;
}

table.tabelle{width:100%;border-collapse:collapse;font-size:.92rem}
table.tabelle th,table.tabelle td{
  padding:11px 12px;text-align:left;border-bottom:1px solid var(--line);vertical-align:top;
}
table.tabelle thead th{
  font-size:.74rem;letter-spacing:.06em;text-transform:uppercase;
  color:var(--muted);font-weight:700;border-bottom:2px solid var(--line);
}
table.tabelle tbody tr:hover{background:var(--kp-tile-bg)}

/* --------------------------------------------------------------------------
   Filter im Spaltenkopf (Punkt 15, src/Spaltenfilter.php)
   Aufklappen macht <details>, abgeschickt wird ein GET-Formular — der Filter
   funktioniert also ohne JavaScript.
   -------------------------------------------------------------------------- */
/* Band über der Tabelle: gesetzte Filter als Bubbles, dazu die beiden
   Zurücksetzen-Knöpfe (Ansage des User 08.08.2026). Ohne das Band sieht man
   einen Filter nur am gefärbten Spaltenkopf und muss jede Spalte aufklappen,
   um ihn loszuwerden. */
.kp-filterband{
  display:flex;flex-wrap:wrap;gap:8px;align-items:center;
  margin:0 0 14px;
}
.kp-bubble{
  display:inline-flex;align-items:center;gap:7px;
  padding:5px 12px;border-radius:999px;
  background:var(--brand-soft);border:1px solid var(--brand);
  color:var(--text);font-size:.84rem;line-height:1.3;
}
.kp-bubble-feld{color:var(--muted);font-weight:600}
.kp-bubble > a{
  color:var(--muted);text-decoration:none;font-size:1.05rem;line-height:1;
  padding:0 2px;border-radius:4px;
}
.kp-bubble > a:hover{color:var(--brand);background:var(--hover,rgba(0,0,0,.06))}
/* Die Zurücksetzen-Bubbles sind selbst der Verweis, nicht die Anzeige eines
   Zustands — deshalb neutral und nicht in der Markenfarbe. Sonst sähen sie aus
   wie ein weiterer gesetzter Filter. */
a.kp-bubble-weg{
  background:none;border:1px solid var(--line);color:var(--muted);
  text-decoration:none;font-weight:600;
}
a.kp-bubble-weg:hover{color:var(--text);border-color:var(--muted)}

/* Dieselbe Überlegung für die Meldung „Punkt ist erledigt" (Punkt 30,
   12.08.2026): Sie zeigt keinen gesetzten Filter an, sondern erklärt, warum
   die Liste ungefiltert dasteht. In der Markenfarbe sähe sie aus wie eine
   Einschränkung, die noch wirkt. */
.kp-bubble-neutral{background:none;border:1px solid var(--line);color:var(--muted)}
/* ⚠️ Der Verweis darin ist Text, kein ✕ — die Regel `.kp-bubble > a` macht
   daraus sonst ein großes, graues Zeichen. */
.kp-bubble-neutral > a{
  font-size:inherit;color:var(--brand);text-decoration:underline;padding:0;
}
.kp-bubble-neutral > a:hover{background:none;color:var(--brand)}

/* Sortier-Link im Spaltenkopf (src/Sortierung.php). Trägt den Spaltennamen;
   der Trichter daneben ist der Filter. */
.kp-sort{
  display:inline-flex;align-items:center;gap:5px;
  color:inherit;text-decoration:none;
}
.kp-sort:hover{color:var(--text)}
.kp-sort.an{color:var(--text)}
.kp-sort-pfeil{font-size:.9em;color:var(--brand)}
/* Sortierte und gefilterte Spalte stehen nebeneinander im selben Kopf —
   etwas Luft, sonst kleben Name und Trichter aneinander. */
th > .kp-sort + .kp-spf{margin-left:6px}
/* ⚠️ Ohne das bricht der Trichter in die zweite Zeile, sobald die Spalte
   schmal ist (bei „Portalzugang" und „Aktiv" gesehen) — er sieht dann aus wie
   ein zweites, leeres Kopffeld. */
th:has(> .kp-sort){white-space:nowrap}

.kp-spf{position:relative;display:inline-block;vertical-align:middle}
.kp-spf > details > summary{
  display:inline-flex;align-items:center;gap:6px;
  cursor:pointer;list-style:none;
  /* Der Spaltenkopf erbt seine Auszeichnung — der Filter soll wie eine
     Überschrift aussehen, nicht wie ein Knopf. */
  color:inherit;font:inherit;letter-spacing:inherit;text-transform:inherit;
}
.kp-spf > details > summary::-webkit-details-marker{display:none}
.kp-spf > details > summary:hover{color:var(--text)}
.kp-spf-trichter{
  width:11px;height:11px;flex:0 0 auto;
  fill:currentColor;opacity:.35;
}
.kp-spf > details > summary:hover .kp-spf-trichter{opacity:.7}
/* Greift der Filter, muss man das der Spalte ansehen, ohne sie aufzuklappen. */
.kp-spf.an > details > summary{color:var(--brand)}
.kp-spf.an .kp-spf-trichter{opacity:1}

.kp-spf-kasten{
  position:absolute;z-index:40;top:calc(100% + 8px);left:0;
  min-width:240px;max-width:320px;
  padding:14px;
  background:var(--kp-flyout);border:1px solid var(--line);
  border-radius:var(--radius);box-shadow:0 14px 40px rgba(0,0,0,.35);
  /* Zurück zur normalen Textauszeichnung: Der Kopf ist versal und gesperrt,
     die Bedienelemente darin sollen das nicht erben. */
  text-transform:none;letter-spacing:normal;font-size:.9rem;color:var(--text);
}
/* Die letzten Spalten öffnen nach links, sonst schiebt der Kasten die Tabelle
   in die Breite (und wird von .table-wrap abgeschnitten). */
table.tabelle th:nth-last-child(-n+3) .kp-spf-kasten{left:auto;right:0}
.kp-spf-kasten input[type="text"],
.kp-spf-kasten input:not([type]),
/* Diese vier Stellen wollen ausdruecklich die volle Breite ihres Behaelters
   und nehmen den Deckel aus `--kp-feldbreite` deshalb wieder zurueck. Sie
   sitzen alle in ohnehin schmalen Kaesten (Filter im Spaltenkopf, Ansichts-
   einstellung, Telefonansicht) — dort waere ein Rest neben dem Feld ein
   sichtbarer Fehler, kein Gewinn. */
.kp-spf-kasten select{width:100%;max-width:none}
.kp-spf-haken{display:grid;gap:6px;max-height:230px;overflow-y:auto}
.kp-spf-haken label{
  display:flex;align-items:center;gap:8px;
  font-weight:500;cursor:pointer;
}
.kp-spf-haken input{margin:0;flex:0 0 auto}
.kp-spf-fuss{display:flex;gap:8px;margin-top:12px}

/* Zeitraumfilter (09.08.2026): von und bis untereinander. Nebeneinander
   bleiben von einem Datumsfeld im 240 px schmalen Kasten nur noch die Pfeile
   der Jahreszahl übrig — der Kalenderknopf drängt es zusammen. */
.kp-spf-zeitraum{display:grid;gap:10px}
.kp-spf-zeitraum label{display:grid;gap:4px}
.kp-spf-zeitraum label > span{
  font-size:.78rem;font-weight:600;color:var(--muted);
  /* Der Kasten erbt die Auszeichnung des Spaltenkopfes — ohne das Zurücksetzen
     stünde „von" in Kapitälchen mit Sperrung wie eine zweite Überschrift. */
  letter-spacing:normal;text-transform:none;
}
/* input[type=date] fällt nicht unter die Breitenregel oben (die trifft nur
   text/typlos/select) und bliebe sonst auf seiner Eigenbreite stehen. */
.kp-spf-kasten input[type="date"]{width:100%}

/* 🔴 .table-wrap scrollt waagerecht (overflow-x:auto) und schneidet damit
   ALLES ab, was aus dem Kasten herausragt — auch nach unten. Solange kein
   Filter offen ist, bleibt das Scrollen; ist einer offen, wird der Deckel
   kurz aufgehoben. Ohne diese Regel wäre der Filterkasten bei einer kurzen
   Tabelle unten abgeschnitten. */
.table-wrap:has(.kp-spf details[open]){overflow:visible}

/* Adressblock so, wie er auf der Rechnung steht */
.kp-adresse{font-style:normal;line-height:1.55}
.kp-adresse .fehlt{color:var(--muted);font-style:italic}

.kp-marke{
  display:inline-block;font-size:.72rem;font-weight:700;
  border-radius:999px;padding:2px 9px;
  background:var(--brand-soft);color:var(--brand);
}
.kp-marke.ruhig{background:var(--line);color:var(--muted)}
/* Warnende Marke in Listen (03.09.2026) — z. B. „Rechnungsdaten geändert" in
   der Rechnungsliste. Gleiche Form wie die ruhige Marke, nur in der Warnfarbe:
   Sie soll auffallen, ohne die Zeile zu sprengen. */
.kp-marke.kp-marke-warn{background:var(--kp-warn-soft,rgba(224,161,42,.16));color:var(--kp-warn-text)}

/* Abgeschlossene Leistungen in der Kundenansicht (17.08.2026). Sie bleiben
   vollständig lesbar — es ist die eigene Vertragshistorie — treten aber
   zurück, damit das Laufende beim Überfliegen vorne steht.
   ⚠️ Nur ein leiser Ton, KEIN `opacity` auf der ganzen Karte: Das zöge auch
   den Text mit und ginge auf Kosten der Lesbarkeit. Der Stand steht ohnehin
   als Wort in der Marke, nicht nur als Farbe. */
/* „Nächste Rechnung am …" auf der Leistungskarte (03.09.2026).
   Bewusst leiser als der Preis und dicht unter „seit …" — es ist eine
   Zusatzauskunft, keine Zahlungsaufforderung. */
.kp-naechste-rechnung{margin:4px 0 0;font-size:.92rem;color:var(--muted)}
.kp-naechste-rechnung strong{color:var(--text);font-weight:600}

.karte.kp-leist-beendet{border-style:dashed}
.karte.kp-leist-beendet h3{color:var(--muted)}

/* Die Filterleiste der Kundenansicht nutzt `.kp-reiter`, hat aber keine
   Registerkarten darunter — die untere Kante würde ins Leere zeigen. */
.kp-leist-filter{border-bottom:0}

/* --------------------------------------------------------------------------
   7. Fusszeile — im Portal deutlich schlanker als auf den Demoseiten
   -------------------------------------------------------------------------- */
.kp-fuss{
  flex:0 0 auto;
  margin:0;padding:0 34px;
  min-height:var(--kp-fussleiste);
  border-top:1px solid var(--line);
  background:var(--bg);
  display:flex;gap:16px;flex-wrap:wrap;align-items:center;
  font-size:.82rem;color:var(--muted);
}
.kp-fuss a{color:var(--muted)}
.kp-fuss .rechts{margin-left:auto}

/* --------------------------------------------------------------------------
   8. Schmal — Seitenmenue wird zur Schublade
   -------------------------------------------------------------------------- */
.kp-backdrop{display:none;position:fixed;inset:0;background:rgba(0,0,0,.45);z-index:399}
.kp-backdrop.offen{display:block}
.kp-side-zu{display:none}

@media (max-width:980px){
  .kp-side-btn{display:inline-flex}

  /* Schmale Geräte scrollen wieder ganz normal: Die Seitenspalte ist hier
     eine Schublade, und eine fensterhohe Seite mit eigenem Scrollbereich
     macht auf dem Handy mehr kaputt als sie hilft. */
  /* 🔴 `overflow-y:visible` und NICHT `overflow:visible` (15.08.2026, Fund des
     Users: „scrolle ich da nach rechts verschwindet auch der hintergrund").
     Die Kurzform setzte beide Achsen — und damit das `overflow-x:clip` aus
     `base.css` außer Kraft. Ein zu breiter Inhalt ließ dann die GANZE Seite
     zur Seite scrollen; Kopfzeile, Fußzeile und Hintergrund enden aber bei der
     Fensterbreite, weshalb rechts das Nichts erschien.
     ⚠️ `clip` und nicht `hidden`: `hidden` erzeugt einen Scrollcontainer und
     bricht `position:sticky` der Kopfzeile — steht so schon in `base.css`. */
  body.kp{height:auto;display:block;overflow-y:visible;overflow-x:clip}
  .kp-shell{display:flex}
  .kp-main{overflow:visible;display:block}
  .kp-main-scroll{overflow:visible;padding:20px 18px 28px}
  .kp-fuss{padding:12px 18px;min-height:0}
  .kp-neu{min-height:0;padding:12px 18px 16px;display:block}
  /* Hier läuft die Fußzeile im normalen Fluss mit — kein Platz freihalten. */
  body.kp .to-top{bottom:20px}

  /* Schmale Geraete: Untermenues klappen untereinander auf statt zur Seite —
     rechts waere kein Platz, das Menue ist dort eine Schublade. */
  .kp-neu-unter{
    position:static;min-width:0;margin:0 0 6px;
    box-shadow:none;border-radius:0;border-left:0;border-right:0;
  }

  .kp-side{
    position:fixed;top:0;left:0;z-index:400;
    height:100dvh;width:290px;max-width:88vw;
    transform:translateX(-100%);
    transition:transform .26s cubic-bezier(.4,0,.2,1);
    box-shadow:4px 0 28px rgba(0,0,0,.22);
    border-right:0;overscroll-behavior:contain;
  }
  .kp-side.offen{transform:translateX(0)}

  .kp-side-zu{
    display:flex;align-items:center;justify-content:center;
    position:absolute;top:10px;right:10px;
    width:32px;height:32px;border-radius:50%;
    background:rgba(0,0,0,.08);border:0;cursor:pointer;
    color:var(--text);font-size:1rem;z-index:1;
  }
  html[data-theme="dark"] .kp-side-zu{background:rgba(255,255,255,.1)}

  .kp-main{padding:20px 18px 44px}
  .kp-zweispalt{grid-template-columns:1fr}
}

@media (prefers-reduced-motion:reduce){
  .kp-side{transition:none}
  a.kp-kachel:hover{transform:none}
}

/* Trenner im Seitenmenü — setzt die „+ Neu"-Einträge von den Listen ab. */
.kp-nav-trenner{
  border:0;border-top:1px solid var(--line);
  margin:10px 18px 8px;
}


/* --------------------------------------------------------------------------
   Reiter auf Detailseiten
   Die Leiste klebt oben im Scrollbereich, damit man beim Blättern nicht
   erst zurückscrollen muss. Ohne JavaScript sind alle Bereiche sichtbar —
   das ist zwar lang, aber nie kaputt.
   -------------------------------------------------------------------------- */
/* 🔴 KEIN `position:sticky` (vom User verworfen, 10.08.2026: „im tab möchte
   ich da aber kein sticky das sieht scheisse aus").
   Woran es lag: Der Scrollbereich `.kp-main-scroll` hat `padding-top:28px`.
   Die Leiste blieb deshalb 28 px unterhalb seiner Oberkante stehen, und in
   diesem Streifen lief der Inhalt sichtbar an ihr vorbei — es sah aus, als
   schwebe die Leiste willkürlich im Text. Nicht wieder einbauen, ohne diesen
   Streifen zu lösen. */
/* 🔴 Die Leiste bleibt oben kleben (31.08.2026). Auf einer langen Seite —
   Stammdaten sind 854 px hoch, die Adresse mit der Umkreiskarte 842 — war sie
   nach dem Scrollen ausser Sicht: Wer die Karte ansah und den Reiter wechseln
   wollte, musste erst zurückscrollen.

   ⚠️ `background` ist Pflicht, sonst scheint der Inhalt beim Scrollen
   durch die Leiste hindurch. `z-index` hält sie über den Karten, aber unter
   den Klappmenüs (die liegen bei 6000). */
/* 🔴 36 px statt 22 px Abstand nach unten (02.09.2026, Meldung des Users:
   „auf dem admin dashboard rutschen die ersten kacheln unter die tabs, wenn
   ich die maus darauf fahre").

   Zwei Dinge greifen bei 22 px ineinander: Der Schattenkranz der klebenden
   Leiste (`::before`, `0 8px 16px`) reicht 24 px nach unten und lag damit
   schon im Ruhezustand auf der Oberkante der ersten Kachelreihe. Der
   Hover einer Kachel hebt sie zusätzlich um 2 px an — sie fährt also in den
   Schatten hinein statt von ihm weg.

   ⚠️ Der Abstand hängt an der LEISTE und nicht an `.kp-kacheln`: Welcher
   Baustein im Überblick zuerst steht, stellt jeder Zugang selbst ein
   (`Dashboard::SORTIERBAR`) — ein `:first-child`-Griff auf die Kacheln träfe
   je nach Sortierung ins Leere. Und unter den Detailseiten stehen dort Karten
   statt Kacheln, die genauso angeschnitten wurden.
   📌 Der Zwilling für die enge Leiste steht bei `.kp-leiste-schiebe.kp-eng` —
   beide Werte gehören zusammen. */
.kp-reiter{
  display:flex;gap:2px;flex-wrap:wrap;
  margin:0 0 36px;padding-top:2px;
  background:var(--bg);
  border-bottom:1px solid var(--line);
}

/* Zoom der Umkreiskarte (03.09.2026): rechts in der Reiterleiste, damit die
   Bedienung an EINER Stelle sitzt und nicht über der Karte schwebt.
   ⚠️ `margin-left:auto` schiebt die Gruppe ans Ende — ohne sie klebt sie am
   letzten Reiter und sieht aus wie ein dritter.
   📌 Am Rand der Spanne bleibt das Zeichen als stiller Text stehen (kein `a`);
   es wird nur blasser, damit die Leiste nicht springt. */
/* 🔴 Die Reiterleiste der Umkreiskarte ist genau so breit wie die Karte
   darunter (03.09.2026, Meldung des Users: „die tabs ragen über den
   container"). Die Karte hat feste 460 px — ihre Kacheln sind `<img>` mit
   festen Pixelmassen und skalieren nicht —, die Leiste nahm dagegen die volle
   Spaltenbreite. Damit standen Leiste und Karte nie auf derselben Kante.
   ⚠️ Ist die Spalte schmaler als 460 px, ragen jetzt BEIDE gleich weit hinaus.
   Das ist gewollt: „die karte ist dort auch recht weit draussen, das ist ok."
   📌 `max-width:100%` bleibt weg — sonst schrumpfte die Leiste und die Karte
   nicht, und die Kanten liefen wieder auseinander. */
/* 462 = 460 px Karte + der 1-px-Rahmen auf beiden Seiten; das Portal rechnet
   mit `box-sizing:border-box`. Beide Zahlen gehoeren zusammen — wer die
   Kartenbreite in `Touren::osmKarte()` aendert, aendert diese mit. */
.kp-reiter-karte{width:462px}

/* 🔴 Die Trefferliste im Umkreisblock bleibt schmal (03.09.2026, Ansage des
   Users: „mach halt einfach die bubble mit den kunden links kleiner").
   Sie führt nur zwei Spalten — Entfernung und Name —, lief aber über die
   ganzen 1,6 Rasteranteile und reichte damit bis fast an die Karte heran.
   ⚠️ Am `.table-wrap` und nicht an der Spalte: Die Spalte trägt weiterhin das
   Raster, nur der Kasten darin hört früher auf. So bleibt der Abstand zur
   Karte sichtbar, statt dass beide aneinanderstossen. */
.kp-umkreis-block .kp-zweispalt > div > .table-wrap{max-width:620px}

/* 🔴 Reiter und Karte in EINEM Kasten (03.09.2026, Meldung des Users: „die
   tabs liegen über dem container"). Die Reiterleiste stand frei über dem
   Kartenrahmen und sah dadurch aus, als schwebe sie darüber. Die Trefferliste
   daneben macht es vor: Kopfzeile IM Kasten.
   ⚠️ Der Rahmen sitzt jetzt an der Box; der Rahmen der Karte selbst wird
   abgeschaltet, sonst stünden zwei ineinander. `overflow:hidden` haelt die
   Ecken rund. */
.kp-kartenbox{
  width:462px;max-width:100%;
  border:1px solid rgba(128,128,128,.35);
  border-radius:8px;overflow:hidden;
}
.kp-kartenbox > .kp-reiter-karte{
  width:auto;margin:0;padding:2px 6px 0;
  background:transparent;border-bottom:1px solid var(--line);
}
/* Die Karte bringt ihren eigenen Rahmen mit — in der Box waere er der zweite. */
.kp-kartenbox > div[style*="border"]{border:0 !important;border-radius:0 !important;width:100% !important}

.kp-reiter-zoom{display:flex;gap:2px;margin-left:auto;align-items:center}
.kp-reiter-zoom > a,
.kp-reiter-zoom > span{
  padding:8px 12px;line-height:1;
  font-size:1rem;color:var(--muted);text-decoration:none;
}
.kp-reiter-zoom > a:hover{color:var(--text);background:var(--hover)}
.kp-reiter-zoom > span{opacity:.35}

/* ---- Reiterleiste bleibt oben stehen (31.08.2026) ------------------------
   Ansage des Users: „die fixierten tabs dann ÜBERALL, nicht nur im account".
   Deshalb hängt es an `.kp-reiter` selbst und gilt damit für jede Leiste im
   Portal.

   🔴 Die Schiebehülle muss MIT kleben. Ein klebendes Element klebt nur
   innerhalb seines Elternkastens — und `.kp-leiste-schiebe` ist 70 px hoch.
   Ohne diese Zeile blieb die Leiste stehen und scrollte nach 70 px mit weg;
   gemessen stand sie bei Scrollstand 369 um 175 px ÜBER dem sichtbaren
   Bereich. Die Hülle setzt JavaScript, sie ist nicht immer da — deshalb kleben
   beide.

   🔴 `top:-28px` und der Kranz aus negativem Rand plus Polsterung sind KEINE
   Kosmetik (Fund des Users: „die leiste klebt nun als streifen drüber, im
   hintergrund sieht man den rest der überscrollten seite"). `.kp-main-scroll`
   polstert 28 px oben und 34 px seitlich. Ein Element mit `top:0` klebt am
   POLSTERKASTEN — die 28 px darüber und die 34 px daneben bleiben frei, und
   genau dort lief der Inhalt sichtbar vorbei. Der negative Rand zieht den
   Kasten in die Polsterung hinein, die Polsterung stellt den Abstand innen
   wieder her.

   ⚠️ Erst ab 980 px. Darunter scrollt `.kp-main-scroll` gar nicht (dort steht
   `overflow:visible`, gescrollt wird das Fenster) — und eine Leiste, die auf
   dem Telefon ein Sechstel der Höhe wegnimmt, ist keine Hilfe. */
@media (min-width:981px){
  /* 🔴 Die obere Polsterung wandert von der Scrollfläche nach INNEN
     (31.08.2026, zweiter Fund des Users: „scrollt man einmal runter und wieder
     hoch sind die vorheriger und nächste buttons halb weg").

     Vorher polsterte `.kp-main-scroll` oben 28 px. Ein klebendes Element mit
     `top:0` klebt am Polsterkasten — also 28 px unterhalb der Oberkante —, und
     durch diesen Streifen lief der Inhalt sichtbar vorbei. Ihn mit einem
     hochgezogenen Hintergrund zu überdecken war der Fehler: Der deckte im
     ungescrollten Zustand die Blätterleiste zur Hälfte zu.

     Liegt die Polsterung stattdessen an `.kp-inner`, sitzt die Oberkante der
     Scrollfläche direkt an der Kopfzeile. `top:0` klebt dann genau dort, es
     gibt keinen Streifen mehr zu überdecken, und im Fluss verschiebt sich
     nichts. */
  .kp-main-scroll{padding-top:0}
  .kp-main-scroll > .kp-inner{padding-top:28px}

  .kp-main-scroll .kp-leiste-schiebe,
  .kp-main-scroll .kp-reiter{
    position:sticky;top:0;z-index:15;
    background:var(--bg);
  }
  /* 🔴 Der Kranz kommt aus einem PSEUDOELEMENT und nicht aus negativen
     Rändern (31.08.2026, zweiter Anlauf). Beim ersten Versuch stand
     `margin:-28px -34px` — das verschiebt den Kasten auch im normalen Fluss
     nach oben, und dort deckte er die Blätterleiste darüber zur Hälfte zu
     (Fund des Users: „scrollt man einmal runter und wieder hoch sind die
     vorheriger und nächste buttons halb weg").

     Das Pseudoelement liegt AUSSERHALB des Flusses: Es füllt die Polsterung
     von `.kp-main-scroll` (28 px oben, 34 px seitlich) mit dem Seitengrund,
     ohne irgendetwas zu verschieben. */
  .kp-main-scroll .kp-leiste-schiebe::before,
  .kp-main-scroll .kp-reiter::before{
    content:"";position:absolute;
    top:0;bottom:0;left:-34px;right:-34px;
    background:var(--bg);
    box-shadow:0 8px 16px rgba(0,0,0,.30);
    z-index:-1;
  }
  /* In der Hülle klebt nur die Hülle — sonst zwei Kränze übereinander. */
  .kp-main-scroll .kp-leiste-schiebe > .kp-reiter{
    position:static;top:auto;box-shadow:none;
  }
  .kp-main-scroll .kp-leiste-schiebe > .kp-reiter::before{content:none}
}
/* Reiter sind meist Knöpfe (JS schaltet um). Die Stammdaten nutzen LINKS —
   jede Liste hat eigene Blätterung und wird einzeln geladen. Gleiche Optik,
   deshalb dieselben Regeln; `text-decoration` muss beim Link weg. */
.kp-reiter button,
.kp-reiter a{
  display:inline-flex;align-items:center;gap:8px;
  border:0;border-bottom:3px solid transparent;background:none;
  padding:10px 16px;margin-bottom:-1px;
  font:inherit;font-size:.92rem;font-weight:600;color:var(--muted);
  cursor:pointer;text-decoration:none;
}
.kp-reiter button:hover,
.kp-reiter a:hover{color:var(--text)}
.kp-reiter button.aktiv,
.kp-reiter a.aktiv{color:var(--brand);border-bottom-color:var(--brand)}
.kp-reiter-zahl{
  font-size:.72rem;font-weight:700;border-radius:999px;padding:1px 8px;
  background:var(--line);color:var(--muted);
}
/* Trenner in der Reiterleiste: Was dahinter steht, wechselt die SEITE und
   nicht nur den Reiter (Einstellungen → Stammdaten/Hilfe/Zugänge). Ohne diese
   Kante sähe ein Seitenwechsel wie ein Reiterwechsel aus — und ungespeicherte
   Eingaben im Formular gingen unbemerkt verloren. */
.kp-reiter-trenner{
  align-self:center;width:1px;height:20px;margin:0 10px;
  background:var(--line);flex:0 0 auto;
}
.kp-reiter button.aktiv .kp-reiter-zahl,
.kp-reiter a.aktiv .kp-reiter-zahl{background:var(--brand-soft);color:var(--brand)}

/* 🔴 Punkt am Reiter mit UNGESPEICHERTEN Eingaben (17.08.2026, Meldung des
   Users: Leistung eingetippt, Reiter gewechselt, dort gespeichert — Leistung
   weg). Jeder Reiter trägt sein eigenes Formular; abgeschickt wird immer nur
   eines. Der Punkt macht sichtbar, wo noch etwas offen ist, `portal.js` fragt
   zusätzlich vor dem Absenden nach.
   ⚠️ Als `::after` und nicht als zusätzliches Element: Die Knöpfe entstehen im
   Markup an acht Stellen, ein Element müsste überall mitgepflegt werden.
   ⚠️ Die Farbe kommt aus `--kp-warn` und nicht aus der Markenfarbe — es ist
   ein Hinweis, keine Auszeichnung. */
.kp-reiter button.kp-offen::after,
.kp-reiter a.kp-offen::after{
  content:"";display:inline-block;width:7px;height:7px;margin-left:7px;
  border-radius:999px;background:var(--kp-warn,#c47f17);vertical-align:middle;
}

/* Stammdatenlisten als RASTER (14.08.2026, Ansage des Users: „die darstellung
   noch etwas schöner"). Sechzehn Knöpfe in einer flexiblen Reihe brechen
   ausgefranst um — jede Zeile endet woanders, und das Auge findet den
   gesuchten Eintrag nicht.

   `auto-fill` mit fester Mindestbreite füllt die Zeile stattdessen mit gleich
   breiten Feldern; bei schmalem Fenster werden es von selbst weniger Spalten.
   Der Name steht links, die Anzahl rechts — dadurch stehen alle Zahlen
   untereinander und lassen sich vergleichen. */
.kp-stammliste{
  display:grid;
  grid-template-columns:repeat(auto-fill, minmax(215px, 1fr));
  gap:8px;margin:0 0 22px;
}
.kp-stammliste .btn{
  display:flex;align-items:center;justify-content:space-between;gap:10px;
  width:100%;text-align:left;
  /* 🔴 `.btn + .btn{margin-left:8px}` gilt global für jeden Knopf AUSSER dem
     ersten — gedacht für Knöpfe nebeneinander in einer Reihe. Im Raster ist
     das falsch: Der Abstand kommt hier von `gap`, und der zusätzliche Rand
     schob alle Felder außer dem ersten um 8 px nach rechts. Genau so vom User
     gesehen (14.08.2026): „abteilungen ist weiter links als alle anderen und
     hat rechts etwas mehr abstand". */
  margin-left:0;
  /* Lange Namen („Beschäftigungsarten") dürfen den Knopf nicht sprengen. */
  overflow:hidden;
}
.kp-stammliste .btn > span:first-child{
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
/* Die Zahl im ausgewählten Knopf steht auf gefülltem Grund — dort trägt der
   graue Kasten nicht, er verschwindet fast. Deshalb durchscheinendes Weiß. */
.kp-stammliste .btn:not(.btn-outline) .kp-reiter-zahl{
  background:rgba(255,255,255,.22);color:#fff;
}

/* Erst wenn JavaScript da ist, wird ausgeblendet. */
/* ⚠️ `html.js`, nicht `body.js` (12.08.2026, Punkt 4b). Die Klasse setzt
   portal.js im KOPF der Seite, bevor der Browser zeichnet — am <body> ginge
   das nicht, den gibt es zu dem Zeitpunkt noch nicht. Vorher fiel sie erst
   bei `DOMContentLoaded`, und bis dahin standen alle Reiter untereinander.
   🔴 Ohne Klasse bleiben sie sichtbar: Eine Detailseite ohne JavaScript wäre
   sonst unbedienbar — man käme an zehn von elf Reitern nicht heran. */
html.js .kp-reiter-inhalt{display:none}
html.js .kp-reiter-inhalt.aktiv{display:block}

/* --------------------------------------------------------------------------
   Kopfzeile über Tabellen: Zahl der Zeilen und Blätterung
   -------------------------------------------------------------------------- */
.kp-listenkopf{
  display:flex;align-items:center;gap:16px;flex-wrap:wrap;
  margin-bottom:12px;font-size:.86rem;
}
.kp-pro{display:flex;align-items:center;gap:8px;margin:0;font-weight:600;font-size:.86rem}
.kp-pro select{width:auto;padding:6px 10px;font-size:.86rem}
.kp-blaettern{display:flex;align-items:center;gap:10px;margin-left:auto}
.kp-blaettern .aus{opacity:.4;pointer-events:none}

/* Dieselbe Leiste noch einmal UNTER der Liste (18.08.2026, Ansage des Users).
   Wer zwanzig Zeilen durchgesehen hat, steht am Ende der Tabelle — zum
   Weiterblaettern erst wieder hochzuscrollen ist bei jeder Seite derselbe
   unnoetige Weg.
   ⚠️ Abgesetzt durch eine Linie OBEN statt durch Abstand allein: Ohne sie haengt
   sie an der letzten Tabellenzeile und liest sich wie deren Fortsetzung. */
/* ⚠️ Der obere Rand war bis zum 21.08.2026 NEGATIV (-14px) und zog die
   Leiste an die Tabelle heran — Ansage des Users: „die vor / zurück buttons
   unter den listen bitte etwas mehr abstand zur liste selbst, sie kleben
   direkt an der liste". Der Wert stammte aus einer Zeit, in der die Hülle
   `.table-wrap` einen eigenen Abstand nach unten mitbrachte; den hat sie nicht
   mehr, und so klebte die Leiste an der letzten Zeile.
   Die Trennlinie bleibt: Sie sagt, dass hier die Liste endet und die Bedienung
   anfängt — nur eben mit Luft davor. */
.kp-listenfuss{
  display:flex;align-items:center;gap:16px;flex-wrap:wrap;
  margin:14px 0 26px;padding-top:14px;
  border-top:1px solid var(--line);
  font-size:.86rem;
}

/* --------------------------------------------------------------------------
   Dateiauswahl
   Der Browser zeichnet sonst eine graue Systemschaltfläche mitten in ein
   sonst durchgestaltetes Formular — und schneidet den Dateinamen ab.
   -------------------------------------------------------------------------- */
input[type=file]{
  padding:8px 10px;font-size:.86rem;cursor:pointer;line-height:1.6;
}
input[type=file]::file-selector-button{
  margin-right:12px;padding:6px 13px;
  border:1px solid var(--line);border-radius:8px;
  background:var(--kp-tile-bg);color:var(--text);
  font:inherit;font-size:.83rem;font-weight:600;cursor:pointer;
  transition:border-color .15s,color .15s;
}
input[type=file]::file-selector-button:hover{border-color:var(--brand);color:var(--brand)}

/* --------------------------------------------------------------------------
   Dateiauswahl in einer Tabellenzelle (Beleg-Spalte der Zahlliste)
   🔴 Fund des Users am 21.08.2026: „der durchsuchen button bei den belegen
   rutscht aus seiner bubble". Das Feld stand auf `max-width:150px` und war
   damit SCHMALER als sein eigener Knopf — und weil ein Dateifeld seinen Inhalt
   abschneidet, wurde der Knopf rechts gekappt.

   Die Lösung ist nicht ein breiteres Feld, sondern gar kein Feld: Neben einem
   „Hochladen" in derselben Zelle ist für Kasten, Knopf UND Dateinamen kein
   Platz. Ohne Rahmen und Grund ist der KNOPF das äußerste Element — es gibt
   dann nichts mehr, woraus er rutschen könnte.

   ⚠️ Der Dateiname bleibt sichtbar (das Feld zeigt ihn nach der Auswahl an) und
   wird nur mit Auslassungspunkten gekürzt. Ihn wegzublenden wäre bequemer und
   falsch: Wer eine Datei wählt, will lesen können, welche.
   -------------------------------------------------------------------------- */
/* ⚠️ `input[type=file]` davor ist SPEZIFISCHER als eine Klasse (Element +
   Attribut schlaegt Klasse). Ohne den Typ im Selektor blieben Polsterung und
   Hoehe von dort stehen, und die Zeile waere weiter zu hoch — an genau dieser
   Stelle einmal hereingefallen und im Browser nachgemessen. */
input[type=file].kp-beleg-wahl{
  border:0;background:transparent;padding:0;
  width:auto;max-width:none;
  /* Volle Zeilenbreite, damit der Dateiname lesbar bleibt: Der „Hochladen"
     rutscht dadurch in die zweite Zeile. Nebeneinander blieben nach dem Knopf
     rund 70 px fuer den Namen — daraus wird „K…", und das ist keine Auskunft,
     sondern Schutt. */
  flex:1 1 100%;
}
input[type=file].kp-beleg-wahl::file-selector-button{margin-right:8px}
.kp-beleg-form{flex-wrap:wrap}

/* Datumsfelder in einer Suchleiste (21.08.2026).
   ⚠️ `base.css` setzt `input{width:100%}`. In einem Flex-Kasten wird daraus
   eine Wunschbreite, die sich das Feld auch nimmt: Die beiden Datumsfelder der
   Eingangsrechnungen standen bei je 380 px und drueckten das Suchfeld auf 275.
   Ein Datum braucht rund 150 — gemessen im Browser, nicht geschaetzt. */
/* ⚠️ Auch Zahlenfelder: Das km-Feld im Umkreisblock zog sich sonst ueber die
   halbe Leiste, obwohl `size="4"` daran steht — `size` gilt nur, solange
   keine Breite gesetzt ist, und `base.css` setzt eine. Gefunden am
   Erinnerungs-Umkreis (21.08.2026). */
.kp-suchleiste input[type=date],
.kp-suchleiste input[type=number]{width:auto;min-width:0;flex:0 0 auto}

/* --------------------------------------------------------------------------
   Laufbalken des Geo-Sammellaufs (21.08.2026)
   Der Lauf zerfaellt in Haeppchen; dieser Balken zeigt, wie weit er ist.

   ⚠️ Die Schiene hat eine feste Hoehe und der Fuellstand waechst per `width`.
   Eine Skalierung ueber `transform` waere fluessiger, verzerrt aber die
   abgerundeten Enden — bei 3 % saehe die Fuellung aus wie ein Strich mit
   Delle.
   -------------------------------------------------------------------------- */
.kp-geo-stand{margin-top:12px}
.kp-geo-schiene{
  height:8px;border-radius:999px;overflow:hidden;
  background:var(--kp-tile-bg);border:1px solid var(--line);
}
.kp-geo-fuellung{
  height:100%;width:0;border-radius:999px;
  background:var(--brand);
  transition:width 320ms ease;
}
/* Abgebrochen: Der Balken bleibt stehen, wo er war, und wechselt die Farbe.
   Ihn zurueckzusetzen wuerde verschweigen, dass die halbe Arbeit getan ist —
   und sie IST getan, jede Anschrift ist einzeln gespeichert. */
.kp-geo-fuellung.fehler{background:var(--danger)}
.kp-geo-text{margin:8px 0 0;font-size:.82rem;color:var(--muted)}

/* Solange der Lauf laeuft, ist der Knopf gesperrt — ein zweiter Lauf wuerde
   dieselben Anschriften parallel anfragen. */
.kp-geo button[disabled]{opacity:.55;cursor:default}



/* Anklickbare Diagrammzeile (21.08.2026). Der Zeiger ist der einzige Hinweis,
   dass hinter der Zeile etwas liegt — ohne ihn probiert es niemand aus.
   Der Fokusrahmen gehoert an den Anker und nicht an die durchsichtige
   Trefferflaeche: Auf transparentem Grund saehe man ihn nicht. */
.kp-chart-verweis{cursor:pointer}
.kp-chart-verweis:focus-visible{outline:2px solid var(--brand);outline-offset:2px}
.kp-chart-verweis:hover .kp-chart-stab{filter:brightness(1.15)}



/* --------------------------------------------------------------------------
   Logo-Upload: Vorschau statt Pfad
   Zwei gleich hohe Karten nebeneinander. Das helle Logo wird auf hellem, das
   dunkle auf dunklem Grund gezeigt — sonst sieht man bei einem von beiden
   schlicht nichts.
   -------------------------------------------------------------------------- */
.kp-logos{
  display:grid;gap:18px;
  grid-template-columns:repeat(auto-fit,minmax(min(280px,100%),380px));
  justify-content:start;
}
.kp-logo{
  border:1px solid var(--line);border-radius:var(--radius);
  padding:16px;background:var(--kp-tile-bg);
}
.kp-logo-kopf{display:flex;align-items:baseline;gap:8px;margin-bottom:12px}
.kp-logo-kopf strong{font-size:.95rem}
.kp-logo-kopf .muted{font-size:.82rem}
.kp-logo-vorschau{
  height:104px;margin-bottom:12px;
  display:flex;align-items:center;justify-content:center;
  border:1px solid var(--line);border-radius:var(--radius-sm);padding:12px;
}
.kp-logo-vorschau.hell{background:#fff}
.kp-logo-vorschau.dunkel{background:#1b1e24}
.kp-logo-vorschau img{max-width:100%;max-height:78px;height:auto;display:block}

/* Kleine Marke, die sagt, woran man gerade ist: Vorgabe oder eigenes Bild. */
.kp-logo-marke{
  display:inline-block;margin:0 0 8px;
  font-size:.7rem;font-weight:700;letter-spacing:.06em;text-transform:uppercase;
  background:var(--line);color:var(--muted);border-radius:999px;padding:3px 10px;
}
.kp-logo input[type=file]{width:100%}
.kp-logo small{display:block;margin-top:6px}
.kp-check-schmal{margin-top:12px;padding:9px 12px;font-size:.86rem}

/* --------------------------------------------------------------------------
   Farbwähler
   input[type=color] erbt sonst width:100% aus base.css und wird zu einem
   dünnen Balken quer über die Spalte — im Bild kaum als Bedienelement
   erkennbar. Hier: quadratische Fläche, Beschriftung daneben.
   -------------------------------------------------------------------------- */
.kp-farben{display:flex;gap:26px;flex-wrap:wrap}
.kp-farbe{display:flex;align-items:center;gap:12px}
.kp-farbe label{margin:0;font-size:.92rem}
.kp-farbe small{display:block;font-weight:400;margin-top:2px}
.kp-farbe input[type=color]{
  width:56px;height:46px;flex:0 0 auto;padding:4px;cursor:pointer;
  border:1px solid var(--line);border-radius:var(--radius-sm);
  background:var(--input-bg);
}
.kp-farbe input[type=color]::-webkit-color-swatch-wrapper{padding:0}
.kp-farbe input[type=color]::-webkit-color-swatch{border:0;border-radius:6px}
.kp-farbe input[type=color]::-moz-color-swatch{border:0;border-radius:6px}

/* --------------------------------------------------------------------------
   Dokumente (Modul Dateiverwaltung)
   -------------------------------------------------------------------------- */
.kp-datei-name{display:flex;align-items:center;gap:8px}
.kp-datei-art{
  font-size:.68rem;font-weight:700;text-transform:uppercase;letter-spacing:.04em;
  background:var(--line);color:var(--muted);border-radius:4px;padding:2px 6px;
}

/* Reiter, auf denen es nichts zu speichern gibt (etwa die Modulübersicht),
   blenden die Knopfreihe des Formulars aus. Ohne JavaScript sind ohnehin
   alle Karten sichtbar, dann bleibt die Reihe stehen — richtig so. */
.kp-reiter-inhalt[data-ohne-aktionen].aktiv ~ .kp-form-aktionen{display:none}
/* Dasselbe fuer Reiter, die VOR dem Formular stehen muessen, weil sie eigene
   Formulare enthalten (Ticketverteiler) — ein <form> im <form> ist ungueltig. */
.kp-reiter-inhalt[data-ohne-aktionen].aktiv ~ form .kp-form-aktionen{display:none}

/* Freigabecode fürs Vorlesen am Telefon: groß, monospace, gesperrt. */
.kp-code{
  font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
  font-size:1.8rem;font-weight:700;letter-spacing:.12em;
  margin:6px 0 12px;color:var(--brand);
}


/* --------------------------------------------------------------------------
   Suche ueber alles (Kopfzeile der Verwaltung + Trefferseite)
   Vorbild ist das LMS: Feld im Kopf, Vorschlaege darunter, vollstaendige
   Treffer auf einer eigenen Seite.
   -------------------------------------------------------------------------- */
/* Das Feld waechst beim Anklicken (Vorbild LMS, dort 160 → 220 px).
   Im Ruhezustand soll es nicht die halbe Kopfzeile belegen; wer tippt,
   braucht dagegen Platz — Firmennamen sind laenger als ein Suchwort.

   🔴 Aufgeklappt bleibt es breit, auch wenn der Fokus schon weg ist
   (Klasse `offen` aus portal.js). Sonst schrumpft der Kasten in dem Moment,
   in dem die Maus auf einen Vorschlag zusteuert — und man klickt daneben. */
.kp-such-kopf{
  position:relative;margin-left:auto;flex:0 1 280px;min-width:0;
  transition:flex-basis .2s ease;
}
.kp-such-kopf:focus-within,
.kp-such-kopf.offen{flex-basis:460px}
.kp-such-kopf form{margin:0}

@media (prefers-reduced-motion:reduce){
  .kp-such-kopf{transition:none}
}

.kp-such-feld{
  width:100%;height:38px;padding:5px 40px 5px 16px;
  border-radius:999px;background:var(--card);
  font-size:.9rem;
}
.kp-such-feld::-webkit-search-cancel-button{-webkit-appearance:none}

/* Lupe rechts im Feld — wie im LMS. Sie sitzt IM Feld und nicht daneben,
   damit die Kopfzeile eine Zeile bleibt. */
.kp-such-knopf{
  position:absolute;right:6px;top:50%;transform:translateY(-50%);
  background:none;border:0;padding:6px;cursor:pointer;color:var(--muted);
  display:flex;align-items:center;line-height:1;border-radius:999px;
  transition:color .15s ease, background .15s ease;
}
.kp-such-knopf:hover{color:var(--brand);background:var(--brand-soft)}
.kp-such-knopf:focus-visible{outline:2px solid var(--brand);outline-offset:1px}

/* Vorschlagsliste. Sie liegt ueber allem anderen im Kopf — sonst schoebe
   sich die Kopfzeile beim Tippen auseinander. */
.kp-such-klapp{
  position:absolute;left:0;right:0;top:calc(100% + 8px);z-index:70;
  max-height:min(70vh,560px);overflow-y:auto;
  /* deckend — siehe .kp-benutzer-klapp */
  background:var(--kp-flyout);border:1px solid var(--line);border-radius:12px;
  box-shadow:0 16px 44px rgba(0,0,0,.24);
  padding:6px;
}
.kp-such-klapp[hidden]{display:none}

.kp-such-gruppenkopf{
  display:flex;align-items:center;gap:7px;
  margin:8px 8px 4px;
  font-size:.72rem;font-weight:700;letter-spacing:.06em;text-transform:uppercase;
  color:var(--muted);
}
.kp-such-gruppenkopf:first-child{margin-top:4px}

.kp-such-treffer{
  display:block;padding:8px 10px;border-radius:9px;
  color:var(--text);text-decoration:none;
}
.kp-such-treffer:hover,
.kp-such-treffer.aus{background:var(--brand-soft);text-decoration:none}
.kp-such-treffer.aus{outline:2px solid var(--brand);outline-offset:-2px}

.kp-such-treffer b{display:block;font-size:.9rem;font-weight:600}
.kp-such-treffer small{
  display:block;font-size:.78rem;color:var(--muted);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.kp-such-treffer mark{background:var(--brand-soft);color:inherit;font-weight:700}

.kp-such-leer{padding:14px 10px;color:var(--muted);font-size:.88rem}
.kp-such-alle{
  display:block;margin-top:6px;padding:9px 10px;
  border-top:1px solid var(--line);
  font-size:.84rem;font-weight:600;color:var(--brand);text-align:center;
}
.kp-such-alle:hover{background:var(--brand-soft);text-decoration:none}

/* 🔴 Die Suche stand auf schmalen Geraeten bis zum 15.08.2026 auf
   `display:none` — begruendet mit fehlendem Platz neben Marke und Konto.
   Der User hat das beanstandet: „mir faellt grad auf, dass wir mobile unsere
   suche komplett unterschlagen." Zu Recht: Die Suche ist der schnellste Weg
   durch das Portal, und gerade auf dem Handy will man nicht erst ein Menue
   aufklappen.
   Sie sitzt jetzt zwischen Menueknopf und Marke und teilt sich die Zeile mit
   beiden — die Anordnung dafuer steht oben im Block ab `max-width:980px`. */

/* ---- Trefferseite -------------------------------------------------------- */
.kp-suchseite-form{
  display:flex;gap:10px;align-items:center;
  margin:0 0 20px;max-width:640px;
}
.kp-suchseite-form .kp-feld-symbolisch{flex:1 1 auto}

.kp-such-zahl{margin:0 0 16px;color:var(--muted)}
.kp-such-zahl strong{color:var(--text)}

.kp-such-chips{display:flex;flex-wrap:wrap;gap:8px;margin:0 0 22px}
.kp-such-chip{
  display:inline-flex;align-items:center;gap:7px;
  padding:6px 12px;border:1px solid var(--line);border-radius:999px;
  font-size:.85rem;font-weight:600;color:var(--text);text-decoration:none;
  background:var(--card);
}
.kp-such-chip:hover{border-color:var(--brand);color:var(--brand);text-decoration:none}
.kp-such-chip-zahl{
  font-size:.72rem;font-weight:700;border-radius:999px;padding:1px 7px;
  background:var(--line);color:var(--muted);
}

.kp-such-gruppe{margin-bottom:18px}
.kp-such-gruppe-titel{
  display:flex;align-items:center;gap:9px;
  margin:0 0 12px;font-size:1rem;
}
.kp-such-icon{color:var(--brand)}
.kp-such-gruppe-zahl{
  font-size:.74rem;font-weight:700;border-radius:999px;padding:1px 8px;
  background:var(--brand-soft);color:var(--brand);
}

.kp-such-liste{list-style:none;margin:0;padding:0}
.kp-such-liste > li{padding:11px 0;border-top:1px solid var(--line)}
.kp-such-liste > li:first-child{border-top:0}

.kp-such-titel{font-weight:600}
.kp-such-kunde{
  font-size:.8rem;color:var(--muted);
  margin-left:8px;
}
.kp-such-schnipsel{
  margin:4px 0 0;font-size:.86rem;color:var(--muted);
  overflow-wrap:anywhere;
}
.kp-such-liste mark{background:var(--brand-soft);color:inherit;font-weight:700}
.kp-such-mehr{margin:14px 0 0;font-size:.88rem}


/* --------------------------------------------------------------------------
   Glocke (Benachrichtigungen)
   Sieht aus wie der Briefumschlag daneben — es sind zwei Anzeigen derselben
   Art, und sie sollen nicht wie zwei verschiedene Bedienelemente wirken.
   <details>/<summary> wie beim Benutzermenue.
   -------------------------------------------------------------------------- */
.kp-glocke{position:relative}
.kp-glocke > summary{
  position:relative;display:inline-flex;align-items:center;justify-content:center;
  width:38px;height:38px;border-radius:10px;color:var(--text);
  border:1px solid var(--line);cursor:pointer;list-style:none;
  transition:border-color .15s, color .15s;
}
.kp-glocke > summary::-webkit-details-marker{display:none}
.kp-glocke > summary::marker{content:""}
.kp-glocke > summary:hover{color:var(--brand);border-color:var(--brand)}
.kp-glocke > summary:focus-visible{outline:2px solid var(--brand);outline-offset:2px}
.kp-glocke[open] > summary{color:var(--brand);border-color:var(--brand)}

.kp-glocke-zahl{
  position:absolute;top:-6px;right:-6px;
  background:var(--brand);color:#fff;border-radius:20px;
  min-width:18px;height:18px;padding:0 5px;
  font-size:.68rem;font-weight:700;line-height:18px;text-align:center;
  border:2px solid var(--card);
}

.kp-glocke-klapp{
  position:absolute;right:0;top:calc(100% + 8px);z-index:60;
  width:min(380px,calc(100vw - 32px));
  max-height:min(70vh,520px);overflow-y:auto;
  padding:6px;
  /* deckend — siehe .kp-benutzer-klapp */
  background:var(--kp-flyout);border:1px solid var(--line);border-radius:12px;
  box-shadow:0 14px 40px rgba(0,0,0,.22);
}

.kp-glocke-kopf{
  display:flex;align-items:center;justify-content:space-between;gap:10px;
  padding:8px 10px 10px;border-bottom:1px solid var(--line);margin-bottom:4px;
}
.kp-glocke-kopf form{margin:0}
.kp-glocke-alle{
  background:none;border:0;padding:0;cursor:pointer;
  font:inherit;font-size:.8rem;font-weight:600;color:var(--brand);
}
.kp-glocke-alle:hover{text-decoration:underline}

.kp-glocke-leer{padding:16px 10px;margin:0;color:var(--muted);font-size:.86rem}

.kp-glocke-eintrag{
  display:flex;gap:10px;align-items:flex-start;
  padding:9px 10px;border-radius:9px;color:var(--text);text-decoration:none;
}
.kp-glocke-eintrag:hover{background:var(--brand-soft);text-decoration:none}

/* Ungelesen traegt einen Balken links UND fettere Schrift: Farbe allein
   traegt die Unterscheidung nicht, wenn jemand sie nicht sieht. */
.kp-glocke-eintrag.neu{border-left:3px solid var(--brand);padding-left:7px}
.kp-glocke-eintrag.neu b{font-weight:700}

.kp-glocke-icon{flex:0 0 auto;color:var(--brand);line-height:1.4}
.kp-glocke-text{min-width:0;display:block}
.kp-glocke-text b{display:block;font-size:.88rem;font-weight:600}
.kp-glocke-text small{
  display:block;font-size:.79rem;color:var(--muted);margin-top:2px;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.kp-glocke-text time{display:block;font-size:.72rem;color:var(--muted);margin-top:3px}

.kp-glocke-mehr{
  display:block;margin-top:6px;padding:9px 10px;
  border-top:1px solid var(--line);
  font-size:.84rem;font-weight:600;color:var(--brand);text-align:center;
}
.kp-glocke-mehr:hover{background:var(--brand-soft);text-decoration:none}

/* ---- Seite „Hinweise" ---------------------------------------------------- */
.kp-hinweis-leiste{
  display:flex;flex-wrap:wrap;gap:12px;align-items:center;
  justify-content:space-between;margin-bottom:14px;
}
.kp-hinweis-filter,.kp-hinweis-aktionen{display:flex;gap:8px;flex-wrap:wrap}
.kp-hinweis-filter .btn.aktiv{
  border-color:var(--brand);color:var(--brand);background:var(--brand-soft);
}

.kp-hinweis-liste{list-style:none;margin:0;padding:0}
.kp-hinweis-liste > li{
  display:flex;gap:12px;align-items:flex-start;
  padding:12px 0;border-top:1px solid var(--line);
}
.kp-hinweis-liste > li:first-child{border-top:0}
.kp-hinweis-liste > li.neu{
  border-left:3px solid var(--brand);padding-left:11px;
}
.kp-hinweis-icon{flex:0 0 auto;color:var(--brand);line-height:1.5}
.kp-hinweis-text{flex:1 1 auto;min-width:0}
.kp-hinweis-titel{font-weight:600}
.kp-hinweis-liste > li.neu .kp-hinweis-titel{font-weight:700}
.kp-hinweis-schnipsel{
  margin:3px 0 0;font-size:.86rem;color:var(--muted);overflow-wrap:anywhere;
}
.kp-hinweis-wann{display:block;font-size:.75rem;color:var(--muted);margin-top:4px}

.kp-hinweis-weg{margin:0;flex:0 0 auto}
.kp-hinweis-weg button{
  background:none;border:0;padding:4px 8px;cursor:pointer;
  color:var(--muted);font:inherit;font-size:.9rem;border-radius:8px;
}
.kp-hinweis-weg button:hover{color:var(--danger,#c8362e);background:var(--brand-soft)}

/* ==========================================================================
   Auswahlfeld mit eigenem Klappteil (12.08.2026)

   Ansage des Users: „kannst du die optik der dropdown nochmal überarbeiten?
   es hat einen runden rahmen aber eckige einträge, beim lms hast du das
   schöner hinbekommen (ich arbeite im dunkel modus)" — und als Vorbild „im
   lms z.b. das admin menü".

   🔴 Die Liste eines nativen <select> zeichnet das BETRIEBSSYSTEM. Rand,
   Ecken und Farben dieser Liste lassen sich mit CSS nicht anfassen; deshalb
   sitzt unter einem runden Feld ein eckiger Kasten, im dunklen Design
   obendrein oft ein heller. Das ist kein Stylesheet-Fehler, sondern die
   Grenze des Bauteils.

   Deshalb dasselbe Muster wie beim Benutzermenü und der Suche: ein eigener
   Klappteil auf `--kp-flyout` mit Innenabstand, dessen Einträge selbst
   gerundet sind und beim Überfahren die Markenfarbe bekommen.

   ⚠️ Das echte <select> BLEIBT im Markup und trägt weiterhin den Wert — ohne
   JavaScript ist das Feld also unverändert bedienbar, und das Formular
   schickt dasselbe wie vorher. Erst `auswahlfelder()` in portal.js blendet es
   aus und setzt den Knopf davor.
   ========================================================================== */
/* 🔴 Obergrenze für Auswahlfelder (22.08.2026, Meldung des Users: „die ticket
   status drop down box geht über die volle breite" — und gleich danach: „bei
   accounts ebenfalls", „überall auch bei erinnerungen", „und auch aufgaben").

   Es war kein Fehler einzelner Seiten, sondern diese eine Regel: Der Umschlag
   ist ein `div`, also von Haus aus so breit wie sein Container. Steht das Feld
   im Raster `.kp-felder`, deckelt dessen Spalte es bei 340px — steht es in
   einer Karte oder einem einspaltigen Formular, läuft es über die ganze
   Breite. Genau die Stellen hat der User gemeldet.

   340px ist nicht frei gewählt: Es ist das Spaltenmaß von `.kp-felder`, also
   dieselbe Breite, die ein Texteingabefeld daneben höchstens bekommt. Damit
   steht die Auswahl in jedem Zusammenhang auf derselben Kante wie die Felder
   um sie herum, statt einmal so und einmal anders auszusehen.

   ⚠️ `max-width`, nicht `width`: In schmalen Behältern (Filterkasten im
   Spaltenkopf, Telefon) bleibt das Feld weiterhin so breit wie der Platz —
   nur nach oben ist jetzt Schluss.
   ⚠️ Als Variable, weil sie an vier Stellen gebraucht wird und der Wert
   erfahrungsgemäß nachjustiert wird. */
:root{--kp-feldbreite:340px}
.kp-auswahl{position:relative;width:100%;max-width:var(--kp-feldbreite)}
/* Dasselbe für das native Feld — ohne JavaScript wird kein Knopf gebaut, und
   dann zöge das `<select>` selbst über die volle Breite (`input,select,
   textarea{width:100%}` in base.css). Beide Wege müssen gleich aussehen. */
select{max-width:var(--kp-feldbreite)}

/* 🔴 IM Feldraster gilt die Spalte, nicht der Deckel (25.08.2026, Meldung des
   Users: „bei leistungen sind die textboxen auch teilweise nicht ueber die
   gesamte breite"). Seit die Spalten sich bis zum Rand dehnen, sind sie
   breiter als 340px; gemessen 380px Zelle gegen 340px Auswahlfeld. Neben
   einem Eingabefeld, das die Zelle ausfuellt, sah das aus wie eine versetzte
   rechte Kante — bei „Steuersatz" und „Standardturnus" gut zu sehen.
   ⚠️ Der Deckel bleibt fuer Auswahlfelder AUSSERHALB eines Rasters stehen:
   Dort begrenzt sie keine Spalte, und sie zoegen sich sonst ueber die ganze
   Seitenbreite. */
.kp-felder .kp-auswahl,
.kp-felder .kp-wahl-alt,
.kp-felder select{max-width:100%}

/* 🔴 Das echte Feld wird DURCHSICHTIG gelegt, nicht ausgeblendet.
   Fünf Auswahlfelder im Portal sind `required`. Ein ungültiges Pflichtfeld,
   das der Browser nicht anspringen kann (`display:none`, `visibility:hidden`,
   `hidden`), bricht das Absenden mit „An invalid form control is not
   focusable" ab — und zwar STILL: Der Nutzer klickt auf Speichern und es
   passiert nichts. Durchsichtig hinter dem Knopf bleibt es fokussierbar, die
   Prüfblase erscheint an der richtigen Stelle. */
.kp-auswahl-echt{
  position:absolute;left:0;top:0;width:100%;height:100%;
  opacity:0;pointer-events:none;margin:0;padding:0;border:0;
}
.kp-auswahl-text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

/* Ohne JavaScript sieht man nur das native Feld — der Knopf entsteht erst
   dort. Umgekehrt verschwindet das Feld erst, wenn der Knopf steht. */
/* 🔴 Dieselben Werte wie `input,select,textarea` in base.css — Polsterung,
   Radius, Grund und Rand. Der Knopf steht neben echten Eingabefeldern; weicht
   er auch nur um zwei Pixel ab, sieht die Zeile schief aus. */
.kp-auswahl-knopf{
  display:flex;align-items:center;justify-content:space-between;gap:8px;
  width:100%;padding:12px;
  background:var(--input-bg);
  border:1px solid var(--line);border-radius:var(--radius-sm);
  color:var(--text);font-family:inherit;font-size:.95rem;text-align:left;
  cursor:pointer;
}
.kp-auswahl-knopf:hover{border-color:var(--brand)}
.kp-auswahl-knopf:focus-visible{outline:2px solid var(--brand);outline-offset:1px}
.kp-auswahl.offen > .kp-auswahl-knopf{border-color:var(--brand)}
/* Der Pfeil dreht sich beim Aufklappen — dasselbe Zeichen wie im „Neu"-Menü. */
/* ⚠️ Deutlich größer als im LMS-Menü (dort .68rem): Dieser Pfeil ersetzt den
   Pfeil eines Auswahlfeldes und steht am Ende einer breiten Zeile. Klein und
   gedämpft war er im Dunkelmodus praktisch unsichtbar — nachgemessen. */
.kp-auswahl-pfeil{
  flex:0 0 auto;font-size:.95rem;line-height:1;
  color:var(--text);opacity:.65;transition:transform .15s;
}
.kp-auswahl-knopf:hover .kp-auswahl-pfeil{opacity:1}
.kp-auswahl.offen .kp-auswahl-pfeil{transform:rotate(180deg)}
/* „— keine Angabe —" steht gedämpft: Es ist die Abwesenheit eines Werts. */
.kp-auswahl-knopf.leer{color:var(--muted)}

.kp-auswahl-klapp{
  position:absolute;left:0;right:0;top:calc(100% + 6px);z-index:80;
  max-height:min(50vh,320px);overflow-y:auto;
  /* 🔴 deckend über `--kp-flyout`, nicht `--card` — dieselbe Regel wie bei
     allen Klappteilen des Portals. */
  background:var(--kp-flyout);border:1px solid var(--line);border-radius:12px;
  box-shadow:0 16px 44px rgba(0,0,0,.24);
  padding:6px;
}
.kp-auswahl-klapp[hidden]{display:none}

.kp-auswahl-eintrag{
  display:block;padding:8px 10px;border-radius:9px;
  color:var(--text);font-size:.92rem;cursor:pointer;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.kp-auswahl-eintrag:hover,
.kp-auswahl-eintrag.aus{background:var(--brand-soft)}
/* Der GEWÄHLTE Eintrag trägt die Markenfarbe, der gerade angesteuerte nur den
   weichen Grund — sonst sieht man beim Blättern mit den Pfeiltasten nicht
   mehr, was eigentlich gesetzt ist. */
.kp-auswahl-eintrag[aria-selected="true"]{font-weight:600;color:var(--brand)}
.kp-auswahl-eintrag.leer{color:var(--muted)}

/* Der rote Rahmen des Pflichtfeldes — das durchsichtige <select> kann ihn
   nicht zeigen, also übernimmt ihn der Knopf. */
.kp-auswahl-knopf.fehlt{border-color:var(--danger,#c8362e)}

/* Der Pflegeverweis unter dem Feld — wie beim Kündigungsgrund. */
.kp-feld-pflege{display:block;margin-top:4px;font-size:.82rem}

/* ⚠️ Wo das <select> bisher schmal war, muss es der Umschlag auch sein: Die
   bestehenden Regeln treffen `select`, und das ist jetzt das unsichtbare Feld
   in der Ecke. Ohne diese vier Zeilen sprengte die Blätterauswahl ihre Zeile. */
/* 🔴 Die Zeilenzahl-Auswahl war zu schmal (17.08.2026, Meldung des Users:
   „die dropdown box mit 10, 20 … ist zu klein und zeigt nur A.. statt Alle").

   Ursache: `width:auto` bemisst sie nach ihrem INHALT — beim Wert „20" sind
   das 59 px. Sie sitzt aber in einem flexiblen Listenkopf, und dort schrumpft
   sie mit, sobald es eng wird; `white-space:normal` bricht „Alle" dann um und
   es bleibt „A.." sichtbar.

   Drei Dinge dagegen: eine Mindestbreite, die auch den längsten Wert samt
   Pfeil trägt, kein Umbruch, und kein Schrumpfen im Flex-Kopf.
   ⚠️ `nowrap` nur hier und nicht am Bauteil allgemein — dieselbe Auswahl
   trägt anderswo lange Katalognamen, die umbrechen dürfen. */
.kp-pro{flex:0 0 auto}
.kp-pro .kp-auswahl{width:auto;min-width:92px}
.kp-pro .kp-auswahl-knopf{padding:6px 10px;font-size:.86rem;white-space:nowrap}
.kp-pro select{min-width:92px}
.kp-jahrfilter .kp-auswahl{width:auto;min-width:120px}
.kp-suchleiste .kp-auswahl{max-width:190px}
.kp-suchleiste .kp-auswahl-knopf{padding:9px 12px}

/* In der Tabellenzeile sitzt das Feld eng — dort keine 100 %. */
table.tabelle .kp-auswahl{width:auto;min-width:140px}
/* ⚠️ Der Spaltenfilter steht AUCH in `table.tabelle` (im `<th>`), soll aber
   die volle Breite seines Klappkastens haben — sonst stünde ein 140 px
   schmales Feld in einem 300 px breiten Kasten. Diese Regel muss deshalb
   hinter der Tabellenregel stehen und die spezifischere sein. */
table.tabelle .kp-spf-kasten .kp-auswahl{width:100%;min-width:0;max-width:none}

/* ---- Newsfeed (Punkt 3b, 12.08.2026) --------------------------------------
   Meldungen auf der Übersicht — in der Verwaltung die des Anbieters, im
   Kundenbereich die des Mandanten. Bewusst schlicht: Der Kasten steht ganz
   oben und darf die Arbeit darunter nicht verdrängen. */
.kp-news{padding:12px 0;border-top:1px solid var(--line)}
.kp-news:first-of-type{padding-top:0;border-top:0}
.kp-news-titel{margin:0;font-size:1rem;font-weight:600}
.kp-news-meta{font-size:.78rem;color:var(--muted);margin:2px 0 6px}
/* Hervorgehoben heißt: ein Balken in der Markenfarbe, keine gefärbte Fläche.
   Eine volle Farbfläche zöge mehr Aufmerksamkeit als der Handlungsbedarf
   darunter, und der ist dringlicher. */
.kp-news.wichtig{
  border-left:3px solid var(--brand);padding-left:11px;
  border-top-color:transparent;
}
.kp-news.wichtig .kp-news-titel{color:var(--brand)}
/* 🔴 Rechtstexte kommen aus der Datenbank und enthalten lange Adressen,
   E-Mails und Aufsichtsbehörden-Links (15.08.2026, Fund des Users: „die
   datenschutzerklärung rutscht auch ausserhalb des bildes"). Ein Wort ohne
   Trennstelle ist so breit, wie es ist — auf dem Handy schiebt es den ganzen
   Kasten über den Rand. `anywhere` erlaubt den Umbruch notfalls mitten im
   Wort; das ist bei einer URL richtig und bei Fließtext folgenlos, weil dort
   Leerzeichen die günstigere Trennstelle sind.
   ⚠️ Eine Tabelle im Rechtstext (Aufbewahrungsfristen) bricht davon nicht um —
   sie bekommt ihren eigenen Scrollbereich. */
.kp-rechtstext{overflow-wrap:anywhere}
.kp-rechtstext table{display:block;width:100%;overflow-x:auto}

/* 🔴 Die ÜBERSCHRIFT war der eigentliche Grund (15.08.2026, Verdacht des
   Users: „ich vermute mal es liegt an der schriftgröße der überschrift" —
   er hatte recht). „Datenschutzerklärung" ist EIN Wort mit 20 Zeichen; bei
   rund 32 px ist es etwa 350 px breit. Auf einem 390-px-Schirm bleiben nach
   Seiten- und Kartenrand aber nur ungefähr 290 px übrig, und ein Wort ohne
   Trennstelle ist so breit, wie es ist — es schiebt die Karte auf.
   ⚠️ Die Überschrift steht AUSSERHALB von `.kp-rechtstext` (sie kommt aus
   `recht.php`, nicht aus dem Text der Datenbank). Die Umbruchregel darüber
   hat sie deshalb nie erfasst — deswegen blieb der Fehler nach dem ersten
   Anlauf bestehen.

   Zwei Maßnahmen, in dieser Reihenfolge wirksam:
   1. `clamp()` — auf schmalen Geräten ist die Zeile kleiner und passt ohne
      Trennung. Das ist die schönere Lösung, deshalb steht sie zuerst.
   2. Silbentrennung als Netz für noch längere Komposita
      („Verantwortlichkeit", „Aufsichtsbehörde"). Deutsch trennt sauber, weil
      `<html lang="de">` gesetzt ist; ohne `lang` täte `hyphens:auto` nichts.
   ⚠️ `-webkit-hyphens` mitschreiben — Safari kennt die kurze Form nicht.
   `overflow-wrap:anywhere` bleibt als letzte Rückfallebene: Es greift erst,
   wenn auch die Trennung nicht reicht. */
.karte-schmal h1{
  font-size:clamp(1.35rem,5.2vw,2rem);
  line-height:1.2;
}
.karte-schmal h1,
.karte-schmal h2,
.kp-rechtstext h2,
.kp-rechtstext h3{
  overflow-wrap:anywhere;
  -webkit-hyphens:auto;hyphens:auto;
}
/* Auf dem Handy zählt jeder Millimeter Textbreite mehr als das Polster:
   34/30 px Innenrand kosten bei 390 px Schirmbreite ein Sechstel der Zeile. */
@media (max-width:560px){
  .karte-schmal{padding:22px 18px}
}
/* ⚠️ `.schmalseite` ist ein Raster mit `place-items:center` (theme.css). Ein
   zentriertes Rasterelement bekommt KEINE volle Breite, sondern richtet sich
   nach seinem Inhalt — bei einem langen Rechtstext kann das breiter werden
   als der Bildschirm. Auf den Anmeldekarten fällt das nicht auf, die sind
   schmal. */
.schmalseite > .container{width:100%}

.kp-news .kp-rechtstext{font-size:.92rem}
.kp-news .kp-rechtstext p:last-child{margin-bottom:0}

/* ---- „Bereits gelesen" (12.08.2026) ---------------------------------------
   Kopfzeile der Karte: Überschrift links, der Archivschalter rechts. Er sitzt
   dort und nicht unter den Meldungen — sonst wandert er mit jeder neuen
   Meldung weiter nach unten und ist einmal ganz aus dem Blick. */
.kp-news-kopf{
  display:flex;align-items:center;justify-content:space-between;
  gap:12px;flex-wrap:wrap;margin-bottom:10px;
}
.kp-news-kopf h2{margin:0}
/* Der Knopf gehört zur Meldung, nicht zum Text — deshalb rechtsbündig darunter
   und mit Abstand. Neben dem Titel bräche er bei langen Überschriften um. */
.kp-news-aktion{margin-top:8px;text-align:right}
/* Gelesenes bleibt lesbar, tritt aber zurück: Es steht nur im Archiv, und dort
   sucht man Bekanntes. Kein Durchstreichen — das wäre „erledigt", und eine
   Meldung erledigt sich nicht durchs Lesen. */
.kp-news.erledigt .kp-news-titel{color:var(--muted);font-weight:500}
.kp-news.erledigt .kp-rechtstext{color:var(--muted)}
/* ⚠️ Auch im Archiv behält eine wichtige Meldung ihren Balken, aber in
   Grau — sonst leuchtet eine längst gelesene Wartungsmeldung so kräftig wie
   eine neue. */
.kp-news.wichtig.erledigt{border-left-color:var(--line)}
.kp-news.wichtig.erledigt .kp-news-titel{color:var(--muted)}

/* ==========================================================================
   Mein Arbeitsplatz: Wochenkalender auf dem Dashboard (13.08.2026)
   --------------------------------------------------------------------------
   Ansage des Users: „vielleicht ein kleiner wochenkalender auf dem überblick
   des dashboards?" — Montag bis Sonntag, sieben gleich breite Felder.

   🔴 `grid-template-columns:repeat(7,minmax(0,1fr))` und nicht `1fr`: Ohne
   `minmax(0,…)` bestimmt der längste Inhalt (ein Feiertagsname) die Spalte,
   und aus sieben gleichen Feldern werden sieben verschieden breite.
   ========================================================================== */
.kp-woche-kopf{
  display:flex;align-items:center;justify-content:space-between;
  gap:12px;flex-wrap:wrap;margin-bottom:12px;
}
.kp-woche-kopf h2{margin:0}
.kp-woche-nav{display:flex;align-items:center;gap:8px}
.kp-woche-spanne{font-size:.92rem;white-space:nowrap}

.kp-woche{
  display:grid;grid-template-columns:repeat(7,minmax(0,1fr));gap:8px;
}
.kp-woche-tag{
  /* Deckende Fläche, kein `--card`: Bei eingeschalteter Glasoptik schiene der
     Hintergrund durch und die Tage verlören ihre Kante. */
  background:var(--kp-tile-bg);
  border:1px solid var(--line);border-radius:var(--radius);
  padding:8px;min-height:78px;
  display:flex;flex-direction:column;gap:4px;
}
/* Wochenende, Feiertag, Abwesenheit: derselbe zurückgenommene Ton. Sie haben
   verschiedene Gründe, aber dieselbe Aussage — an diesem Tag wird nicht
   gearbeitet. Der Grund steht als Text darin. */
.kp-woche-tag.ruhig{background:transparent}
.kp-woche-tag.heute{border-color:var(--brand);box-shadow:0 0 0 1px var(--brand) inset}
.kp-woche-datum{display:flex;align-items:baseline;gap:6px;line-height:1}
.kp-woche-wt{font-weight:700;font-size:.86rem}
.kp-woche-nr{font-size:.8rem;color:var(--muted)}
.kp-woche-zeit{font-size:.86rem;margin-top:auto}
/* Marke für Abwesenheit und Feiertag — schmaler Text, umbruchfähig: „Tag der
   Deutschen Einheit" muss in 90 px passen, ohne die Spalte zu sprengen. */
.kp-woche-marke{
  font-size:.78rem;line-height:1.2;font-weight:600;color:var(--kp-warn-text);
  overflow-wrap:anywhere;
}
.kp-woche-marke.frei{color:var(--muted);font-weight:500}
/* Beantragt ist noch nicht entschieden — gestrichelt, wie im Jahreskalender. */
.kp-woche-marke.offen{border-bottom:1px dashed var(--kp-warn)}
.kp-woche-klein{font-size:.72rem;line-height:1.2}
.kp-woche-summe{
  margin:12px 0 0;display:flex;align-items:baseline;gap:8px;flex-wrap:wrap;
  font-size:.92rem;
}
.kp-woche-saldo{margin-left:auto;font-weight:700}
.kp-woche-saldo.minus{color:var(--kp-warn-text)}

/* ⚠️ Unter 900 px vier Spalten, unter 560 px zwei: Sieben Felder nebeneinander
   werden auf dem Handy zu Streifen, in denen keine Uhrzeit mehr steht. Die
   Reihenfolge bleibt dieselbe, nur der Umbruch ändert sich. */
@media (max-width:900px){
  .kp-woche{grid-template-columns:repeat(4,minmax(0,1fr))}
}
@media (max-width:560px){
  .kp-woche{grid-template-columns:repeat(2,minmax(0,1fr))}
  .kp-woche-saldo{margin-left:0}
}

/* Karte „Mein Konto" (13.08.2026) — Avatar neben Name, darunter die beiden
   Anmeldezeiten. Der Avatar bringt seine eigene Größe mit (Profil::avatar),
   hier steht nur die Anordnung. */
.kp-konto{display:flex;align-items:center;gap:12px;margin-bottom:12px}
.kp-konto-text{display:flex;flex-direction:column;gap:2px;min-width:0}
/* ⚠️ `min-width:0` und Umbruch: Eine lange Adresse sprengt sonst die Karte —
   Flex-Kinder schrumpfen ohne das nicht unter ihre Inhaltsbreite. */
.kp-konto-text > *{overflow-wrap:anywhere}
.kp-konto-text .muted{font-size:.86rem}

/* Erinnerung im Wochenkalender (13.08.2026) — ein Verweis, kein Absatz: Er
   muss in eine 90-px-Spalte passen und darf die Zeilenhöhe der Woche nicht
   sprengen. Deshalb zweizeilig abgeschnitten statt umbrechend. */
.kp-woche-er{
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;
  overflow:hidden;
  font-size:.76rem;line-height:1.25;color:var(--brand);text-decoration:none;
}
.kp-woche-er:hover{text-decoration:underline}
.kp-woche-er.muted{color:var(--muted)}

/* Eigene Erinnerung in der Kalenderkachel (13.08.2026) — wie ein Name
   abgeschnitten statt umgebrochen, damit das Raster nicht wackelt. Kein
   farbiger Balken: Sie ist kein Zustand des Tages wie eine Abwesenheit,
   sondern ein Verweis. */
.kal-er{
  display:block;font-size:.74rem;line-height:1.25;padding:1px 3px;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  color:var(--brand);text-decoration:none;
}
.kal-er:hover{text-decoration:underline}
.kal-er.muted{color:var(--muted)}

/* „2 abwesend" im Wochenkalender (13.08.2026) — Zahl statt Namen: In eine
   90-px-Spalte passt kein Name, und die Frage lautet ohnehin „fehlt heute
   jemand?". Wer wissen will, wer, klickt in den Kalender. */
.kp-woche-koll{
  font-size:.74rem;line-height:1.2;color:var(--muted);text-decoration:none;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.kp-woche-koll:hover{text-decoration:underline;color:var(--text)}

/* „Mein Arbeitsplatz" auf dem Dashboard (13.08.2026) — Abstand nach oben und
   zwischen den eigenen Bausteinen. Vom User beanstandet: Die Kachelreihe klebte
   an der Karte darüber. `.kp-kacheln` bringt nur einen Rand nach unten mit.
   ⚠️ Der Abstand sitzt an der Hülle, nicht an den einzelnen Bausteinen — die
   stehen auch anderswo und sollen dort ihr gewohntes Maß behalten. */
.kp-arbeitsplatz{margin-top:34px}
.kp-arbeitsplatz > .kp-kacheln{margin-bottom:18px}
.kp-arbeitsplatz > .karte + .karte,
.kp-arbeitsplatz > .karte + .kp-zweispalt,
.kp-arbeitsplatz > .kp-kacheln + .karte,
/* 🔴 Nachgetragen 31.08.2026 (Fund des Users: „meine offenen aufgaben hat
   keinen abstand zu mein konto"). Die Liste deckte `.karte + .karte` und
   `.karte + .kp-zweispalt` ab, aber nicht die beiden Fälle, in denen ein
   Rasterblock oben steht — und genau die stehen im Arbeitsplatz
   untereinander. */
.kp-arbeitsplatz > .kp-zweispalt + .kp-zweispalt,
.kp-arbeitsplatz > .kp-zweispalt + .karte{margin-top:18px}

/* ==========================================================================
   Auswahl-Overlay (13.08.2026)
   --------------------------------------------------------------------------
   Breiter als im LMS (Ansage des Users): bis 1120 px, damit Nummer, Titel,
   Kunde und Status nebeneinander lesbar bleiben. Auf schmalen Geräten füllt
   es die Fläche.
   ========================================================================== */
.kp-wahl-hintergrund{
  position:fixed;inset:0;z-index:1200;
  background:rgba(15,23,42,.55);
  display:flex;align-items:center;justify-content:center;padding:24px;
}
.kp-wahl-hintergrund[hidden]{display:none}
/* Der Seiteninhalt darf nicht mitscrollen, solange das Fenster offen ist. */
body.kp-wahl-offen{overflow:hidden}

.kp-wahl-fenster{
  /* 🔴 Deckend, nicht `--card`: Bei eingeschalteter Glasoptik ist das im
     Dunkeln fast durchsichtig, und die Tabelle läge über dem Seiteninhalt. */
  background:var(--kp-flyout);
  color:var(--text);
  border:1px solid var(--line);border-radius:var(--radius);
  box-shadow:0 24px 60px rgba(0,0,0,.35);
  width:min(1120px,100%);max-height:min(760px,90vh);
  display:flex;flex-direction:column;overflow:hidden;
}
.kp-wahl-kopf{
  display:flex;align-items:center;gap:16px;flex-wrap:wrap;
  padding:16px 20px;border-bottom:1px solid var(--line);
}
.kp-wahl-kopf h2{margin:0;font-size:1.1rem}
.kp-wahl-suche{flex:1 1 240px;min-width:180px}
.kp-wahl-filter{
  display:flex;gap:16px;flex-wrap:wrap;align-items:center;
  padding:10px 20px;border-bottom:1px solid var(--line);
}
.kp-wahl-filter:empty{display:none}
.kp-wahl-filterfeld{display:flex;align-items:center;gap:8px;font-size:.9rem}
.kp-wahl-filterfeld select{width:auto}

/* Die Liste ist der einzige Bereich, der scrollt — Kopf und Fuß bleiben
   stehen, damit „Übernehmen" immer erreichbar ist. */
.kp-wahl-liste{overflow:auto;flex:1 1 auto;padding:0 8px}
.kp-wahl-liste table{margin:0}
.kp-wahl-zeile{cursor:pointer}
.kp-wahl-zeile:hover{background:var(--hover)}
.kp-wahl-zeile.gewaehlt{background:var(--hover);box-shadow:inset 3px 0 0 var(--brand)}
.kp-wahl-sort{
  background:none;border:0;padding:0;font:inherit;font-weight:700;
  color:inherit;cursor:pointer;
}
.kp-wahl-sort:hover{text-decoration:underline}

.kp-wahl-fuss{
  display:flex;align-items:center;gap:16px;flex-wrap:wrap;
  padding:12px 20px;border-top:1px solid var(--line);
}
.kp-wahl-pro{display:flex;align-items:center;gap:8px;font-size:.9rem}
.kp-wahl-pro select{width:auto}
.kp-wahl-blaettern{display:flex;align-items:center;gap:8px}
.kp-wahl-knoepfe{margin-left:auto;display:flex;gap:8px}

/* Das Feld im Formular: Knopfreihe oben, gewählter Eintrag darunter (Ansage
   des Users, 13.08.2026). Nebeneinander schob ein langer Tickettitel den
   Knopf „entfernen" aus der Zeile. */
/* Das Feld im Formular: Anzeige links, daneben ＋ ✕ ⚙ (Ansage des Users,
   13.08.2026). Vorher standen zwei flache Knöpfe über dem Text und der
   Pflege-Link darunter — drei Zeilen für eine Angabe.
   🔴 Die Anzeige übernimmt Polsterung, Rand und Grund von `input` aus
   base.css: Das Feld steht neben echten Eingabefeldern, und schon zwei Pixel
   Abweichung lassen die Zeile schief aussehen. */
.kp-wahl-feld{display:flex;align-items:stretch;gap:6px}
.kp-wahl-anzeige{
  flex:1 1 auto;min-width:0;
  display:flex;align-items:center;
  padding:12px;
  background:var(--input-bg);
  border:1px solid var(--line);border-radius:var(--radius-sm);
  font-size:.95rem;line-height:1.2;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
/* Ohne Auswahl gedämpft — es ist die Abwesenheit eines Werts, kein Wert. */
.kp-wahl-anzeige.leer{color:var(--muted)}
/* Die drei Zeichenknöpfe: quadratisch, so hoch wie das Feld daneben. */
.kp-wahl-sym{
  flex:0 0 auto;width:44px;
  display:flex;align-items:center;justify-content:center;
  background:var(--input-bg);
  border:1px solid var(--line);border-radius:var(--radius-sm);
  color:var(--text);font-size:1rem;line-height:1;text-decoration:none;
  cursor:pointer;transition:border-color .15s,color .15s;
}
.kp-wahl-sym:hover{border-color:var(--brand);color:var(--brand)}
.kp-wahl-sym:focus-visible{outline:2px solid var(--brand);outline-offset:1px}
/* ⚠️ Unter 560 px bricht die Reihe um: Ein Feld mit drei Knöpfen daneben
   lässt auf dem Handy sonst zwei Zeichen für den Wert übrig. */
@media (max-width:560px){
  .kp-wahl-feld{flex-wrap:wrap}
  .kp-wahl-anzeige{flex:1 1 100%}
}

/* ==========================================================================
   Overlays auf dem Handy (15.08.2026)
   --------------------------------------------------------------------------
   🔴 Fund des Users: „im overlay hab ich auch keine ,x button' oben, muss also
   immer bis zum abbrechen runterscrollen."

   Ursache war NICHT ein fehlender Knopf — er stand die ganze Zeit im Markup.
   Die Schale ist `position:fixed;inset:0` und zentriert ihr Fenster
   (`align-items:center`), das Fenster durfte `100vh` hoch werden. Auf dem
   Handy ist `100vh` die Höhe OHNE die eingeblendete Adressleiste des Browsers:
   Das Fenster wurde höher als der sichtbare Bereich und stand zentriert
   darin — oben und unten ragte es heraus, und was oben herausragte, war die
   Kopfzeile mit ✕.

   Deshalb hier zweierlei:
   1. `align-items:stretch` — das Fenster beginnt oben, statt zu schweben.
   2. `100dvh` (dynamische Sichthöhe) statt `100vh`. Ältere Browser kennen es
      nicht und bleiben beim bisherigen Verhalten; ein Rückschritt entsteht
      dadurch nicht.
   ⚠️ Der Kopf darf nicht schrumpfen (`flex:0 0 auto`) — sonst gibt er unter
   Druck des scrollenden Inhalts nach und der Knopf wandert doch aus dem Bild.
   ========================================================================== */
@media (max-width:720px){
  .kp-wahl-hintergrund{padding:0;align-items:stretch;height:100dvh}
  .kp-wahl-fenster{width:100%;max-height:none;height:100%;
                   border-radius:0;border:0}
  .kp-wahl-kopf{flex:0 0 auto}
  .kp-wahl-knoepfe{margin-left:0;width:100%}
  .kp-wahl-knoepfe .btn{flex:1 1 auto}
}

/* Pflichtfeld-Zeichen (13.08.2026) — portalweit von `portal.js` angehängt.
   ⚠️ `--kp-warn-text` statt `--danger`: Ein Pflichtfeld ist kein Fehler,
   sondern ein Hinweis. Rot bekommt das Feld erst, wenn es leer bleibt. */
.kp-pflicht{color:var(--kp-warn-text);margin-left:3px;font-weight:700}
.kp-pflicht-hinweis{font-size:.82rem;margin:14px 0 0}

/* Spaltenfilter im Auswahl-Overlay (13.08.2026) — die Kästen kommen aus
   derselben Familie wie in den Arbeitslisten (`.kp-spf`), sie brauchen hier
   nur zwei Anpassungen: Der Kopf trägt Sortierknopf UND Trichter
   nebeneinander, und der Kasten darf nicht unter dem Tabellenrand
   verschwinden. */
.kp-wahl-liste th{white-space:nowrap}
.kp-wahl-liste th .kp-spf{display:inline-block;vertical-align:middle;margin-left:6px}
/* ⚠️ `overflow:auto` am Listenbereich schneidet aufgeklappte Kästen ab.
   Deshalb liegt der Kasten hier fest über der Tabelle statt im Fluss. */
.kp-wahl-liste .kp-spf-kasten{position:absolute;z-index:5}
.kp-wahl-liste .kp-spf details[open]{position:relative}
.kp-wahl-filterweg{
  background:none;border:0;padding:0;font:inherit;color:var(--brand);
  cursor:pointer;text-decoration:underline;
}

/* Bearbeiten-Overlay (13.08.2026) — dieselbe Schale wie die Auswahl, nur mit
   einem Formular darin statt einer Tabelle. Etwas schmaler: Ein Formular liest
   sich in einer breiten Spalte schlechter als eine Tabelle. */
.kp-maske-fenster{width:min(860px,100%)}
.kp-maske-inhalt{overflow:auto;padding:20px;flex:1 1 auto}
/* Die Maske bringt ihre eigene Überschrift mit — im Fenster steht sie schon
   im Kopf, deshalb hier weg. Dasselbe gilt für „Zur Übersicht". */
.kp-maske-inhalt .kp-titel{display:none}
.kp-maske-inhalt > .kp-maske > .kp-aktionen:first-of-type{margin-bottom:14px}
.kp-maske-inhalt .kp-unter{margin-top:0}

/* Der Schließen-Knopf gehört an den rechten Rand, nicht neben den Titel
   (13.08.2026 im Browser gesehen). Im Auswahl-Overlay schiebt ihn das
   Suchfeld dorthin, im Bearbeiten-Overlay gibt es keines. */
.kp-maske-fenster .kp-wahl-kopf > h2{margin-right:auto}

/* Im Fenster gezeigte LISTEN (Stammdaten) brauchen etwas mehr Breite als ein
   Formular — Tabellen mit fünf Spalten sind sonst gequetscht. Die Schale
   entscheidet nach Inhalt: Steht eine Tabelle darin, wird sie breiter. */
.kp-maske-fenster:has(.kp-maske-inhalt table){width:min(1120px,100%)}
/* Der Zurück-Pfeil sitzt vor dem Titel und erscheint erst ab dem zweiten
   Schritt. */
.kp-maske-fenster .kp-wahl-kopf{gap:10px}

/* ⚠️ Der Unterstrich kommt von der allgemeinen Regel `a:hover` — beim ⚙ ist
   er falsch: Es ist ein Knopf, der zufällig ein Verweis ist (vom User
   beanstandet, 13.08.2026). Der Rahmen zeigt schon, dass er anspricht. */
.kp-wahl-sym:hover,
.kp-wahl-sym:focus-visible{text-decoration:none}

/* Der Block um Feld und Pflege-Verweis (13.08.2026): Die Reihe mit Anzeige
   und Knöpfen oben, der dezente Verweis darunter — kein Zahnrad in der Reihe
   (Entscheidung des Users). */
.kp-wahl-block{display:flex;flex-direction:column;gap:6px}
.kp-wahl-block .kp-feld-pflege{margin:0}

/* ==========================================================================
   Flackern im Hintergrund abstellen (13.08.2026)
   --------------------------------------------------------------------------
   Fund des Users: „im dunkelmodus ist mir schon öfters ein flackern
   aufgefallen … die portal maske im hintergrund flackert, während das andere
   Fenster im Vordergrund nicht flackert."

   🔴 Ursache sind die Farbwolken aus `base.css`: `.blob` trägt
   `filter:blur(90px)` UND eine endlose Animation (`blob-drift`, 20–28 s). Ein
   700-px-Kreis mit 90 px Weichzeichner muss damit in JEDEM Bild neu gerastert
   werden — dauerhaft, auch wenn das Fenster im Hintergrund liegt. Im dunklen
   Design fällt das besonders auf, weil die Abstufungen dort größer sind.

   Die Wolken BLEIBEN, nur stehen sie still. Im Portal ist die Bewegung
   ohnehin fehl am Platz: Es ist ein Arbeitswerkzeug, keine Schaufensterseite —
   und die Demoseiten (dieselbe `base.css`) behalten ihre Bewegung.
   ========================================================================== */
body.kp .blob{animation:none}

/* ==========================================================================
   🔴 Glasoptik auf kleinen und berührungsbedienten Geräten AUS (22.08.2026)
   ==========================================================================
   Meldung des Users: „auf mobil lädt die seite gefühlt langsam und verzögert"
   — und nach dem Gegentest: „wenn die glassmorph aus sind läuft es sehr sehr
   viel flüssiger."

   Gemessen wurde vorher, woran es NICHT liegt: Der Server antwortet in 9 ms,
   gzip ist an, der Langzeit-Cache steht. Es bleibt das Zeichnen — elf Regeln
   mit `backdrop-filter: blur(24px) saturate(160%)` und drei Farbwolken mit
   `blur(90px)` bis `blur(150px)` bei 450 bis 700 px Kantenlänge. Jede
   unscharfe Fläche zwingt die Grafikeinheit, den Hintergrund dahinter neu zu
   rastern — auf einem Notebook unauffällig, auf einem Telefon nicht.

   🔴 Nur die UNSCHÄRFE fällt weg, nicht die Farbwelt. `--card`, `--line`,
   Radien und Schatten bleiben, wie sie sind — die Oberfläche sieht also
   weiterhin nach Glasoptik aus, sie wird nur nicht mehr weichgezeichnet. Wer
   die Flächen zusätzlich deckend haben will, schaltet die Optik ganz ab; das
   geht seit heute auch je Zugang (→ `Mandant::glasoptikFuer()`).

   ⚠️ Die Farbwolken müssen mit weg. Ohne sie hätte die Unschärfe nichts, was
   durchscheinen könnte — und umgekehrt sind gerade sie die teuersten Flächen
   der ganzen Seite. Dieselbe Kopplung wie beim Mandantenschalter.

   ⚠️ `!important` und `*` sind hier bewusst gesetzt, und zwar als einzige
   Stelle im Portal: Die Glasregeln stehen verteilt über `base.css` (5 Stück,
   über `--card-blur`) und `theme.css` (7 Stück, mit fest eingetragenen
   Werten), teils mit höherer Spezifität als alles, was hier stehen könnte.
   Eine Aufzählung müsste bei jeder neuen Glasfläche nachgepflegt werden — und
   würde beim ersten Vergessen still wieder Leistung kosten. Es gibt keinen
   Fall, in dem auf einem Telefon eine Unschärfe stehen bleiben soll.

   Grenze: 900px ODER Berührungsbedienung ohne Zeigegerät. Zwei Bedingungen,
   weil weder allein reicht — ein Tablet im Querformat ist breiter als 900,
   und ein schmal gezogenes Fenster am Rechner ist kein Telefon. Getroffen
   werden soll, was langsam zeichnet, nicht was schmal ist.
   ========================================================================== */
@media (max-width:900px), (hover:none) and (pointer:coarse){
  html[data-modern="on"]{--card-blur:none}
  html[data-modern="on"] *{
    backdrop-filter:none !important;
    -webkit-backdrop-filter:none !important;
  }
  html[data-modern="on"] .bg-blobs{display:none}

  /* 🔴 NACHTRAG am selben Tag, Meldung des Users: „im portal ist mobil nun ein
     roter rahmen um den header".

     Mein Fehler: Ich hatte nur die Unschärfe abgeschaltet und die
     DURCHSICHTIGEN Flächen stehen lassen. Genau davon lebt die Glasoptik aber:
     `--bg-image` legt zwei rote Farbverläufe in die oberen Ecken
     (`12% -8%` und `92% 8%`, aus `--brand` und `--accent`), und der
     Weichzeichner hat daraus einen diffusen Schimmer gemacht. Ohne ihn steht
     der Verlauf scharf da — links und rechts neben der Kopfzeile, also
     genau als „Rahmen".

     ⚠️ Dieselbe Falle wie bei `--card` gegen `--kp-flyout`: Eine durchsichtige
     Fläche ist nur so lange eine Fläche, wie etwas sie mattiert. Fällt der
     Weichzeichner weg, MUSS die Fläche deckend werden.

     Zweiter Grund, der ohne die Meldung später aufgefallen wäre: Die
     Kopfzeile klebt beim Scrollen oben. Mit 72 % Deckkraft und ohne
     Weichzeichner wäre der Inhalt sichtbar dahinter durchgelaufen.

     📌 Der Verlauf kostet nebenbei selbst Rechenzeit — zwei Flächen von
     900×600 und 800×520 px. Ihn wegzulassen ist also nicht nur richtiger,
     sondern auch schneller. */
  /* 🔴 ZWEI Selektoren, und der zweite ist der entscheidende. `base.css`
     definiert die Glaswerte unter `html[data-modern="on"][data-theme="light"]`
     — das sind ZWEI Attribute und schlägt ein einzelnes `[data-modern]`,
     egal wie spät die Datei geladen wird. Mein erster Versuch hatte nur den
     kurzen Selektor: im Dunkeln griff er (dort hatte ich zufällig die lange
     Form geschrieben), im HELLEN blieb alles beim Alten — und genau da liegt
     der rote Verlauf.
     Nachgemessen im Browser: `--bg-image` stand danach immer noch auf beiden
     radial-gradient-Flächen mit #c8362e und #8f231d.
     Merksatz, den ich schon einmal aufgeschrieben habe: Wer eine bestehende
     Regel überschreibt, nimmt IHREN Selektor — nicht einen kürzeren.
     Die erste Zeile deckt den Fall ohne `data-theme` mit ab (Systemvorgabe,
     bevor das Skript das Attribut setzt). */
  html[data-modern="on"],
  html[data-modern="on"][data-theme="light"]{
    --bg-image:none;
    --header-bg:rgba(255,255,255,.96);
    --footer-bg:#f1f5f9;
    --card:#ffffff;
    --input-bg:#ffffff;
  }
  html[data-modern="on"][data-theme="dark"]{
    --bg-image:none;
    --header-bg:#0b1020;
    --footer-bg:#0c111c;
    --card:#141b2b;
    --input-bg:#141a28;
  }
}

/* Mehrfachauswahl im Overlay (13.08.2026): schmale Hakenspalte ganz links. */
.kp-wahl-liste th.kp-wahl-haken,
.kp-wahl-liste td.kp-wahl-haken{width:44px;text-align:center}
.kp-wahl-liste td.kp-wahl-haken input{cursor:pointer}

/* ==========================================================================
   Dashboard anpassen (Punkt 19c, 15.08.2026)
   --------------------------------------------------------------------------
   Eine Zeile je Registerkarte und Baustein: links Haken und Name, rechts die
   beiden Pfeile. Bewusst eine Liste und kein Ziehen mit der Maus — Ziehen
   braucht Zeigegerät und ruhige Hand, zwei Knöpfe kommen auch mit Tastatur
   und auf dem Handy aus.
   ========================================================================== */
/* Zweite Ebene der Maske: eine Reiterleiste je Registerkarte (15.08.2026).
   🔴 `.kp-dash-tabinhalt` ist im Grundzustand SICHTBAR — erst `kp-tabs-an`
   (von `portal.js` gesetzt) blendet aus. Ohne Skript bleibt die Maske damit
   vollständig bedienbar; andersherum wäre sie leer. */
.kp-dash-tabs:not(.kp-tabs-an) .kp-leiste-schiebe{display:none}
.kp-dash-tabbar{display:flex;gap:2px;flex-wrap:wrap}
.kp-dash-tabbar button{
  border:0;border-bottom:3px solid transparent;background:none;
  padding:10px 16px;margin-bottom:-1px;white-space:nowrap;
  font:inherit;font-size:.92rem;font-weight:600;color:var(--muted);
  cursor:pointer}
.kp-dash-tabbar button:hover{color:var(--text)}
.kp-dash-tabbar button.aktiv{color:var(--brand);border-bottom-color:var(--brand)}
.kp-dash-tabs.kp-tabs-an .kp-dash-tabinhalt{display:none}
.kp-dash-tabs.kp-tabs-an .kp-dash-tabinhalt.aktiv{display:block}
/* Mit Leiste trägt die Karte den Namen schon oben — die Überschrift bliebe
   eine Dopplung. Ohne Leiste ist sie die einzige Orientierung. */
.kp-dash-tabs.kp-tabs-an .kp-dash-tabinhalt > .karte > h2{display:none}
.kp-dash-tabs.kp-tabs-an .kp-dash-tabinhalt > .karte{margin-top:0}

.kp-dash-liste{list-style:none;margin:12px 0 0;padding:0;
               display:flex;flex-direction:column;gap:2px}
.kp-dash-zeile{display:flex;align-items:center;gap:12px;
               padding:8px 10px;border-radius:var(--radius);
               border:1px solid transparent}
.kp-dash-zeile:hover{background:var(--hover);border-color:var(--border)}

.kp-dash-name{display:flex;align-items:flex-start;gap:10px;flex:1 1 auto;
              margin:0;cursor:pointer;font-weight:500}
.kp-dash-name input{margin-top:3px;flex:0 0 auto;cursor:pointer}
/* Ein abgeschalteter Haken („Überblick") ist keine Einladung zum Klicken. */
.kp-dash-name input:disabled{cursor:default;opacity:.55}
.kp-dash-name input:disabled + span{opacity:.75}
.kp-dash-name small{display:block;font-weight:400;font-size:.82rem;
                    margin-top:1px}

/* Die Spalte bleibt auch bei festen Zeilen stehen — sonst rutschen deren
   Namen nach rechts und die Liste franst aus. */
.kp-dash-pfeile{flex:0 0 auto;display:flex;gap:4px;min-width:62px;
                justify-content:flex-end}
.kp-dash-pfeile button{width:29px;height:29px;line-height:1;padding:0;
                       border:1px solid var(--border);border-radius:8px;
                       background:var(--card);color:var(--text);
                       cursor:pointer;font-size:.78rem}
.kp-dash-pfeile button:hover{background:var(--hover)}
.kp-dash-pfeile button:focus-visible{outline:2px solid var(--primary);
                                     outline-offset:1px}

@media (max-width:560px){
  /* Namen wie „Verantwortung je Mitarbeiter" brauchen die Breite; die Pfeile
     rücken enger zusammen, statt den Text zweizeilig zu machen. */
  .kp-dash-zeile{gap:8px;padding:8px 6px}
  .kp-dash-pfeile{min-width:auto}

  /* 🔴 Aktionsknöpfe stehen auf dem Handy untereinander und gleich breit
     (Fund des Users, 15.08.2026: „ticket erstellen und abbrechen nicht exakt
     untereinander"). Ohne die Regel behält jeder Knopf beim Umbruch seine
     Textbreite, und zwei gleichrangige Aktionen sehen aus wie zwei
     verschiedene Dinge.
     ⚠️ Nur die großen Knöpfe. `.btn-klein` steht in Listenzeilen und in
     Werkzeugreihen — die gehören nebeneinander, nicht gestapelt. */
  .kp-aktionen > .btn:not(.btn-klein){flex:1 1 100%}
}

/* ==========================================================================
   Schiebbare Reiterleisten (15.08.2026)
   --------------------------------------------------------------------------
   Ansage des Users: dieselbe Darstellung wie in „Dashboard anpassen" fuer
   alle Reiterleisten, „damit das portal wie aus einem guss wirkt".

   Die Huelle `.kp-leiste-schiebe` steht im MARKUP — `leisteAuf()` und
   `leisteZu()` in `index.php` geben sie an den acht Stellen aus, an denen
   eine Leiste entsteht. Ein erster Anlauf liess sie vom Skript um die Leiste
   herum bauen; das verschob sie im DOM und brach die Umschaltung der
   Stammdaten. **Bestehendes Markup nicht nachtraeglich umbauen.**

   Auf dem DESKTOP aendert sich nichts: Die Leiste bricht weiter um, nichts
   liegt ausserhalb, `portal.js` findet nichts zu schieben und die Pfeile
   bleiben unsichtbar.
   ========================================================================== */
/* 🔴 Der Abstand nach unten gehört an die HÜLLE, nicht an die Leiste darin
   (02.09.2026, Fund des Users: „der abstand ist im sticky tab, sollte aber VOR
   den kacheln kommen").

   `.kp-leiste-schiebe` ist ein Flex-Container: Die Marge eines Flex-Kindes
   zählt zu seiner Höhe. Der `margin-bottom` von `.kp-reiter` lag damit INNEN
   — der klebende Kasten war 36 px höher als die Reiter, sein Hintergrund samt
   Schattenkranz reichte über den Abstand hinweg, und beim Scrollen stand ein
   entsprechend dicker Balken über der Seite. Gemessen: Kasten 183–267, die
   sichtbare Reiterkante aber schon bei 231.

   An der Hülle liegt die Marge AUSSERHALB des klebenden Kastens, also dort,
   wo der Abstand hingehört.
   📌 `.kp-leiste-schiebe.kp-eng` löst dasselbe weiter unten schon richtig —
   dort trägt die Hülle den Abstand und das Kind bekommt `margin:0`. Ohne
   `kp-eng` fehlte genau dieser Schritt. */
.kp-leiste-schiebe{display:flex;align-items:stretch;margin:0 0 36px}
.kp-leiste-schiebe > .kp-reiter,
.kp-leiste-schiebe > .kp-dash-tabbar{flex:1 1 auto;min-width:0;margin-bottom:0}

.kp-leiste-pfeil{
  display:none;flex:0 0 auto;width:30px;align-self:stretch;
  border:0;background:none;color:var(--muted);
  font-size:1.2rem;line-height:1;cursor:pointer;
}
.kp-leiste-schiebe.kp-schiebbar .kp-leiste-pfeil{display:block}
.kp-leiste-pfeil:hover:not(:disabled){color:var(--brand)}
/* Am Ende angekommen abgeblendet STEHEN LASSEN — verschwaende der Knopf,
   spraenge die Leiste bei jedem Schieben um 30 px zur Seite. */
.kp-leiste-pfeil:disabled{opacity:.3;cursor:default}

/* 🔴 Umgeschaltet wird nach BEDARF, nicht nach Bildschirmbreite (Ansage des
   Users, 15.08.2026: „bau es so, dass es bei zwei zeilen auf die buttons
   springt"). `portal.js` rechnet die natuerliche Breite der Reiter zusammen;
   passt sie nicht in eine Zeile, setzt es `kp-eng` — und erst dann scrollt
   die Leiste. Das gilt auf dem Handy wie am Schreibtisch: Zwei Zeilen Reiter
   sehen ueberall unruhig aus.
   ⚠️ `overflow-y:hidden` gegen die zweite, senkrechte Bildlaufleiste: Der
   aktive Reiter ragt mit `margin-bottom:-1px` ueber den Rand, und bei
   `overflow-x:auto` zaehlt dieses eine Pixel in der Senkrechten. */
/* 📌 36 px wie bei `.kp-reiter` (02.09.2026) — im engen Zustand trägt die
   Hülle den Abstand, im weiten die Leiste selbst. Stünden hier noch 22 px,
   spränge der Abstand beim Umschalten auf die schiebbare Leiste. */
.kp-leiste-schiebe.kp-eng{margin:0 0 36px;border-bottom:1px solid var(--line)}
.kp-leiste-schiebe.kp-eng > .kp-reiter,
.kp-leiste-schiebe.kp-eng > .kp-dash-tabbar{
  margin:0;border-bottom:0;
  flex-wrap:nowrap;overflow-x:auto;overflow-y:hidden;
  scrollbar-width:none;-webkit-overflow-scrolling:touch;
}
.kp-leiste-schiebe.kp-eng > .kp-reiter::-webkit-scrollbar,
.kp-leiste-schiebe.kp-eng > .kp-dash-tabbar::-webkit-scrollbar{display:none}

/* ⚠️ Muss IMMER gelten, nicht nur im engen Zustand: Die Messung im Skript
   zaehlt die Breiten der Reiter zusammen. Duerfte ein Reitertext umbrechen,
   waere seine Breite von der Fensterbreite abhaengig und die Rechnung
   liefe im Kreis. */
.kp-reiter button,.kp-reiter a,.kp-dash-tabbar button{white-space:nowrap}

@media (max-width:720px){
  .kp-reiter button,.kp-reiter a,.kp-dash-tabbar button{padding:10px 13px}
}

/* ==========================================================================
   Klappfenster der Kopfleiste auf dem Handy (15.08.2026)
   --------------------------------------------------------------------------
   🔴 Fund des Users: „klicke ich oben die glocke an verschwindet der overlay
   links aus dem bild." Die Fenster hängen mit `right:0` an ihrem eigenen
   Knopf und sind bis zu 380 px breit — sitzt der Knopf nicht ganz rechts,
   ragen sie nach links über den Bildrand hinaus.

   Auf schmalen Geräten hängen sie deshalb nicht mehr am Knopf, sondern an der
   Kopfzeile: `position:static` am Knopf gibt den Bezugsrahmen an die Zeile ab,
   und `left`/`right` spannen das Fenster über die volle Breite.
   ⚠️ Dafür MUSS die Zeile positioniert sein — sonst wäre der nächste Bezug
   das Fenster selbst und die Fenster stünden ganz oben auf der Seite.
   ========================================================================== */
@media (max-width:720px){
  body.kp header.site .container.nav{position:relative}
  .kp-glocke,.kp-benutzer{position:static}
  .kp-glocke-klapp,.kp-benutzer-klapp{
    left:12px;right:12px;width:auto;min-width:0;max-width:none;
    top:calc(100% + 6px);
  }
}

/* ==========================================================================
   Sprachauswahl in der Kopfleiste (Punkt 18, 15.08.2026)
   --------------------------------------------------------------------------
   Sitzt zwischen Hell/Dunkel-Umschalter und Glocke (Ansage des Users). Sie
   ist ein `<details>` wie Glocke und Benutzermenue — damit klappt sie ohne
   JavaScript auf, und `portal.js` muss sich um nichts kuemmern.

   🔴 Deckende Flaeche (`--kp-flyout`), nicht `--card`: Jeder Kasten, der
   UEBER dem Inhalt schwebt, braucht sie — bei eingeschalteter Glasoptik ist
   `--card` fast durchsichtig. Derselbe Merksatz wie beim Benutzermenue.
   ========================================================================== */
.kp-sprache{position:relative}
.kp-sprache > summary{
  list-style:none;cursor:pointer;
  display:inline-flex;align-items:center;gap:7px;
  height:42px;padding:0 12px;
  border:1px solid var(--line);border-radius:999px;
  background:var(--input-bg);color:var(--text);
}
.kp-sprache > summary::-webkit-details-marker{display:none}
.kp-sprache > summary::marker{content:""}
.kp-sprache > summary:hover{color:var(--brand);border-color:var(--brand)}
.kp-sprache > summary:focus-visible{outline:2px solid var(--brand);outline-offset:2px}
.kp-sprache[open] > summary{color:var(--brand);border-color:var(--brand)}
.kp-sprache-kurz{font-size:.8rem;font-weight:700;letter-spacing:.03em}
.kp-flagge{flex:0 0 auto;display:block;border-radius:50%}

.kp-sprache-klapp{
  position:absolute;right:0;top:calc(100% + 8px);z-index:60;
  min-width:190px;padding:6px;
  background:var(--kp-flyout);border:1px solid var(--line);border-radius:12px;
  box-shadow:0 14px 40px rgba(0,0,0,.22);
}
.kp-sprache-klapp form{margin:0}
.kp-sprache-klapp button{
  width:100%;display:flex;align-items:center;gap:10px;
  padding:9px 10px;border:0;border-radius:8px;
  background:none;color:var(--text);font:inherit;font-size:.92rem;
  cursor:pointer;text-align:left;
}
.kp-sprache-klapp button:hover{background:var(--hover)}
.kp-sprache-klapp button.aktiv{color:var(--brand);font-weight:600}

/* Auf dem Handy haengt das Fenster an der Kopfzeile statt am Knopf — dieselbe
   Regel wie bei Glocke und Benutzermenue, begruendet dort. */
@media (max-width:720px){
  .kp-sprache{position:static}
  .kp-sprache-klapp{left:12px;right:12px;min-width:0}
}

/* 🔴 Briefumschlag raus auf schmalen Geraeten (16.08.2026, Fund des Users:
   „durch die uebersetzung bricht es auf dem iphone auf eine dritte zeile
   um"). Mit der Sprachauswahl ist die Symbolreihe eine Stelle zu lang.

   Warum ausgerechnet der Umschlag: Er ist die einzige Abkuerzung der Reihe,
   die es doppelt gibt — „Nachrichten" steht im Seitenmenue, und die Glocke
   meldet neue Nachrichten ohnehin. Hell/Dunkel, Sprache, Status, Papierkorb
   und das Benutzermenue haben keinen zweiten Weg.
   ⚠️ `display:none` und nicht abblenden: Es geht um PLATZ, nicht um ein
   fehlendes Recht. Ein abgeblendetes Symbol braucht denselben Platz.

   🔴 NUR in der Verwaltung (03.09.2026, Ansage des Users: „mobil verschwindet
   im kundenportal auch der nachrichten button, in der verwaltung ist das ok
   aber im kundenportal muss er bleiben").

   Der Grund von damals traegt im Kundenportal nicht: Die Reihe ist dort
   kuerzer — kein Teamstatus, kein Papierkorb — und es bleibt Platz. Vor allem
   aber ist die Nachricht an uns fuer den Kunden der Hauptweg und nicht eine
   Abkuerzung unter vielen. */
@media (max-width:720px){
  body.kp:not(.kp-kundenportal) .kp-kopf-mail{display:none}
}

/* 🔴 Zahl der ungelesenen Nachrichten am Profilbild — NUR auf schmalen
   Geraeten (16.08.2026). Dort ist der Briefumschlag ausgeblendet; ohne diese
   Marke verschwaende der Hinweis mit ihm. Auf dem Desktop bleibt sie am
   Umschlag, zweimal dieselbe Zahl waere verwirrend.
   ⚠️ Sie sitzt am `<summary>`, das `position:relative` bekommt — nicht am
   Bild: Das Bild ist rund und beschnitten, eine Marke daran wuerde
   angeschnitten.

   ⚠️ Seit dem 03.09.2026 bleibt der Umschlag im KUNDENPORTAL auch mobil
   stehen. Dort ist diese Ersatzmarke deshalb nicht nur ueberfluessig, sondern
   falsch: Dieselbe Zahl staende zweimal im Kopf. */
.kp-benutzer-zahl{display:none}
@media (max-width:720px){
  body.kp-kundenportal .kp-benutzer-zahl{display:none}
  .kp-benutzer > summary{position:relative}
  .kp-benutzer-zahl{
    display:block;position:absolute;top:-2px;left:-4px;z-index:2;
    min-width:18px;padding:0 5px;border-radius:999px;
    background:var(--brand);color:#fff;
    font-size:.68rem;font-weight:700;line-height:18px;text-align:center;
    box-shadow:0 0 0 2px var(--kp-kopf-bg, var(--bg));
  }
}

/* --------------------------------------------------------------------------
   Einrichtungsassistent (Punkt 24, 17.08.2026)
   -------------------------------------------------------------------------- */

/* Die Schrittleiste. Bewusst KEINE `.kp-reiter`: Reiter sind gleichrangig und
   in beliebiger Reihenfolge erreichbar, Schritte haben eine Richtung und einen
   Stand. Sie teilen sich deshalb weder Aussehen noch Mechanik.

   🔴 Der Stand haengt an drei Klassen und nicht allein an der Farbe: `fertig`
   traegt ein Haekchen als Textzeichen, `hier` den Rahmen in der Markenfarbe,
   `offen` bleibt blass. Wer Rot und Gruen nicht unterscheidet, sieht trotzdem,
   wo er steht — dieselbe Ueberlegung wie bei den Erfolgsmeldungen. */
.kp-schritte{
  display:flex;flex-wrap:wrap;gap:8px;
  list-style:none;margin:0 0 22px;padding:0;
}
.kp-schritte li{
  display:flex;align-items:center;gap:8px;
  padding:8px 13px;
  background:var(--kp-tile-bg);
  border:1px solid var(--line);border-radius:999px;
  font-size:.88rem;color:var(--muted);
}
.kp-schritte li a{
  display:flex;align-items:center;gap:8px;
  color:inherit;text-decoration:none;
}
.kp-schritte li a:hover{color:var(--text)}
.kp-schritt-nr{
  display:inline-flex;align-items:center;justify-content:center;
  width:22px;height:22px;flex:0 0 22px;
  border-radius:999px;
  background:var(--line);color:var(--text);
  font-size:.78rem;font-weight:700;
}
.kp-schritte li.fertig{
  background:var(--kp-gut-soft);
  border-color:var(--kp-gut);
  color:var(--kp-gut-text);
}
.kp-schritte li.fertig .kp-schritt-nr{background:var(--kp-gut);color:#fff}
/* 🔴 Das Haekchen steht im MARKUP neben dem Namen, nicht als `::after` an der
   Nummer. Erster Anlauf war genau das — zusammen mit `font-size:0` an der
   Nummer, damit beides nicht uebereinanderliegt. Damit war die Nummer weg,
   und die ist der Weg zurueck („Schritt 2"), nicht bloss Zierrat. Ein Zeichen,
   das ein anderes verdraengt, ist keine zweite Unterscheidung. */
.kp-schritte li.hier{
  background:var(--brand-soft, var(--kp-tile-bg));
  border-color:var(--brand);
  color:var(--text);font-weight:600;
}
.kp-schritte li.hier .kp-schritt-nr{background:var(--brand);color:#fff}
.kp-schritte li.offen{opacity:.6}

/* Der Einrichtungslink des ersten Zugangs. Eigener Kasten und keine
   `.meldung`: Die ist eine Zeile Rueckmeldung, hier steht eine Adresse, die
   jemand herauskopieren soll — sie braucht Platz und einen Umbruch. */
.kp-linkkasten{
  margin:0 0 20px;padding:14px 16px;
  background:var(--kp-gut-soft);
  border:1px solid var(--kp-gut);border-radius:var(--radius-sm);
}
.kp-linkkasten code{
  display:block;padding:9px 11px;margin-top:4px;
  background:var(--kp-flyout);
  border:1px solid var(--line);border-radius:var(--radius-sm);
  font-size:.85rem;
}

/* --------------------------------------------------------------------------
   Rechnungsliste (18.08.2026)
   -------------------------------------------------------------------------- */

/* Mehrfachauswahl (26.08.2026) --------------------------------------------
   Ansage des Users: „mehrfach auswahl macht in jeder tabelle mehr sinn als
   checkboxen die direkt was machen". Bewusst allgemein benannt (`kp-stapel`,
   nicht `kp-rechnung-stapel`) — die naechste Liste bekommt dieselbe Leiste. */
.kp-stapel{
  display:flex;align-items:center;gap:12px;flex-wrap:wrap;
  margin:0 0 12px;padding:10px 14px;
  background:var(--kp-flyout);border:1px solid var(--line);border-radius:8px;
}
.kp-stapel[hidden]{display:none}
.kp-stapel-zahl{font-weight:600}
/* Solange nichts gewaehlt ist, sind die Knoepfe gesperrt — ohne JavaScript
   greift das nicht, dort verhindert der Handler den Leerlauf. */
.kp-stapel button[disabled]{opacity:.5;cursor:not-allowed}

/* ⚠️ `.kp-haken` wird von der Rechnungsliste seit dem 26.08.2026 NICHT mehr
   benutzt — dort steht jetzt ein echtes Auswahlkaestchen. Die Regeln bleiben
   stehen, weil die Klasse an anderer Stelle noch vorkommt; wer sie aufraeumen
   will, muss vorher das ganze Projekt danach absuchen. */
.kp-haken{
  width:22px;height:22px;padding:0;
  display:inline-flex;align-items:center;justify-content:center;
  border:2px solid var(--line);border-radius:6px;
  background:var(--kp-flyout);color:var(--brand);
  font-size:.9rem;font-weight:800;line-height:1;cursor:pointer;
}
.kp-haken:hover{border-color:var(--brand)}
.kp-haken.an{background:var(--brand);border-color:var(--brand);color:#fff}
/* Tastaturbedienung muss sichtbar bleiben — der Knopf traegt sonst keinen
   eigenen Rahmen, an dem man den Fokus erkennen wuerde. */
.kp-haken:focus-visible{outline:2px solid var(--brand);outline-offset:2px}

/* Ueberfaellige Zeile: ein Streifen am linken Rand statt einer Flaechenfarbe.
   ⚠️ KEIN eingefaerbter Hintergrund ueber die ganze Zeile — der zieht den Text
   mit und geht auf Kosten der Lesbarkeit; dieselbe Ueberlegung wie bei den
   beendeten Karten der Kundenansicht. */
/* ⚠️ `--warn` gibt es im Portal nicht — nur `--danger`. Ueberfaellig ist
   aber kein Fehler, sondern eine Faelligkeit, deshalb der Markenton
   statt Rot. Rot bliebe fuer echte Stoerungen reserviert. */
.kp-zeile-warn td:first-child{box-shadow:inset 3px 0 0 var(--brand)}

/* Die Positionen unter einer Rechnung. Schmal gesetzt, damit die Zeile trotz
   mehrerer Posten nicht auseinanderfaellt. */
.kp-liste-schmal{margin:0;padding:0;list-style:none}
.kp-liste-schmal li{padding:1px 0;font-size:.92rem}
.kp-liste-schmal li + li{border-top:1px dashed var(--line)}

/* In der Liste der zu schreibenden Rechnungen steht an jeder Position, ob der
   Leistungszeitraum an die Bezeichnung kommt (27.08.2026). Der Regelfall bleibt
   leise; die Ausnahme wird eingerahmt, damit sie beim Ueberfliegen auffaellt —
   sie ist es, die man vor dem Uebertragen sehen will. */
.kp-ohne-zeitraum{
  color:var(--warn-text,#8a5a00);
  background:var(--warn-bg,rgba(240,160,0,.10));
  border-radius:4px;padding:0 6px;
}
.kp-liste-schmal .muted{margin-left:6px;font-size:.85rem}

/* Knopfleiste ueber dem Titel einer Detailseite (18.08.2026, Meldung des Users:
   „bei sehr langen titeln brechen die buttons um").
   🔴 Eigene Zeile statt neben der Ueberschrift: Ein Accountname kann beliebig
   lang werden, und in derselben Zeile zerfiel die Leiste dann in einzelne
   umgebrochene Knoepfe. Getrennt ist die Breite des Titels egal.
   ⚠️ `flex-wrap` bleibt trotzdem — auf dem Telefon passen fuenf Knoepfe auch in
   einer eigenen Zeile nicht nebeneinander. Der Unterschied ist, dass sie dann
   ALS GRUPPE umbrechen und nicht mehr um den Titel herum. */
.kp-kopfleiste{
  display:flex;align-items:center;gap:10px;flex-wrap:wrap;
  margin-bottom:14px;
}
.kp-kopfleiste form{margin:0}

/* Sichtwahl ueber einer Liste — „Alle / Wiederkehrend / Einmalig" (18.08.2026).
   Dieselbe Sprache wie die Filterknoepfe auf der Hinweisseite: Der gewaehlte
   Knopf traegt den Markenton, die uebrigen bleiben Umrisse.
   ⚠️ Das ist bewusst KEIN Spaltenfilter. Die Trichter im Tabellenkopf
   verfeinern, was man sieht; diese Leiste wechselt die SICHT. Zwei
   Bedienelemente, die man nicht verwechseln soll, duerfen nicht gleich
   aussehen. */
.kp-sichtwahl{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:14px}
.kp-sichtwahl .btn.aktiv{
  border-color:var(--brand);color:var(--brand);background:var(--brand-soft);
}
.kp-sichtwahl .kp-reiter-zahl{margin-left:6px}

/* Kennzahlenzeile ueber einer Arbeitsliste (Rechnungen).
   🔴 Der erklaerende Satz steht UNTER den Zahlen, nicht daneben (Ansage des
   Users, 18.08.2026). Rechts neben „8 offen · 818,87 € gesamt" konkurriert er
   mit ihnen um dieselbe Zeile und dieselbe Aufmerksamkeit — dabei ist das eine
   die Auskunft und das andere ihre Erlaeuterung. */
.kp-kopfzahlen{
  display:flex;align-items:center;gap:10px;flex-wrap:wrap;
  margin:0 0 18px;padding:12px 16px;
  background:var(--kp-flyout);border:1px solid var(--line);
  border-radius:var(--radius);
}
.kp-kopfzahlen > small{flex:0 0 100%;font-size:.8rem;line-height:1.45;margin-top:2px}

/* Ein Knopf in der Sichtwahl, der von sich aus auffallen soll — „Überfällig",
   solange dort etwas steht. Warnton statt Markenton: Der Markenton markiert die
   GEWAEHLTE Sicht, hier geht es um den Inhalt.
   ⚠️ Der aktive Zustand gewinnt: Wer die Sicht offen hat, sieht sie als
   gewaehlt, nicht als Warnung. Deshalb steht `.aktiv` in der Datei danach. */
.kp-sichtwahl .btn.kp-warnton{
  border-color:#e0a12a;color:#c07800;
}
.kp-sichtwahl .btn.kp-warnton.aktiv{
  border-color:var(--brand);color:var(--brand);background:var(--brand-soft);
}

/* --------------------------------------------------------------------------
   Barrierefreiheit: hoher Kontrast (18.08.2026)
   --------------------------------------------------------------------------
   Ansage des Users: „im LMS haben wir fuer die barrierefreiheit noch ,hoher
   kontrast' der fehlt hier im crm noch."

   🔴 Ueber die FARBTOKEN, nicht ueber Einzelregeln je Bauteil. Das Portal
   zeichnet alles aus `--text`, `--muted`, `--line`, `--card` und `--bg` — wer
   diese fuenf verschaerft, erreicht jede Karte, jede Tabelle und jedes Feld
   auf einmal. Eine Liste einzelner Selektoren waere ab der naechsten neuen
   Seite unvollstaendig.

   ⚠️ Die Markenfarbe bleibt unangetastet: Sie ist das Erkennungszeichen des
   Mandanten (Whitelabel). Verschaerft werden Text, Linien und Flaechen.
   -------------------------------------------------------------------------- */
html[data-kontrast="hoch"]{
  --text:#000000;
  --muted:#333333;
  --line:#4a4a4a;
  --card:#ffffff;
  --bg:#f4f4f4;
  --input-bg:#ffffff;
}
html[data-kontrast="hoch"][data-theme="dark"]{
  --text:#ffffff;
  --muted:#d4d4d4;
  --line:#9a9a9a;
  --card:#0a0a0a;
  --bg:#000000;
  --input-bg:#0a0a0a;
}

/* Raender kraeftiger — Farbe allein traegt bei schwachem Sehen nicht. */
html[data-kontrast="hoch"] .karte,
html[data-kontrast="hoch"] .kp-kachel,
html[data-kontrast="hoch"] table.tabelle{border:2px solid var(--line)}
html[data-kontrast="hoch"] .btn{border-width:2px;font-weight:600}
html[data-kontrast="hoch"] input,
html[data-kontrast="hoch"] select,
html[data-kontrast="hoch"] textarea{border-width:2px}

/* 🔴 Verweise werden unterstrichen. Ein Link, der sich nur durch die Farbe
   vom Text unterscheidet, ist fuer Farbfehlsichtige kein Link.
   ⚠️ Nicht bei Knoepfen und Menuepunkten — die sind schon als Flaeche
   erkennbar, und die Unterstreichung machte sie unruhig. */
html[data-kontrast="hoch"] a{text-decoration:underline}
html[data-kontrast="hoch"] a.btn,
html[data-kontrast="hoch"] a.kp-kachel,
html[data-kontrast="hoch"] .kp-reiter a,
html[data-kontrast="hoch"] .kp-seite a,
html[data-kontrast="hoch"] a.kp-sort{text-decoration:none}

/* Der Knopf selbst: gedrueckt = Markenfarbe, damit man den Zustand sieht. */
.kontrast-toggle.an{color:var(--brand);border-color:var(--brand)}

/* Sichtbarer Fokusring — Tastaturbedienung darf nicht raten lassen. */
html[data-kontrast="hoch"] :focus-visible{
  outline:3px solid var(--brand);outline-offset:2px;
}

/* Interne Notiz der Leistung im Zuweisungsformular (18.08.2026).
   Abgesetzt, damit sie nicht wie eine Feldbeschriftung wirkt — sie ist eine
   Information zum Nachschlagen, kein Hinweis zur Eingabe. */
.kp-leist-notiz{
  margin:8px 0 0;padding:8px 10px;
  border-left:3px solid var(--brand);
  background:var(--kp-flyout);
  font-size:.86rem;line-height:1.45;white-space:pre-line;
}

/* Punkt im Handlungsbedarf ausblenden (18.08.2026). Zurueckhaltend: Das × soll
   erreichbar sein, aber nicht mit der Zahl daneben um Aufmerksamkeit ringen. */
.kp-tuwas-weg{
  border:0;background:none;padding:0 2px;cursor:pointer;
  color:var(--muted);font-size:1.05rem;line-height:1;opacity:.55;
}
.kp-tuwas-weg:hover{opacity:1;color:var(--text)}
.kp-tuwas-weg:focus-visible{outline:2px solid var(--brand);outline-offset:2px;border-radius:4px}

/* Knopf, der wie ein dezenter Verweis aussieht — fuer Aktionen, die per POST
   laufen muessen (CSRF), aber keine Aufmerksamkeit verlangen.
   🔴 Vorbild ist „⚙ Ansicht anpassen" auf dem LMS-Dashboard (Ansage des Users,
   18.08.2026: „kriegen wir den Link etwas kleiner und dezenter hin? im LMS
   haben wir das auch schoen dezent"). Dieselben Werte: 0,78 rem, gedaempfte
   Farbe, erst beim Ueberfahren Markenton mit leiser Flaeche.
   ⚠️ KEINE Unterstreichung im Ruhezustand — sie machte den Knopf zum zweiten
   Blickfang neben den Zahlen darueber, und genau das war der Fund. */
.kp-textknopf{
  border:0;background:none;cursor:pointer;
  font-family:inherit;font-size:.78rem;line-height:1.4;
  color:var(--muted);text-decoration:none;
  display:inline-flex;align-items:center;gap:3px;
  padding:2px 6px;border-radius:4px;
  transition:color .15s, background .15s;
}
.kp-textknopf:hover{color:var(--brand);background:var(--hover,var(--kp-flyout))}
.kp-textknopf:focus-visible{outline:2px solid var(--brand);outline-offset:2px}

/* Eigene Zeile fuer den Weg zurueck, rechtsbuendig unter dem Erklaertext. */
.kp-tuwas-zurueck{display:flex;justify-content:flex-end;margin:6px 0 0}


/* ---------------------------------------------------------------------------
   Abweichende Rechnungsadresse (20.08.2026)
   ---------------------------------------------------------------------------
   🔴 Ein- und Ausblenden OHNE JavaScript. Die CSP des Portals blockt
   Inline-Skripte (Befund A″-8, 16.08.2026), und für einen einzigen Haken
   lohnt kein Eintrag in `portal.js`.

   ⚠️ Der Geschwister-Selektor `~` verlangt, dass `.kp-abw` NACH dem Label
   mit dem Kästchen steht und beide DASSELBE Elternelement haben. Wer den
   Block später in ein weiteres <div> wickelt, schaltet ihn damit still ab.
   Ein `:has()` wäre unempfindlicher, wird aber von älteren Browsern nicht
   verstanden — und dort wäre das Feld dann dauerhaft unsichtbar. */
.kp-abw { display: none; }
.kp-abw-schalter:has(input:checked) ~ .kp-abw { display: block; }

/* Rückfall für Browser ohne `:has()`: Dort bleibt der Block immer sichtbar.
   Sichtbar zu viel ist harmlos, unsichtbar zu wenig wäre ein verlorenes
   Formularfeld. */
@supports not (selector(:has(*))) {
  .kp-abw { display: block; }
}


/* ---------------------------------------------------------------------------
   Blättern in der Detailansicht (20.08.2026)
   ---------------------------------------------------------------------------
   🔴 Die Klasse heißt `kp-satzblaettern` und NICHT `kp-blaettern`. Letztere
   gehört der Seitenblätterung UNTER den Listen. Als hier zuerst derselbe Name
   stand, machte `display:flex` aus deren <span> einen Flex-Kasten — „‹ Zurück"
   und „Weiter ›" standen daraufhin versetzt. Der User hat es sofort gesehen.
   Vor einem neuen Klassennamen im Stylesheet nachsehen, ob es ihn schon gibt.

   ⚠️ Der abgeblendete Knopf ist ein <span> und kein <button disabled>: Er soll
   den Platz halten, damit „Nächster" nicht springt, sobald man am Ende der
   Liste ankommt. */
.kp-satzblaettern {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 0 0 14px;
  flex-wrap: wrap;
}

/* Was die Seite selbst in die Zeile hängt — beim Account der zweite
   „Speichern" (27.08.2026). `margin-left: auto` schiebt ihn nach rechts, ohne
   dass „vorheriger / nächster" ihre Stelle verlieren.

   ⚠️ Beim Umbruch auf schmalen Bildschirmen fällt das `auto` weg und der Knopf
   steht links in der neuen Zeile — sonst klebte er am rechten Rand einer
   sonst leeren Zeile und sähe aus, als gehöre er nicht dazu. */
.kp-satzblaettern-zusatz { margin-left: auto; }

@media (max-width: 560px) {
  .kp-satzblaettern-zusatz { margin-left: 0; }
}


/* ---------------------------------------------------------------------------
   Export-Knopf über den Listen (20.08.2026)
   ---------------------------------------------------------------------------
   Ansage des Users: „der csv button klebt an der liste, kriegen wir den etwas
   höher und auf die rechte seite der listen?"

   ⚠️ `float` und nicht Flex: Der Knopf steht im Markup als einzelnes Element
   zwischen Steuerung und Tabelle, ohne umschließenden Kasten. Ein Flex-Elter
   müsste in jede der über zwanzig Listen eingezogen werden; `float: right`
   holt ihn ohne Eingriff in den Seiten nach rechts. Das `clear` an der Tabelle
   darunter verhindert, dass sie unter ihn rutscht. */
/* ⚠️ KEIN `float` mehr (20.08.2026): Der Knopf steht seit heute IM Flex-Kasten
   der Steuerungszeile, ausgegeben von `Liste::steuerung()`. Ein Float daneben
   hätte ihn wieder herausgelöst. */
.kp-export {
  margin: 0;
}

/* ⚠️ Gemessen statt geschätzt (20.08.2026): Mit »1em« war das Symbol 14×14 px
   und der ganze Knopf 37×25 — in der Größe ist ein Blatt mit Pfeil nicht mehr
   zu deuten. Feste 18 px und ein quadratischer Knopf: gut sichtbar und auf
   dem Touchscreen zu treffen. Der Knopf trägt nur noch ein Symbol, deshalb
   braucht er keine Textbreite mehr. */
.kp-export {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 34px;
  min-height: 34px;
  padding: 6px;
}

/* Die Größe kommt aus `symbolSvg('export', '18px')` — sie steht inline und
   ließe sich von hier ohnehin nicht überschreiben. */

/* Trägt der Knopf ausnahmsweise doch eine Beschriftung (zwei Listen auf einer
   Seite), darf er wieder in die Breite gehen. */
.kp-export:not(:has(.sr-only)) {
  min-width: 0;
  padding: 5px 11px;
  gap: 6px;
}


/* ==========================================================================
   Listenansicht-Overlay (20.08.2026)
   --------------------------------------------------------------------------
   Hintergrund und Fenster kommen aus dem Auswahl-Overlay (`kp-wahl-*`) — es
   ist derselbe Dialog, nur mit anderem Inhalt. Zwei eigene Sätze Regeln für
   dasselbe Fenster wären die Stelle, an der eines Tages nur noch eines von
   beiden zur Glasoptik passt.
   ========================================================================== */
.kp-ansicht-fenster{width:min(520px,100%);max-height:min(680px,90vh)}

/* Der einzige Bereich, der scrollt: Kopf und Fuß bleiben stehen, damit
   „Speichern" bei einer Liste mit fünfzehn Spalten erreichbar bleibt. */
.kp-ansicht-inhalt{overflow:auto;flex:1 1 auto;padding:16px 20px}
.kp-ansicht-hinweis{margin:0 0 12px;font-size:.86rem}

.kp-ansicht-liste{list-style:none;margin:0;padding:0;display:flex;
  flex-direction:column;gap:6px}

.kp-ansicht-zeile{
  display:flex;align-items:center;gap:12px;
  padding:8px 10px;
  border:1px solid var(--line);border-radius:var(--radius);
  background:var(--card);
}
.kp-ansicht-name{display:flex;align-items:center;gap:10px;flex:1 1 auto;
  margin:0;cursor:pointer;min-width:0}
.kp-ansicht-name span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* Eine abgewählte Spalte bleibt lesbar, tritt aber zurück — sonst sieht die
   Zeile aus wie ein Fehler und nicht wie eine Entscheidung. */
.kp-ansicht-name:has(input:not(:checked)) span{opacity:.5}

.kp-ansicht-pfeile{display:flex;gap:4px;flex:0 0 auto}
/* ⚠️ Feste Breite: Ohne sie werden die Knöpfe von „↑" und „↓" verschieden
   breit, und die Zeilen stehen um ein bis zwei Pixel versetzt. */
.kp-ansicht-pfeile .btn{min-width:32px;padding-left:0;padding-right:0;
  text-align:center}
.kp-ansicht-pfeile .btn[disabled]{opacity:.35;cursor:default}

.kp-ansicht-sortierung{
  display:flex;gap:16px;flex-wrap:wrap;
  margin-top:18px;padding-top:16px;border-top:1px solid var(--line);
}
.kp-ansicht-sortierung label{display:flex;flex-direction:column;gap:4px;
  flex:1 1 180px;font-size:.9rem}
.kp-ansicht-sortierung select{width:100%;max-width:none}

/* Der Fuß trägt links „Zurücksetzen", rechts Abbrechen und Speichern —
   `kp-wahl-knoepfe` bringt das `margin-left:auto` mit. */
.kp-ansicht-fenster .kp-wahl-fuss{gap:10px}

/* ---------------------------------------------------------------------------
   Die beiden Symbolknöpfe in der Steuerungszeile (21.08.2026)
   ---------------------------------------------------------------------------
   🔴 Sie standen unterschiedlich hoch: 34 px der Export, 29,6 px das
   Zahnrad (Ansage des Users). Der Grund ist die Bauart — der Export ist ein
   `<a>`, das Zahnrad ein `<button>`, und beide bekommen von Browser und
   Stylesheet verschiedene Polsterung. Nebeneinander in einer Zeile fällt schon
   ein Pixel auf.

   ⚠️ Deshalb feste Maße statt Polsterung: Zwei quadratische Flächen von
   34×34 sind unabhängig davon gleich groß, wie das Symbol darin gerechnet
   wird. Eine Angleichung über `padding` hält nur, solange keiner der beiden
   Knöpfe je eine andere Grundregel erbt.

   ⚠️ NICHT für die beschriftete Fassung (`kp-export-text`): Wo zwei Listen
   auf einer Seite stehen, tragen die Knöpfe einen Namen, und 34 px schnitten
   ihn ab. */
.kp-listenkopf .kp-export:not(.kp-export-text),
.kp-listenkopf .kp-ansicht-knopf{
  display:inline-flex;align-items:center;justify-content:center;
  width:34px;height:34px;padding:0;flex:0 0 auto;
}

.kp-ansicht-knopf{display:inline-flex;align-items:center;gap:6px}
.kp-ansicht-knopf svg,
.kp-listenkopf .kp-export svg{width:18px;height:18px}

@media (max-width: 640px){
  .kp-ansicht-fenster{width:100%;max-height:none;height:100%;border-radius:0}
}

/* ==========================================================================
   Listen als Kaertchen auf dem Telefon (21.08.2026)

   Ansage des Users vom 20.08.: „die mobile darstellung der listen muss auch
   nochmal ueberarbeitet werden. ich denke wir fahren da mit einer anderen
   darstellung besser" — ausdruecklich eine ANDERE Darstellung, keine schmalere
   Tabelle.

   🔴 Nur Tabellen mit `.kp-liste-karten`. Die Klasse setzt `portal.js`, und zwar erst
   nachdem es die Zellen beschriftet hat. Eine Tabelle ohne Beschriftung wuerde
   hier zu einer Saeule nackter Werte — schlechter als die Tabelle, die sie
   vorher war.

   ⚠️ Der Name ist mit Bedacht `kp-liste-karten` und NICHT `kp-karten`: Das gab
   es schon (`display:grid` fuer die Leistungskaertchen des Kunden, Zeile 573).
   Beim Bauen habe ich genau das uebersehen — die Tabelle bekam dadurch am
   DESKTOP `display:grid`, und Kopf, Koerper und Summenzeile lagen uebereinander.
   Aufgefallen ist es nur, weil ich die Desktopansicht gegengeprueft habe; auf
   dem Telefon sah alles richtig aus. **Vor einer neuen Klasse einmal danach
   greppen.**

   ⚠️ 720 px und nicht 480: Eine Liste mit neun Spalten ist auf einem Tablet
   quer schon nicht mehr lesbar. Wer bis zur Telefonbreite wartet, laesst den
   unbrauchbaren Zustand genau dort stehen, wo er am haeufigsten auftritt.
   ========================================================================== */
@media (max-width:720px){

  /* Der Rahmen gehoert jetzt an die Kaertchen, nicht mehr um die Tabelle. Der
     waagerechte Bildlauf entfaellt — genau der war das Problem. */
  .table-wrap:has(table.kp-liste-karten){
    overflow:visible;border:0;background:none;box-shadow:none;border-radius:0;
  }

  table.tabelle.kp-liste-karten,
  table.tabelle.kp-liste-karten tbody,
  table.tabelle.kp-liste-karten tbody > tr,
  table.tabelle.kp-liste-karten tbody > tr > td{display:block;width:auto}

  /* 🔴 Der Kopf wird NICHT ausgeblendet, sondern zur Bedienleiste.
     Blendete man ihn aus, waeren Sortierung und Spaltenfilter auf dem Telefon
     ersatzlos weg — beides steckt in den Kopfzellen. Uebrig bleiben nur die
     Zellen, die wirklich etwas zu bedienen haben; die reinen Titel fallen raus,
     ihre Beschriftung steht ja jetzt im Kaertchen. */
  table.tabelle.kp-liste-karten thead{display:block}
  table.tabelle.kp-liste-karten thead tr{
    display:flex;flex-wrap:wrap;gap:6px;
    padding:0 0 10px;border-bottom:1px solid var(--line);margin-bottom:12px;
  }
  table.tabelle.kp-liste-karten thead th{display:none;border:0;padding:0}
  /* Als abgesetzte Plaettchen und nicht als Fliesstext: Nebeneinander gesetzt
     verschwimmen „BEZEICHNUNG GLAEUBIGER BETRAG" zu einer Zeile, in der man
     nicht sieht, was ein einzelnes Bedienelement ist. */
  table.tabelle.kp-liste-karten thead th:has(a.kp-sort),
  table.tabelle.kp-liste-karten thead th:has(details){
    display:block;font-size:.72rem;
    padding:5px 9px;border:1px solid var(--line);border-radius:999px;
    background:var(--kp-tile-bg);
    /* 🔴 `!important` mit Grund (Fund des Users am Telefon, 21.08.2026:
       „bei den Sortier Feldern oben ragt ‚nr' aus seiner bubble'').
       Schmale Spalten tragen inline `style="width:1%"` — der uebliche
       Tabellenkniff fuer „so schmal wie moeglich". In einer Tabelle heisst das
       „nimm die Mindestbreite", als Flex-Element aber ein Prozent der
       Zeilenbreite: Das Plaettchen war 20 px breit, sein Inhalt 37, und „Nr."
       stand rechts daneben im Freien. Ein Inline-Stil laesst sich nur so
       ueberschreiben.
       ⚠️ `flex:0 0 auto` dazu, damit kein Plaettchen unter seinen Inhalt
       gedrueckt wird — umgebrochen wird ohnehin (`flex-wrap:wrap`). */
    width:auto !important;flex:0 0 auto;white-space:nowrap;
  }

  /* Ein Datensatz, ein Kaestchen. */
  table.tabelle.kp-liste-karten tbody > tr{
    border:1px solid var(--line);border-radius:var(--radius);
    background:var(--card);box-shadow:var(--shadow);
    padding:12px 14px;margin-bottom:12px;
  }
  /* ⚠️ Der Zeilen-Hover aus der Tabellenansicht muss hier weg: Auf dem Telefon
     gibt es keinen Zeiger, und die Faerbung bliebe nach einer Beruehrung
     stehen — dann sieht ein beliebiges Kaertchen aus wie ausgewaehlt. */
  table.tabelle.kp-liste-karten tbody > tr:hover{background:var(--card)}

  /* Beschriftung links, Wert rechts. Zwei Spalten und kein Umbruch untereinander:
     Ein Kaertchen mit acht Angaben waere sonst sechzehn Zeilen hoch. */
  /* 🔴 Beschriftung in einem festen linken Streifen, NICHT als Rasterspalte
     (Fund am Telefon, 21.08.2026). Mit `display:grid` wird JEDES Kind der Zelle
     ein eigenes Rasterfeld — eine Zelle mit zwei Kennzeichen („Kunde",
     „Partner") warf das zweite in die naechste Zeile unter die Beschriftung.
     Als Block fliesst der Zellinhalt wieder normal: ein Wert, zwei Kennzeichen,
     ein Auswahlfeld, ein ganzes Formular — alles gleich. */
  /* 🔴 Beschriftung ÜBER dem Wert, nicht daneben (Ansage des Users am Telefon,
     21.08.2026: „die email adresse rutscht raus, vielleicht machen wir Bezug
     etc. nicht neben den inhalt sondern als überschrift darüber").

     Der linke Streifen war 10em breit und nahm auf einem 390-px-Telefon rund
     40 % der Karte. Was übrig blieb, reichte für „Christian Funck", aber nicht
     für `bestellungen@wollberg.de` — die Adresse lief über den Rand, und
     mehrzeilige Texte brachen nach drei Wörtern um. Über dem Wert steht die
     Beschriftung einmal kurz, und der Wert bekommt die GANZE Kartenbreite.

     ⚠️ Die Karte wird dadurch höher. Das ist der Tausch: lieber scrollen als
     raten, was da abgeschnitten steht. */
  table.tabelle.kp-liste-karten tbody > tr > td{
    display:block;
    padding:7px 0 0;border:0;text-align:left;
  }
  table.tabelle.kp-liste-karten tbody > tr > td[data-spalte]{
    /* 🔴 Lange Werte ohne Leerzeichen brechen um, statt herauszulaufen. Eine
       E-Mail-Adresse hat keine Trennstelle, an der der Browser von sich aus
       umbräche — `anywhere` ist hier kein Schönheitsfehler, sondern die
       einzige Stelle, an der er es darf. */
    overflow-wrap:anywhere;
  }
  table.tabelle.kp-liste-karten tbody > tr > td[data-spalte]::before{
    content:attr(data-spalte);
    display:block;margin-bottom:1px;
    /* ⚠️ 10em und nicht 8: Die Einrueckung der Zelle betraegt 8,5em ihrer
       eigenen (groesseren) Schrift — in der kleineren Schrift der Beschriftung
       sind das rund 10,5em. Bei 8em brach „Portalzugang" mitten im Wort um
       („PORTALZUGA / NG"), obwohl daneben Platz war. */

    color:var(--muted);font-size:.74rem;letter-spacing:.04em;
    text-transform:uppercase;font-weight:700;line-height:1.4;
    /* Lange Beschriftungen brechen im Streifen um, statt in den Wert zu
       laufen — „Portalzugang" passt sonst nicht. */
    overflow-wrap:anywhere;
    /* ⚠️ Eigene Ausrichtung: Geldspalten tragen `style="text-align:right"`
       direkt im Markup, und ein Inline-Stil schlaegt jeden Selektor. Ohne
       diese Zeile rutscht die BESCHRIFTUNG mit nach rechts und klebt am Wert.
       Der Wert selbst darf rechts bleiben — Betraege liest man rechtsbuendig. */
    text-align:left;
  }

  /* Die Ueberschrift des Kaertchens: volle Breite, groesser, ohne Beschriftung.
     Welche Zelle das ist, entscheidet `portal.js` — es ist die erste MIT
     Beschriftung, nicht die erste ueberhaupt. */
  table.tabelle.kp-liste-karten tbody > tr > td.kp-karte-titel{
    font-size:1.02rem;font-weight:600;line-height:1.35;
    padding:0 0 8px;margin-bottom:6px;border-bottom:1px solid var(--line);
  }
  table.tabelle.kp-liste-karten tbody > tr > td.kp-karte-titel::before{content:none}
  /* Der Nachsatz unter dem Titel (Notiz, Belegnummern) bleibt klein und leise. */
  table.tabelle.kp-liste-karten tbody > tr > td.kp-karte-titel small{
    display:block;margin-top:4px;font-weight:400;
  }

  /* Zellen ohne Beschriftung sind die festen Spalten: vorn der Statuspunkt,
     hinten die Knoepfe. Sie bekommen die volle Breite statt einer leeren
     Beschriftungsspalte. */
  /* Zellen ohne Beschriftung sind die festen Spalten: vorn der Statuspunkt,
     hinten die Knöpfe. */
  table.tabelle.kp-liste-karten tbody > tr > td:not([data-spalte]){
    padding-top:4px;
  }
  /* Die Knopfspalte sitzt am Fuss des Kaertchens, abgesetzt. */
  table.tabelle.kp-liste-karten tbody > tr > td:last-child:not([data-spalte]){
    margin-top:8px;padding-top:10px;border-top:1px solid var(--line);
  }

  /* Zeilen ohne Spaltenstruktur — „keine Eintraege", Zwischensummen — bleiben
     Tabellenzeilen: `portal.js` hat sie bewusst nicht beschriftet. */
  table.tabelle.kp-liste-karten tbody > tr:not(:has(td[data-spalte])){
    border:0;background:none;box-shadow:none;padding:0;
  }

  /* Die Summenzeile unter der Tabelle traegt ihre eigene Struktur. */
  table.tabelle.kp-liste-karten tfoot{display:block}
  table.tabelle.kp-liste-karten tfoot tr{display:flex;justify-content:space-between;gap:10px}
  table.tabelle.kp-liste-karten tfoot td{border:0;padding:8px 0}
}

/* ==========================================================================
   Mobil: bis zu den Daten scrollen (21.08.2026)
   --------------------------------------------------------------------------
   Ansage des Users: „mobile muss ich erst mal scrollen bis daten kommen,
   kriegen wir das (auf allen ansichten) kompakter hin? ggf. die bubbles als
   dropdown und alles etwas näher beieinander."

   Gemessen an der Accountliste bei 390 px Breite, vorher **673 px** bis zur
   ersten Datenzeile:

     Tabellenkopf   117 px   ← überflüssig, siehe unten
     Listenkopf     124 px   ← fünf Elemente untereinander
     Filterreihe     98 px   ← drei Reihen Bubbles
     Suchleiste      85 px   ← Feld und Knopf übereinander
     Untertitel      79 px

   🔴 Alles hier gilt NUR unter 720 px. Am Schreibtisch ändert sich nichts —
   dort ist Platz, und die Knopfreihe war eine ausdrückliche Entscheidung
   („das system soll wie aus einem guss wirken", 21.08.2026).
   ========================================================================== */
@media (max-width:720px){
  /* Eine Groesse fuer alle Knoepfe, die untereinander buendig stehen sollen. */
  :root{--kp-mobil-knopf:96px;--kp-mobil-knopfhoehe:38px}

  /* ---- 1. Tabellenkopf in der Kartenansicht: weg -----------------------
     🔴 Der größte Einzelposten und schlicht ein Fehler: In der Kartenansicht
     trägt JEDE Zelle ihre Beschriftung selbst (`td::before` aus `data-spalte`).
     Der Tabellenkopf stand daneben und wiederholte dieselben Wörter — als
     Block untereinander, 117 px hoch.
     ⚠️ Damit wandern Sortierpfeile und Trichter am Handy in die Ansicht
     hinter dem Zahnrad. Das Filterband über der Liste bleibt sichtbar, ein
     gesetzter Filter lässt sich also weiterhin sehen und entfernen. */
  table.tabelle.kp-liste-karten > thead{display:none}

  /* ---- 2. Kopfbereich der Seite enger ---------------------------------- */
  .kp-titel{font-size:1.5rem;margin-bottom:4px}
  /* Der Untertitel erklärt die Seite — das liest man einmal. Jeden Aufruf
     daran vorbeizuscrollen kostet mehr, als er einbringt. */
  .kp-unter{display:none}
  .kp-inner > .kp-aktionen{margin-bottom:10px}
  /* Ein Knopf über die volle Breite sieht nach Formularabschluss aus; hier
     ist er ein Einstieg neben anderen. */
  .kp-aktionen .btn{width:auto}

  /* ---- 3. Filterreihe als Auswahlfeld ----------------------------------
     Das Feld baut `portal.js` aus derselben Knopfreihe (Beschriftung + Zahl).
     Beide stehen im Markup, die Breite entscheidet, welches man sieht — so
     muss beim Wechsel der Bildschirmgröße nichts umgebaut werden. */
  .kp-sichtwahl{display:none}
  .kp-sichtwahl-klein{display:block;margin:0 0 14px}
  .kp-sichtwahl-klein select{width:100%;max-width:none}
  /* Und das Feld, das in die Suchleiste gewandert ist — dort volle Breite,
     die Leiste bricht am Handy ohnehin um. */
  .kp-suchleiste .kp-sichtwahl-feld{display:block;width:100%;max-width:none}

  /* ---- 4. Suchleiste einzeilig ------------------------------------------
     ⚠️ `base.css` setzt `input{width:100%}` — deshalb rutschte der Knopf in
     die nächste Zeile. Das Feld darf schrumpfen, der Knopf nicht. */
  .kp-suchleiste{gap:8px;margin-bottom:12px}
  .kp-suchleiste input[type=text],
  .kp-suchleiste input[type=search],
  .kp-suchleiste input:not([type]){flex:1 1 0;min-width:0;width:auto}
  .kp-suchleiste .btn{flex:0 0 auto}

  /* ---- 5. Listenkopf zusammenrücken ------------------------------------
     Zählzeile, Zeilenzahl, Export, Zahnrad und Blätterknöpfe standen
     untereinander. Sie gehören nebeneinander und dürfen umbrechen. */
  .kp-listenkopf{gap:8px;margin-bottom:10px;align-items:center}
  /* ⚠️ Die Zaehlzeile bekommt eine EIGENE Zeile. Zwischenzeitlich teilte sie
     sich die Reihe mit den Bedienelementen — das ging nur, solange die beiden
     Knoepfe 34 px schmal waren. Seit sie so breit sind wie der Suchknopf
     (96 px), passt die Reihe nicht mehr: Zaehlzeile + Zeilenwahl + zwei
     Knoepfe sind ueber 430 px. Dann bricht sie an einer beliebigen Stelle um,
     und die zwei Knoepfe stehen NICHT mehr nebeneinander — auf den Tickets
     landete das Zahnrad allein in der naechsten Zeile, 310 px vom rechten
     Rand. Mit einer festen Aufteilung ist die Lage auf jeder Seite dieselbe. */
  .kp-listenkopf > .muted{flex:0 1 auto;font-size:.82rem}
  .kp-listenkopf .kp-pro{margin:0}
  /* 🔴 Blaetterknoepfe OBEN weg: Unter der Liste stehen dieselben noch
     einmal (`Liste::steuerungUnten`). Am Schreibtisch sind zwei Stellen
     bequem, am Handy kosten sie eine ganze Reihe, bevor die erste Zeile
     kommt — und wer blaettern will, ist ohnehin am Ende der Liste. */
  .kp-listenkopf .kp-blaettern{display:none}
  /* ---- Knopfbreiten angleichen (Ansage des Users, 21.08.2026) ----------
     „toll waere es wenn der zahnrad button und der export button genau so
     breit waeren wie suchen und sie buendig mit dem suchen button rechts
     abschliessen."

     🔴 Ueber eine gemeinsame Groesse, NICHT ueber eine abgeschriebene
     Zahl: „Suchen" ist im Deutschen 91 px breit, im Englischen („Search")
     schmaler. Wer 91 px festschreibt, hat die Buendigkeit in genau einer
     Sprache. So sind alle drei per Definition gleich breit — in jeder.

     ⚠️ Auch die Hoehe angeglichen: Drei gleich breite Knoepfe in zwei
     verschiedenen Hoehen sehen nicht nach Absicht aus, sondern nach Zufall.
     Die beiden Listenknoepfe sind `btn-klein`, der Suchknopf nicht. */
  .kp-suchleiste .btn{
    width:var(--kp-mobil-knopf);
    min-width:var(--kp-mobil-knopf);
    height:var(--kp-mobil-knopfhoehe);
    justify-content:center;
  }
  /* 🔴 Die BEIDEN Listenknoepfe ZUSAMMEN so breit wie der Suchknopf darueber,
     nicht jeder einzeln (Praezisierung des Users, 21.08.2026). Also je die
     Haelfte, abzueglich des Zwischenraums — dann steht der rechte Rand des
     Zahnrads genau unter dem rechten Rand von „Anzeigen".
     ⚠️ Der Abzug MUSS dem `gap` der Reihe entsprechen. Steht dort spaeter ein
     anderer Wert, verschiebt sich die Buendigkeit um genau diese Differenz —
     deshalb beides hier beieinander. */
  .kp-listenkopf{gap:8px}
  /* 🔴 DIESELBEN Selektoren wie die Grundregel weiter oben
     (`.kp-listenkopf .kp-export:not(.kp-export-text), .kp-listenkopf
     .kp-ansicht-knopf`), nicht `.kp-listenkopf .btn`. Die Grundregel hat beim
     Export DREI Klassen und schlaegt zwei; beim Zahnrad steht es zwei zu zwei,
     und dort gewann meine, weil sie spaeter steht. Ergebnis war genau das,
     was der User gesehen hat: Export 34 px, Zahnrad 44 px.
     Merksatz: Wer eine bestehende Regel ueberschreibt, nimmt ihren Selektor —
     nicht einen bequemeren. */
  .kp-listenkopf .kp-export:not(.kp-export-text),
  .kp-listenkopf .kp-ansicht-knopf,
  .kp-listenkopf .btn{
    /* ⚠️ `flex:0 0 auto` ist hier entscheidend. Ohne das schrumpft Flexbox den
       ERSTEN Knopf, sobald die Reihe eng wird — auf den Tickets stand der
       Export dann mit 34 px neben einem Zahnrad mit 44, und das Paar war
       schmaler als der Suchknopf. Eine gesetzte Breite ist in einer Flexreihe
       nur ein Wunsch, solange das Schrumpfen erlaubt bleibt. */
    flex:0 0 auto;
    width:calc((var(--kp-mobil-knopf) - 8px) / 2);
    min-width:0;
    height:var(--kp-mobil-knopfhoehe);
    justify-content:center;
    padding-left:0;padding-right:0;
  }
  /* Damit die Reihe nicht an der Zaehlzeile scheitert: sie darf schrumpfen. */
  .kp-listenkopf > .muted{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  /* Alles vor den Knoepfen bekommt den Rest — damit stehen sie rechts und
     der letzte schliesst mit dem Suchknopf darueber ab. */
  .kp-listenkopf .kp-pro{margin-right:auto}

  /* Das Wort hinter der Zahl weg (Ansage des Users): „1–20 von 50" statt
     „1–20 von 50 Accounts". Damit passt das Zahnrad in dieselbe Reihe und
     eine ganze Zeile faellt weg. Unter der Liste bleibt das Wort stehen. */
  .kp-listenkopf .kp-einheit{display:none}

  /* 🔴 …und aus demselben Grund das Wort „Zeilen" vor dem Auswahlfeld
     (22.08.2026). Das Ausblenden der Einheit oben hat auf den Accounts
     gereicht; auf den Erinnerungen fehlten trotzdem 18 Pixel, weil dort
     zusaetzlich die Zaehlzeile kuerzer und damit der Rest laenger ist —
     das Zahnrad rutschte in eine zweite Zeile (Screenshot des Users).
     Die Zahl im Feld traegt die Aussage auch allein, so wie „1–3 von 3"
     ohne das Wort „Erinnerungen" auskommt.
     ⚠️ Nur im Listenkopf. Unter der Liste steht kein Auswahlfeld, und wo die
     Reihe sonst auftaucht, ist Platz. */
  .kp-listenkopf .kp-pro-wort{display:none}

  /* ---- 6. Luft zwischen den Karten ------------------------------------- */
  table.tabelle.kp-liste-karten tbody > tr{margin-bottom:10px}
}

/* ---- 7. Reiterleisten scrollen, statt umzubrechen -----------------------
   Auf den Eingangsrechnungen brach die Reiterleiste am Handy in DREI Zeilen
   und kostete 144 px, bevor die Seite ueberhaupt anfing.

   \U0001f4cc Fuer manche Leisten gibt es schon die Schiebehuelle mit Pfeilen
   (`leisteAuf()`/`leisteZu()`, 15.08.2026) — diese hier steckt nicht darin.
   Statt die Huelle an acht Stellen nachzuruesten, scrollt die Leiste am Handy
   selbst: gleiche Wirkung, eine Regel, und sie greift auch bei jeder Leiste,
   die spaeter dazukommt.

   ⚠️ Innerhalb der Huelle KEIN eigenes Scrollen — sonst schieben zwei
   Behaelter ineinander und die Pfeile bewegen den falschen. */
@media (max-width:720px){
  .kp-reiter{
    flex-wrap:nowrap;
    overflow-x:auto;
    scrollbar-width:none;
    -webkit-overflow-scrolling:touch;
  }
  .kp-reiter::-webkit-scrollbar{display:none}
  .kp-reiter > *{flex:0 0 auto}
  .kp-leiste-schiebe .kp-reiter{overflow-x:visible}

  /* ---- 8. Suchleisten mit Zeitraum ---------------------------------------
     Suchfeld, zwei Datumsfelder und der Knopf standen in drei Zeilen. Das
     Suchfeld darf die erste Zeile behalten, die drei schmalen Felder teilen
     sich die zweite. */
  .kp-suchleiste input[type=search],
  .kp-suchleiste input[type=text]{flex:1 1 100%}
  .kp-suchleiste input[type=date]{flex:1 1 0;min-width:0;width:auto}
}

/* Marke ohne Logo: der Name als Text (21.08.2026). Ein Mandant, der noch kein
   Logo hochgeladen hat, zeigt seinen Namen — nicht das Logo des Betreibers.
   Groesse und Gewicht an die Kopfzeile angepasst, damit die Zeile gleich hoch
   bleibt, ob dort ein Bild oder Text steht. */
.brand-name{
  font-size:1.05rem;font-weight:700;letter-spacing:-.01em;
  color:var(--text);white-space:nowrap;
}

/* ---- Demoanmeldung (21.08.2026) -------------------------------------------
   🔴 NICHT `.kp-haken` benutzen. Das ist der runde Haken-KNOPF aus der
   Rechnungsliste (ein `<button>`), kein Ankreuzfeld. Auf einem `<label>` mit
   `<input type=checkbox>` sah die Modulauswahl kaputt aus — der User hat es
   sofort gemeldet: „die auswahl der module ist kaputt".

   ⚠️ Zwei Spalten ab 520px, darunter eine. Neun Module untereinander sind
   auf dem Telefon eine halbe Bildschirmlaenge Scrollweg vor dem Absenden. */
.kp-modulwahl{border:0;padding:0;margin:20px 0 0}
/* ⚠️ Kein Rahmen mehr: Seit die Formularspalte selbst eine Flaeche ist, waere
   das ein Kasten im Kasten. Zwei ineinandergeschachtelte Rahmen sehen nach
   Versehen aus, nicht nach Gliederung. Die Ueberschrift traegt die Gruppe. */
.kp-modulwahl legend{padding:0;font-weight:600;font-size:1.02rem}
.kp-wahlliste{
  display:grid;grid-template-columns:repeat(auto-fit,minmax(205px,1fr));
  gap:9px 18px;margin-top:10px;
}
.kp-wahl{
  display:flex;align-items:flex-start;gap:10px;
  cursor:pointer;line-height:1.35;
  padding:11px 13px;border:1px solid var(--line);border-radius:12px;
  background:var(--card);
  transition:transform .16s ease, box-shadow .16s ease, border-color .16s ease;
}
.kp-wahl input{
  margin:1px 0 0;flex:0 0 auto;width:17px;height:17px;
  accent-color:var(--brand);cursor:pointer;
}
/* ⚠️ `min-width:0` am Text: Ein Flex-Kind hat als Vorgabe `min-width:auto`
   und schrumpft deshalb NICHT unter seine Inhaltsbreite — ein langer Name wie
   „Mitarbeiterverwaltung" schob sich aus der Kachel heraus, statt umzubrechen.
   Vom User gemeldet, sobald die Kacheln standen. */
.kp-wahl > span{min-width:0;overflow-wrap:anywhere}

/* Anheben und ein sehr weicher Schatten mit stark negativer Streuung. Genau
   das unterscheidet das Schweben von einem Schlagschatten: Der Schatten liegt
   weit unter dem Element und hat kaum eine Kante.
   Vorbild: dealpilot.immo, dort `0 30px 56px -30px` bei 4px Anhebung. */
.kp-wahl:hover{
  transform:translateY(-3px);
  border-color:color-mix(in srgb, var(--brand) 45%, var(--line));
  box-shadow:0 22px 44px -28px rgba(0,0,0,.55);
}

/* Gewaehlt: Rahmen und ein Hauch Markenfarbe im Ruecken. `:has()` erspart
   eine JavaScript-Klasse — das Ankreuzfeld selbst bleibt die Wahrheit, und
   ohne Skript sieht es trotzdem richtig aus. */
.kp-wahl:has(input:checked){
  border-color:var(--brand);
  background:color-mix(in srgb, var(--brand) 8%, var(--card));
}
.kp-wahl:focus-within{outline:2px solid var(--brand);outline-offset:2px}

/* ⚠️ Wer Bewegung abgestellt hat, bekommt nur die Farbe — kein Anheben.
   Ein Effekt, der sich nicht abschalten laesst, ist keine Verzierung mehr. */
@media (prefers-reduced-motion:reduce){
  .kp-wahl{transition:border-color .16s ease}
  .kp-wahl:hover{transform:none}
}

/* Die Zugangsdaten nach dem Einloesen: Beschriftung und Wert nebeneinander,
   der Wert umbrechbar — ein Kennwort mit Sonderzeichen sprengt sonst die
   Karte auf dem Telefon. */
/* `.kp-datenliste` ist derselbe Aufbau unter neutralem Namen — Beschriftung
   links, Wert rechts. Zweiter Selektor statt Kopie der Regeln: Sonst laufen
   zwei identische Bloecke auseinander, sobald jemand einen davon anfasst.
   (03.09.2026, fuer die Detailansicht einer Demoanmeldung.) */
.kp-zugangsdaten,.kp-datenliste{display:grid;grid-template-columns:auto 1fr;gap:7px 18px;margin:18px 0}
.kp-zugangsdaten dt,.kp-datenliste dt{font-weight:600;color:var(--muted)}
.kp-zugangsdaten dd,.kp-datenliste dd{margin:0;overflow-wrap:anywhere}
.kp-zugangsdaten code{font-size:1.05rem;letter-spacing:.02em}

@media (max-width:520px){
  .kp-wahlliste{grid-template-columns:1fr}
  .kp-zugangsdaten,.kp-datenliste{grid-template-columns:1fr;gap:2px 0}
  .kp-zugangsdaten dd,.kp-datenliste dd{margin-bottom:10px}
}

/* ---- Demoanmeldung: zwei Spalten am Rechner (21.08.2026) ------------------
   Frage des Users: „wieso konzentrieren wir das immer so sehr auf die mitte
   und gehen nicht mehr in die breite (zumindest am desktop)?"

   Es steckte keine Entscheidung dahinter — `.karte-schmal` stammt von der
   Anmeldeseite und ist mit 560px fuer ZWEI Eingabefelder richtig bemessen.
   Ein Formular mit fuenf Feldern, neun Modulen und Captcha wird darin zu
   einer schmalen Schlucht mit langem Scrollweg.

   ⚠️ Die schmale Karte bleibt, wo sie hingehoert: bei den Anmeldungen. Ein
   breites Anmeldeformular sieht falsch aus, weil zwei Felder die Breite nicht
   fuellen. Deshalb eine eigene Klasse und keine Aenderung an `.karte-schmal`.

   ⚠️ Umbruchpunkt bei 900px, nicht bei 768px: Bei zwei Spalten braucht die
   Formularspalte allein schon rund 420px, sonst stehen Vor- und Nachname
   wieder untereinander und der Gewinn ist weg. */
/* ⚠️ Eigenes Innenmass: `.karte-schmal` hat 30px seitlich, und was bei
   560px Breite luftig wirkt, klebt bei 1000px am Rand — der User hat es
   sofort gesehen: „die textboxen rechts sind jetzt direkt am rand ihres
   bereiches“. Die Eingabefelder gehen ueber die volle Spaltenbreite,
   also muss der Abstand aus der Karte kommen. */
/* 🔴 1240px, nicht 1000 (21.08.2026). Der User hat viermal dasselbe
   gemeldet, und ich habe es dreimal als Abstandsproblem behandelt. Es war
   ein BREITENproblem: „unverändert nur dass der generelle bereich mit text
   und eingabefeldern erneut kleiner geworden ist“ — mein groesserer
   Innenabstand hat den nutzbaren Bereich weiter verkleinert, also genau das
   Gegenteil.
   Seine erste Frage war schon die richtige: „wieso konzentrieren wir das
   immer so sehr auf die mitte und nicht mehr in die breite?“
   1240px ist das Containermass von dealpilot.immo, das ihm gefaellt. */
/* ⚠️ 21px seitlich statt 42 (21.08.2026). Die Glasflaeche des Formulars
   sass mit 42px Luft in der Karte; auf Wunsch des Users die Haelfte —
   nah genug, dass es zusammengehoert, weit genug, dass die innere Flaeche
   nicht mit der aeusseren verschmilzt.
   Oben und unten bleibt es groesser: Dort steht keine zweite Flaeche
   daneben, sondern die Ueberschrift, und die braucht Luft. */
.karte-breit{max-width:1240px;padding:38px 42px}

.kp-demo-raster{
  display:grid;grid-template-columns:1fr;gap:26px;
}
.kp-demo-text h1{margin-top:0}
.kp-demo-liste{margin:14px 0;padding-left:20px;line-height:1.7}
.kp-demo-liste li{margin-bottom:4px}

/* Zwei Felder nebeneinander — Vor-/Nachname und Mail/Telefon gehoeren
   zusammen und sind einzeln schmal genug. */
.kp-demo-paar{display:grid;grid-template-columns:1fr 1fr;gap:12px}
.kp-demo-paar > div{min-width:0}
.kp-demo-paar label{display:block}

/* 🔴 Die Formularspalte ist eine eigene FLAECHE, keine Trennlinie
   (21.08.2026, dritte Rueckmeldung des User zur selben Sache: „textboxen und
   bereiche liegen bei der servuno demo anmeldung immer noch an den grenzen
   ihrer äußeren container“).

   Gemessen stimmte der Abstand die ganze Zeit — 47px bis zum Kartenrand. Das
   Auge sieht aber etwas anderes: Links steht Text mit Flattersatz, rechts
   stehen harte Rechtecke, deren Kanten exakt auf der Spaltengrenze enden.
   Ohne eine sichtbare Flaeche dahinter wirkt jedes Feld angeschoben.
   Mit Flaeche und Innenabstand hat das Feld einen Rand, zu dem es gehoert.

   Die Flaeche ist bewusst kaum sichtbar — `--line` zu 22% gemischt. Vorbild
   ist dealpilot.immo, wo die Glasflaechen bei rgba(255,255,255,.03) bis .08
   liegen: Man soll sie spueren, nicht sehen. */
@media (min-width:900px){
  /* Die Formularspalte bekommt den groesseren Anteil — sie traegt Felder,
     die Textspalte nur Fliesstext, der ohnehin nicht breiter als rund 60
     Zeichen laufen sollte. */
  .kp-demo-raster{grid-template-columns:minmax(0,1fr) minmax(480px,1.3fr);gap:40px}
  /* 🔴 Die Flaeche ist das FORMULAR, nicht die Spalte (21.08.2026).
     Vorher trug die Spalte eine Flaeche UND das Formular eine zweite aus
     dem Glaseffekt von base.css — die Felder klebten an der inneren. Jetzt
     gibt es genau eine, und die hat ihren Innenabstand. */
  /* 🔴 ZWEI Flaechen, und zwischen ihnen 21px (21.08.2026).
     Der User wollte die Glasflaeche behalten, aber sie soll nicht bis an
     den Rand ihres Bereichs laufen. Vorher waren es 40px, gewuenscht die
     Haelfte. Ich hatte das zuerst am Kartenmass gedreht — falsch: Dadurch
     rueckte auch die Textspalte an den Kartenrand.
     Die Staffelung von aussen nach innen:
       Karte -> 42px -> aeussere Flaeche -> 21px -> Glas -> 34px -> Feld */
  .kp-demo-form{
    background:color-mix(in srgb, var(--line) 14%, transparent);
    border:1px solid var(--line);border-radius:20px;
    padding:21px;
  }
  /* ⚠️ `.karte-schmal .form` (zwei Klassen) schlaegt `.kp-demo-form form`
     (eine Klasse, ein Element) — die Regel darunter blieb wirkungslos, das
     Innenmass stand weiter auf 0. Mit der Karte im Selektor gewinnt sie. */
  .karte-schmal .kp-demo-form form{
    background:color-mix(in srgb, var(--line) 22%, transparent);
    border:1px solid var(--line);border-radius:16px;
    padding:32px 34px 34px;
  }
}
@media (max-width:560px){
  .kp-demo-paar{grid-template-columns:1fr}
  .karte-breit{padding:26px 20px}
}

/* ==== Direktlinks: anrufen und schreiben (25.08.2026) ======================
   Ansage des Users: Neben den Rufnummern und Adressen von Accounts, Kontakten
   und Mitarbeitenden gehoert ein Link, der direkt waehlt bzw. das
   Mailprogramm oeffnet.

   In Listen traegt der Link den Wert gleich mit; an Eingabefeldern steht er
   als reines Symbol daneben (`.kp-direkt-feld`), weil der Wert dort in einem
   `<input>` sitzt und nicht selbst der Link sein kann.

   ⚠️ `inline-flex` mit `gap` statt eines Leerzeichens im HTML: Ein
   Leerzeichen zwischen Symbol und Text bricht in schmalen Tabellenzellen um,
   und dann steht die Nummer eine Zeile unter ihrem eigenen Hoerer. */
.kp-direkt{
  display:inline-flex;align-items:center;gap:.4em;
  color:inherit;text-decoration:none;white-space:nowrap;
}
.kp-direkt svg{color:var(--muted);flex:0 0 auto}
.kp-direkt > span{text-decoration:underline;text-underline-offset:2px}
.kp-direkt:hover,.kp-direkt:focus-visible{color:var(--accent)}

/* 🔴 `[hidden]` allein reicht NICHT. Die Regel oben setzt `display:inline-flex`,
   und eine Klassenregel schlaegt die Vorgabe des Browsers (`[hidden]{display:none}`).
   Gemessen am 25.08.2026: Der Knopf trug `hidden` und war trotzdem 44px breit
   sichtbar — am leeren Feld stand also ein Hoerer, der ins Leere waehlt. */
.kp-direkt[hidden]{display:none}
.kp-direkt:hover svg,.kp-direkt:focus-visible svg{color:var(--accent)}

/* Am Eingabefeld: nur das Symbol, aber als Flaeche gross genug zum Antippen.
   🔴 34px, nicht 20px — ein Symbol in Textgroesse trifft am Handy niemand. */
/* 🔴 Der Umschlag ist das GANZE Feld samt Beschriftung, nicht nur das
   `<input>`. Grund: Die Adressfelder kommen aus `pflichtfeld()` und bringen
   Beschriftung, Eingabe und im Fehlerfall eine Markierung als EINEN Block
   mit — dort liesse sich das `<input>` allein gar nicht umfassen, ohne die
   Funktion umzubauen. Deshalb umbricht die Zeile: Beschriftung und Hinweis
   nehmen die volle Breite, Eingabe und Knopf teilen sich die naechste. */
.kp-feld-direkt{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.kp-feld-direkt > label,
.kp-feld-direkt > small{flex:0 0 100%}

/* 🔴 `flex:1 1 0`, NICHT `1 1 auto` (vom User beanstandet, 25.08.2026:
   „so wird mir das formular zu lang"). Die Grundregel gibt jedem Feld
   `width:100%`; bei `auto` wird genau diese Breite zur Flex-Basis, das Feld
   beansprucht die ganze Zeile und der Knopf rutscht darunter — jedes
   betroffene Feld wurde damit eine Zeile hoeher. Mit der Basis 0 teilt sich
   die Eingabe die Zeile mit dem Knopf und wird um dessen Breite schmaler,
   was genau die Absicht ist.
   ⚠️ `min-width:0` gehoert dazu: Ohne das faellt ein Flex-Element nie unter
   seine Inhaltsbreite zurueck, und die Basis 0 bliebe wirkungslos. */
.kp-feld-direkt > input,
.kp-feld-direkt > textarea,
.kp-feld-direkt > .kp-feld-symbolisch{flex:1 1 0;min-width:0}
/* ⚠️ `align-self:stretch` statt einer festen Hoehe: Das Eingabefeld daneben
   ist 46px hoch, ein 36px-Knopf schwebt darin. Gestreckt sitzt er buendig,
   und er bleibt es auch, wenn sich das Innenmass der Felder einmal aendert. */
.kp-direkt-feld{
  flex:0 0 auto;justify-content:center;align-self:stretch;
  width:44px;min-height:38px;
  border:1px solid var(--line);border-radius:var(--radius-sm);
  background:var(--kp-flyout);
}
.kp-direkt-feld:hover,.kp-direkt-feld:focus-visible{border-color:var(--accent)}

/* ==== Ablageflaeche zum Hineinziehen (25.08.2026) ==========================
   Ansage des Users: „kriegen wir auch ein drag drop feld hin?"

   🔴 Das echte Dateifeld liegt DECKUNGSGLEICH und durchsichtig ueber der
   Flaeche. Dadurch oeffnet ein Klick irgendwo im Kasten die Dateiauswahl und
   eine fallengelassene Datei landet direkt im Feld — beides macht der Browser
   von sich aus, ganz ohne JavaScript. Das Skript malt nur den Rahmen um.

   ⚠️ `opacity:0`, NICHT `display:none` und NICHT `visibility:hidden`. Ein
   Pflichtfeld, das der Browser nicht anzeigen kann, laesst sich auch nicht
   bemaengeln: Chrome bricht das Absenden dann mit „not focusable" ab und sagt
   dem Benutzer gar nichts. Mit `opacity:0` bleibt es ein sichtbares Feld mit
   Flaeche — die Meldung erscheint an der richtigen Stelle. */
.kp-ablage{
  position:relative;
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:4px;min-height:116px;padding:18px 16px;text-align:center;
  border:2px dashed var(--line);border-radius:var(--radius);
  background:color-mix(in srgb, var(--line) 12%, transparent);
  transition:border-color .15s ease, background-color .15s ease;
}
.kp-ablage input[type="file"]{
  position:absolute;inset:0;width:100%;height:100%;
  opacity:0;cursor:pointer;padding:0;border:0;
}
/* ⚠️ `pointer-events:none` an der Beschriftung: Ohne das faengt SIE den Klick
   und den Zeiger beim Ziehen ab, und das Feld darunter bekommt nichts mit. */
.kp-ablage-inhalt{
  display:flex;flex-direction:column;align-items:center;gap:3px;
  pointer-events:none;
}
.kp-ablage svg{color:var(--muted)}
.kp-ablage-titel{font-size:.95rem;word-break:break-all}
.kp-ablage-unter{font-size:.82rem;color:var(--muted)}

/* Waehrend etwas darueber schwebt */
.kp-ablage.ueber{border-color:var(--accent);background:var(--brand-soft)}
.kp-ablage.ueber svg{color:var(--accent)}
/* Wenn eine Datei drin liegt: durchgezogener Rahmen statt gestrichelt —
   gestrichelt heisst „hier ist noch nichts". */
.kp-ablage.hat-datei{border-style:solid;border-color:var(--accent)}
.kp-ablage.hat-datei svg{color:var(--accent)}


/* ---------------------------------------------------------------------------
   Einrichtungscheckliste auf dem Dashboard (Punkt C, 26.08.2026)
   ---------------------------------------------------------------------------
   Zuschnitt vom User gewaehlt: eine Checkliste, die in die vorhandenen
   Einstellungsreiter fuehrt — kein zweiter Assistent. Nichts wird erzwungen.

   🔴 Die Karte traegt einen farbigen linken Rand statt einer eingefaerbten
   Flaeche. Eine getoente Karte haette im dunklen Design entweder zu blass
   (Glasoptik legt `rgba(255,255,255,.06)` darueber) oder zu laut gewirkt —
   der Streifen sagt „das hier ist etwas anderes", ohne die Lesbarkeit des
   Inhalts anzutasten. Verwandt mit dem Fund zu den Diagramm-Tooltips.
--------------------------------------------------------------------------- */
.kp-onboarding > .karte{border-left:3px solid var(--brand)}

.kp-onb-kopf{display:flex;align-items:baseline;justify-content:space-between;gap:12px}
.kp-onb-kopf h2{margin:0}
/* Tabellenziffern: Die Zahl aendert sich mit jedem erledigten Punkt und soll
   dabei nicht springen. */
.kp-onb-zahl{
  font-size:.9rem;color:var(--muted);white-space:nowrap;
  font-variant-numeric:tabular-nums;
}
.kp-onb-unter{margin:4px 0 10px;font-size:.86rem}

.kp-onb-balken{
  height:6px;border-radius:999px;background:var(--line);overflow:hidden;margin-bottom:14px;
}
.kp-onb-balken > span{
  display:block;height:100%;border-radius:999px;background:var(--brand);
  transition:width .3s ease;
}

/* Drei Spalten je Zeile: Haken, Text, Aktion. Der Text bekommt den ganzen
   Rest — nach der Regel „Breite statt Abstand": Die Hinweiszeile ist der
   laengste Inhalt der Karte, und was ihr fehlt, muss sie umbrechen. */
.kp-onb-liste > li{
  display:flex;align-items:flex-start;gap:10px;
}
.kp-onb-text{display:flex;flex-direction:column;flex:1 1 auto;min-width:0}
.kp-onb-text small{font-size:.8rem;line-height:1.35;margin-top:1px}

/* Der Haken haelt seine Spalte auch dann, wenn er leer ist — sonst ruecken
   offene und erledigte Zeilen unterschiedlich weit ein, und die Liste wirkt
   bei jedem Klick neu ausgerichtet. */
.kp-onb-haken{
  flex:0 0 1.1em;text-align:center;line-height:1.5;
  color:var(--kp-gut);font-weight:700;
}
.kp-onb-liste > li.ist-fertig .kp-liste-name{color:var(--muted)}

.kp-onb-tat{display:flex;align-items:center;gap:6px;flex:0 0 auto;margin-left:auto}
.kp-onb-form{display:inline}

.kp-onb-fuss{
  display:flex;justify-content:flex-end;gap:8px;margin-top:10px;
  border-top:1px solid var(--line);padding-top:8px;
}

/* Schmal: Die Aktionen rutschen unter den Text, statt ihn auf wenige Zeichen
   je Zeile zusammenzuquetschen. `margin-left` zuruecknehmen, sonst stuenden
   sie dort weiterhin rechts aussen und der Text darueber bliebe kurz. */
@media (max-width:720px){
  .kp-onb-liste > li{flex-wrap:wrap}
  .kp-onb-tat{margin-left:1.1em;padding-left:10px}
  .kp-onb-fuss{justify-content:space-between}
}


/* ---------------------------------------------------------------------------
   Tooltip-Rundgang (Punkt D, 26.08.2026)
   ---------------------------------------------------------------------------
   🔴 Das Abdunkeln macht EIN Kasten mit riesigem Schlagschatten, kein Klon des
   Ziels und keine vier Rechtecke. Ein Klon verlöre den Zustand des Elements
   (offene Klappe, gesetzter Filter) und lüde Bilder ein zweites Mal; vier
   Rechtecke muessten bei jedem Scrollen einzeln nachgerechnet werden.

   ⚠️ `pointer-events:none` auf der Schale: Die Seite darunter bleibt
   anklickbar. Das ist Absicht — wer mitten im Rundgang doch etwas anderes tun
   will, soll nicht erst beenden muessen.
--------------------------------------------------------------------------- */
.kp-tour-schale{
  position:fixed;inset:0;z-index:1200;pointer-events:none;
}
.kp-tour-loch{
  position:absolute;border-radius:10px;
  box-shadow:0 0 0 9999px rgba(0,0,0,.55);
  outline:2px solid var(--brand);outline-offset:0;
  transition:top .18s, left .18s, width .18s, height .18s;
}

.kp-tour-blase{
  position:fixed;z-index:1201;width:min(340px, calc(100vw - 24px));
  background:var(--kp-flyout);color:var(--text);
  border:1px solid var(--line);border-radius:var(--radius, 12px);
  box-shadow:0 12px 32px rgba(0,0,0,.28);
  padding:14px 16px 12px;
}
.kp-tour-blase:focus{outline:2px solid var(--brand);outline-offset:2px}
.kp-tour-blase h3{margin:2px 0 6px;font-size:1.02rem}
.kp-tour-blase p{margin:0 0 12px;font-size:.88rem;line-height:1.45;color:var(--muted)}

.kp-tour-kopf{display:flex;align-items:center;justify-content:space-between;gap:10px}
/* Tabellenziffern, damit der Zaehler beim Weiterklicken nicht springt. */
.kp-tour-zaehler{
  font-size:.76rem;color:var(--muted);letter-spacing:.04em;
  font-variant-numeric:tabular-nums;
}
.kp-tour-zu{
  border:0;background:none;padding:0 2px;cursor:pointer;line-height:1;
  color:var(--muted);font-size:1.15rem;opacity:.65;
}
.kp-tour-zu:hover{opacity:1;color:var(--text)}
.kp-tour-zu:focus-visible{outline:2px solid var(--brand);outline-offset:2px;border-radius:4px}

/* Beenden links, Navigation rechts: Der Weg hinaus soll erreichbar sein, ohne
   neben „Weiter" zu liegen — sonst trifft ihn jemand beim schnellen Klicken.
   Genau darum hat der User ihn ausdruecklich verlangt. */
.kp-tour-fuss{display:flex;align-items:center;justify-content:space-between;gap:10px}
.kp-tour-nav{display:flex;gap:8px}

@media (max-width:720px){
  /* Am Handy sitzt die Blase unten fest: Ueber einem kleinen Ziel bliebe sonst
     kaum Platz, und beim Tippen verdeckte die Tastatur sie ohnehin. */
  .kp-tour-blase{
    left:12px !important;right:12px;width:auto;
    top:auto !important;bottom:12px;
  }
}


/* ---------------------------------------------------------------------------
   Teilnehmer einer Kontaktaufnahme (26.08.2026)
   ---------------------------------------------------------------------------
   Ansage des Users: „heute hatte ich aber einen videocall mit bbw und 3
   teilnehmern." Aus dem Auswahlfeld wurde eine Kaestchenliste.

   🔴 Zwei Spalten ab mittlerer Breite, darunter eine. Bei einem Account mit
   zehn Ansprechpartnern waere eine einspaltige Liste laenger als der Rest der
   Maske — und das Feld darunter (freier Name) rutschte aus dem Bild.
--------------------------------------------------------------------------- */
.kp-teilnehmer{
  display:grid;grid-template-columns:1fr;gap:2px 16px;
  border:1px solid var(--line);border-radius:var(--radius, 10px);
  padding:8px 10px;background:var(--card);
  max-height:190px;overflow:auto;
}
@media (min-width:620px){
  .kp-teilnehmer{grid-template-columns:1fr 1fr}
}

/* Die ganze Zeile ist klickbar, nicht nur das Kaestchen — auf dem Handy ist
   ein 13-px-Quadrat kein Ziel. */
.kp-teilnehmer-zeile{
  display:flex;align-items:center;gap:8px;
  padding:5px 4px;border-radius:6px;cursor:pointer;
  font-weight:400;
}
.kp-teilnehmer-zeile:hover{background:var(--hover, var(--kp-flyout))}
.kp-teilnehmer-zeile input{flex:0 0 auto;margin:0}
/* Lange Namen brechen um, statt die Spalte zu sprengen. */
.kp-teilnehmer-zeile span{min-width:0;overflow-wrap:anywhere}

/* Firmenfelder bei einer Privatperson: schreibgeschützt, nicht versteckt
   (28.08.2026). Sichtbar gedämpft, damit man erkennt, warum die Eingabe nicht
   greift — ohne den Wert zu verbergen, der weiterhin gelesen wird. */
.kp-feld-gesperrt label{opacity:.65}
.kp-feld-gesperrt input[readonly],
.kp-feld-gesperrt select:disabled,
.kp-feld-gesperrt textarea[readonly]{
  background:var(--kp-tile-bg,rgba(127,127,127,.06));
  cursor:not-allowed;
}

/* ==========================================================================
   Erwähnungen mit @Name (28.08.2026)

   Die Hülle legt JavaScript um das Textfeld; ohne JavaScript entsteht sie gar
   nicht und nichts hier greift.
   🔴 `--kp-flyout`, nicht `--card`: Der Kasten liegt über dem Formular und
   muss DECKEND sein — sonst scheint das Feld darunter durch die Namen.
   ========================================================================== */
.kp-erwaehn-huelle{position:relative}

.kp-erwaehn-klapp{
  position:absolute;left:0;right:0;top:calc(100% + 4px);z-index:70;
  margin:0;padding:5px;list-style:none;
  max-height:min(46vh,260px);overflow-y:auto;
  background:var(--kp-flyout);border:1px solid var(--line);border-radius:10px;
  box-shadow:0 14px 36px rgba(0,0,0,.22);
}
.kp-erwaehn-klapp[hidden]{display:none}

.kp-erwaehn-klapp li{
  padding:7px 10px;border-radius:7px;cursor:pointer;
  font-size:.92rem;color:var(--text);
  /* Lange Namen brechen um, statt den Kasten zu sprengen. */
  overflow-wrap:anywhere;
}
.kp-erwaehn-klapp li.aus,
.kp-erwaehn-klapp li:hover{background:var(--hover)}

/* Der fertige Name im Text. Nur Farbe und Gewicht — kein Kasten dahinter:
   In einer Tabellenzelle mit mehreren Erwähnungen wäre das eine Perlenkette
   aus Hintergründen. */
.kp-erwaehnung{font-weight:600;color:var(--primary)}

/* ==========================================================================
   Woraus sich der Umsatz zusammensetzt (02.09.2026)
   --------------------------------------------------------------------------
   Eine Zeile je Account, aufklappbar zu seinen Positionen. Die Zeile trägt
   drei Dinge nebeneinander: Name links, Anzahl der Posten als Pille, Betrag
   rechtsbündig. Der Betrag steht ganz rechts und in Tabellenziffern, damit
   die Beträge untereinander stehen — eine Liste, in der die Zahlen tanzen,
   lässt sich nicht überfliegen.

   🔴 `<details>` und nicht eine Klapplogik in JavaScript: Ohne Skript bleibt
   die Karte vollständig lesbar, und Tastatur wie Vorlesehilfe bringt der
   Browser mit. Dieselbe Entscheidung wie bei `.kp-tabelle-klapp`, deshalb
   auch dieselben Pfeile — zwei verschiedene Klappzeichen im selben Portal
   sähen aus wie zwei verschiedene Bedienelemente.
   ========================================================================== */
.kp-woraus{
  display:flex;flex-direction:column;
  border:1px solid var(--line);border-radius:var(--radius-sm);
  overflow:hidden;
}
.kp-woraus-kunde + .kp-woraus-kunde{border-top:1px solid var(--line)}

.kp-woraus-kunde > summary{
  display:flex;align-items:center;gap:12px;
  padding:11px 14px;cursor:pointer;list-style:none;
}
.kp-woraus-kunde > summary::-webkit-details-marker{display:none}
.kp-woraus-kunde > summary::before{
  content:"\25B8";flex:0 0 auto;color:var(--muted);font-size:.8rem;
}
.kp-woraus-kunde[open] > summary::before{content:"\25BE"}
.kp-woraus-kunde > summary:hover{background:var(--hover)}

/* Der Name ist ein Link auf den Account — wer die Zusammensetzung liest, will
   als Nächstes dorthin. `flex:1` schiebt den Betrag an den rechten Rand.
   ⚠️ Der Link liegt IM summary: Ein Klick auf den Namen führt zum Account,
   ein Klick daneben klappt auf. Deshalb `z-index` nicht nötig, aber der Link
   darf den Klapp-Klick nicht schlucken — das regelt der Browser von selbst,
   weil ein `<a>` mit href seinen Klick nicht an das summary weitergibt. */
.kp-woraus-name{
  flex:1 1 auto;min-width:0;font-weight:600;color:var(--text);
  text-decoration:none;overflow-wrap:anywhere;
}
.kp-woraus-name:hover{color:var(--brand);text-decoration:underline}

/* Die Leistung führt in den Katalog (02.09.2026, Ansage des Users: „ich kann
   dort accounts anklicken, möchte aber auch gern die leistungen anklicken
   können").
   ⚠️ Bewusst NICHT fett und nicht farbig im Ruhezustand: Der Account im Kopf
   ist die Überschrift, die Leistung eine Zeile darunter. Wären beide gleich
   ausgezeichnet, sähe die Tabelle aus wie eine Linkliste — die Beträge
   rechts sind aber das, was gelesen werden soll. */
.kp-woraus-leistung{color:inherit;text-decoration:none}
.kp-woraus-leistung:hover{color:var(--brand);text-decoration:underline}

/* ⚠️ Feste Breite und Tabellenziffern, aus demselben Grund wie beim Betrag:
   Die Pille sitzt zwischen dem dehnbaren Namen und der festen Betragsspalte,
   also bestimmt IHRE Breite, wo ihre linke Kante steht. In einer
   Proportionalschrift ist die „1" schmaler als die „2" — gemessen 2 px
   Versatz zwischen den Zeilen (02.09.2026). `min-width` fängt zusätzlich den
   Sprung von einer auf zwei Stellen ab. */
.kp-woraus-anzahl{
  flex:0 0 auto;font-size:.72rem;font-weight:700;
  border-radius:999px;padding:1px 8px;
  background:var(--line);color:var(--muted);
  min-width:2.6em;text-align:center;
  font-variant-numeric:tabular-nums;
}
/* 🔴 Feste Spaltenbreite für den Betrag (02.09.2026, Fund des Users: „die
   eingekreiste anzahl rutscht nach rechts, wenn ab der dritten position die
   summe zweistellig wird").

   Der Betrag stand auf `flex:0 0 auto`, war also genau so breit wie sein Text.
   „366,37 €" ist breiter als „14,00 €" — und weil die Pille links davon
   sitzt, wanderte sie mit jeder kürzeren Zahl nach rechts. In einer Liste, die
   von oben nach unten gelesen wird, ist so eine wandernde Spalte genau die
   Unruhe, die das Überfliegen verhindert.

   9,5em trägt „9.999,99 €" — darüber wächst die Spalte mit, statt umzubrechen.
   `tabular-nums` hält zusätzlich die Ziffern selbst auf gleicher Breite. */
.kp-woraus-wert{
  flex:0 0 auto;font-weight:700;color:var(--text);
  font-variant-numeric:tabular-nums;
  min-width:9.5em;text-align:right;
}

/* Die Postentabelle sitzt eingerückt unter ihrer Zeile — die Einrückung ist
   das, was sie als Unterebene ausweist. Kein zweiter Rahmen: Der Kasten
   aussen trägt die Abgrenzung schon. */
.kp-woraus-posten{
  margin:0 0 4px;padding:0 14px 10px 34px;
  font-size:.88rem;
}
.kp-woraus-posten td:last-child{font-variant-numeric:tabular-nums;font-weight:600}
.kp-woraus-posten td:nth-child(3){font-variant-numeric:tabular-nums}

/* Dieselbe Summe nach Leistung — eine flache Tabelle, kein Klappwerk. Nur
   die Zahlenspalten brauchen Regeln; den Rest trägt `.tabelle`. */
.kp-woraus-liste td:not(:first-child),
.kp-woraus-liste th:not(:first-child){font-variant-numeric:tabular-nums}
.kp-woraus-liste td:last-child{white-space:nowrap}

@media (max-width:560px){
  /* Auf dem Telefon reicht die Breite nicht für vier Spalten. Der Betrag je
     Zahlung fällt zuerst weg — er ist die Herleitung, nicht das Ergebnis. */
  .kp-woraus-posten th:nth-child(3),
  .kp-woraus-posten td:nth-child(3){display:none}
  .kp-woraus-posten{padding-left:20px}

  /* In der Leistungsliste fällt die Zahl der Buchungen weg: Die Zahl der
     Accounts ist die Auskunft, die Buchungen sind die Feinheit. */
  .kp-woraus-liste th:nth-child(3),
  .kp-woraus-liste td:nth-child(3){display:none}

  /* Auf schmalem Schirm ist die feste Betragsspalte zu teuer — der Name
     bekommt den Platz, die Beträge stehen ohnehin untereinander. */
  .kp-woraus-wert{min-width:0}
}
