/* ============================================================
   E-Rechnung — Design-System
   Leitidee: das ordentliche Rechnungsbuch eines Handwerksbetriebs,
   digitalisiert. Tinte, Papier, ein Stempel für den Status.
   ============================================================ */

@import url('https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght@9..144,500;9..144,600;9..144,700&family=Inter:wght@400;500;600;700&family=IBM+Plex+Mono:wght@500;600&display=swap');

:root {
  --ink: #1B2A4A;
  --ink-light: #2D4372;
  --paper: #F6F4EE;
  --surface: #FFFFFF;
  --text: #23262B;
  /* Drei Stufen dunkler als bis zum 17.09.2026 (#6B7280). Der alte Ton
     schaffte 4,83:1 auf --surface, verfehlte aber JEDE getoente Flaeche:
     4,40:1 auf --paper, 4,20:1 auf --stamp-draft-bg - und getoent ist hier
     der Normalfall. Dieser Ton kommt auf 5,29 / 4,81 / 4,60 und bleibt
     derselbe kuehle Grau. Vierzehn der neunzehn Fundstellen aus Ae2 haengen
     an dieser einen Marke. */
  --muted: #656C78;
  --border: #DDD7C7;
  --accent: #B9812E;
  --accent-ink: #6E4B12;
  --success: #3F7159;
  --success-bg: #E7F0EA;
  --success-fg: #FFFFFF;
  --danger: #B3452C;
  --danger-bg: #F7E9E4;
  --info-bg: #EAEFF8;
  /* Überschriften-/Emphase-Textfarbe - im Hellmodus identisch zu --ink
     (das gleichzeitig als Hintergrundfarbe für Sidebar/Primär-Buttons
     dient und dafür NICHT umgefärbt werden soll). Im Dunkelmodus muss nur
     dieses Token hell werden, --ink selbst bleibt als Hintergrundfarbe
     unverändert dunkel. */
  --heading: var(--ink);
  --stamp-draft-bg: #F1EFE8;
  --stamp-accent-bg: #FBF1DE;
  /* Das Suchwort im Treffer (A6, 21.09.2026). Auf der gewaehlten Zeile
     (--stamp-draft-bg) geht die Flaeche fast unter (1,04:1) - deshalb traegt
     das Gewicht der Schrift die Aussage mit, nicht die Farbe allein. */
  --treffer-bg: #FFE9A8;

  /* Fraunces ist eine DISPLAY-Schrift: sie trägt den Markenauftritt und den
     Titel der Seite, auf der man steht. Alles, womit gearbeitet wird -
     Kartentitel, Beschriftungen, Tabellen, Knöpfe - läuft in Inter. Ein
     ganzer Satz in einer Display-Serifenschrift bei 17px liest sich schwer
     und wirkt dekorativ, wo er sachlich sein soll.
     Die Rückfallschriften stehen ausgeschrieben da, damit ein blockierter
     Google-Fonts-Abruf nicht in Times New Roman endet. */
  --font-display: 'Fraunces', 'Iowan Old Style', Georgia, 'Times New Roman', serif;
  --font-body: 'Inter', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
  --font-mono: 'IBM Plex Mono', ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

  /* Der Rand von BEDIENELEMENTEN - Knöpfe, Eingabefelder, Auswahllisten.
     Bewusst NICHT --border: der ist für Trennlinien und Kartenkanten, und
     dort ist leise richtig. Ein Bedienelement muss dagegen als solches zu
     erkennen sein; WCAG 2.1 verlangt dafür 3:1 zur Umgebung (SC 1.4.11).

     Gemessen am 11.09.2026: --border kam auf 1,31:1 gegen die Seite. Man
     sah nicht, dass ein Knopf ein Knopf ist - genau das hat der Betrieb
     als „nicht anschaulich" gemeldet. Dieser Ton schafft 3,34:1 hell und
     3,78:1 dunkel. */
  --rand-bedienelement: #8C8574;

  /* Die Schrift AUF dem Akzent. Weiß auf Gold ergibt 3,36:1 (hell) und
     2,17:1 (dunkel) - beides zu wenig für Fließtext, und der Akzentknopf
     ist der Hauptknopf der Anwendung. Dunkel auf Gold schafft 5,38:1 bzw.
     8,34:1, und die Markenfarbe bleibt, wie sie ist. */
  --auf-akzent: #14161C;

  /* Die FLÄCHE des Gefahrenknopfes. Getrennt von --danger, weil der auch
     für SCHRIFT gebraucht wird ("überfällig") - dort muss er im
     Dunkelmodus hell sein, als Fläche unter weißer Schrift dagegen
     dunkel. Eine Marke kann nicht beides. */
  --danger-flaeche: #B3452C;

  /* Wie hoch die klebende Kopfleiste der Maske /case gerade ist. Den Wert
     schreibt 66-case-list.js zur Laufzeit hierher (caseListKopfMessen) -
     er haengt an der Fensterbreite, der Sprache und der Schriftgroesse des
     Geraets. Hier steht nur ein Anfangswert, damit die Rechnung auch vor
     der ersten Messung stimmt. */
  --af-kopf-hoehe: 88px;
  --radius: 10px;
  /* Der kleine Radius. Wurde als var(--radius-sm, 6px) schon benutzt,
     ohne je definiert zu sein - der Rueckfallwert trug ihn. Jetzt steht er
     bei seinem grossen Bruder, und die 6px daneben haben einen Namen. */
  --radius-sm: 6px;
  --shadow: 0 1px 2px rgba(27, 42, 74, 0.06), 0 8px 24px -12px rgba(27, 42, 74, 0.18);
}

/* ============================================================
   Dunkelmodus
   Gleiche "Tinte auf Papier"-Leitidee wie oben, nur umgekehrt: warmes
   Dunkelgrau statt cremefarbenem Papier, helle Warmtöne statt Tinte für
   Überschriften/Fließtext. --ink/--ink-light bleiben UNVERÄNDERT (dienen
   als Hintergrundfarbe für Sidebar/Primär-Buttons, die als dunkler Block
   in beiden Modi funktionieren) - nur die Tokens, die tatsächlich
   Lesbarkeit auf hellem vs. dunklem Untergrund betreffen, werden ersetzt.

   Zwei Wege, in den Dunkelmodus zu kommen:
   1. System-Einstellung (prefers-color-scheme), sofern der Nutzer noch
      KEINE explizite Wahl getroffen hat (siehe :not([data-theme="light"])
      unten - verhindert, dass diese Regel eine explizite Hell-Wahl
      überstimmt).
   2. Manuelle Wahl über den Umschalter (setzt data-theme="dark"/"light"
      auf <html>, siehe app.js: applyTheme/toggleTheme), persistiert in
      localStorage.
   ============================================================ */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --paper: #14161C;
    --surface: #1D212B;
    --text: #DDDBD0;
    --muted: #93927F;
    --border: #333748;
    /* Gemessen: #333748 als Knopfrand kommt auf 1,53:1 gegen die Seite.
       Dieser Ton schafft 3,78:1 - siehe die Begruendung bei :root. */
    --rand-bedienelement: #6B7288;
    --heading: #F2F0E4;
    --accent: #D9A857;
    --accent-ink: #F2C978;
    /* Das Erfolgs-Grün des Hellmodus (#3F7159) blieb im Dunkelmodus
       unverändert und kam dort auf nur 2,4:1 Kontrast - deutlich unter
       dem Mindestwert von 4,5:1 und damit kaum lesbar. Der hellere Ton
       erreicht 5,1:1 auf der Erfolgsfläche und 6,0:1 auf der Karte. */
    --success: #5FAE84;
    --success-bg: #1E3229;
    --success-fg: #0F1720;
    /* Im Dunkeln braucht Rot mehr Helligkeit: #B3452C kaeme auf dem
       dunklen Grund nur auf 2.9:1 und waere schlecht lesbar. */
    --danger: #E8705A;
    /* Als FLAECHE unter weisser Schrift ist #E8705A zu hell (3,05:1).
       Dieser Ton schafft 4,50:1 - und --danger bleibt fuer SCHRIFT
       hell, wo er hell sein muss. */
    --danger-flaeche: #C8503A;
    --danger-bg: #3A241D;
    --info-bg: #1D2436;
    --stamp-draft-bg: #262A34;
    --stamp-accent-bg: #3A311C;
    --treffer-bg: #4A3A12;
    --shadow: 0 1px 2px rgba(0, 0, 0, 0.3), 0 8px 24px -12px rgba(0, 0, 0, 0.55);
  }
}
:root[data-theme="dark"] {
  --paper: #14161C;
  --surface: #1D212B;
  --text: #DDDBD0;
  --muted: #93927F;
  --border: #333748;
  --rand-bedienelement: #6B7288;
  --heading: #F2F0E4;
  --accent: #D9A857;
  --accent-ink: #F2C978;
  /* Gleiche Begründung wie im Block darüber: ohne eigenen Wert bliebe
     hier das dunkle Grün des Hellmodus stehen. Dieser Block greift,
     wenn der Dunkelmodus ausdrücklich über den Umschalter gewählt
     wurde - der Block darüber nur bei entsprechender
     Systemeinstellung. Beide brauchen den Wert. */
  --success: #5FAE84;
  --success-bg: #1E3229;
  --success-fg: #0F1720;
  /* Im Dunkeln braucht Rot mehr Helligkeit: #B3452C kaeme auf dem
     dunklen Grund nur auf 2.9:1 und waere schlecht lesbar. */
  --danger: #E8705A;
  --danger-flaeche: #C8503A;
  --danger-bg: #3A241D;
  --info-bg: #1D2436;
  --stamp-draft-bg: #262A34;
  --stamp-accent-bg: #3A311C;
  --treffer-bg: #4A3A12;
  --shadow: 0 1px 2px rgba(0, 0, 0, 0.3), 0 8px 24px -12px rgba(0, 0, 0, 0.55);
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--paper);
  color: var(--text);
  font-family: var(--font-body);
  /* Ohne Vorgabe rechnet der Browser rund 1,2 - bei 13-14px sind mehrzeilige
     Hinweise ("Zeitpunkt der Lieferung/Leistung (§14 Abs. 4 Nr. 6 UStG)")
     damit gedrängt. Überschriften setzen ihren eigenen, engeren Wert. */
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

body {
  min-height: 100vh;
}

a { color: inherit; }

button {
  font-family: inherit;
  cursor: pointer;
}

:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 2px;
}

.hidden { display: none !important; }

/* ---------- Landing / Marketing ---------- */

.landing-header {
  border-bottom: 1px solid var(--border);
  background: var(--surface);
}
.landing-header-inner {
  max-width: 1080px;
  margin: 0 auto;
  padding: 16px 24px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
}
.landing-header .brand-mark { margin-bottom: 0; }
.landing-nav {
  display: flex;
  align-items: center;
  gap: 20px;
  flex-wrap: wrap;
}
.landing-nav a:not(.btn) {
  color: var(--muted);
  font-size: 14px;
  font-weight: 600;
  text-decoration: none;
}
.landing-nav a:not(.btn):hover { color: var(--heading); }
.landing-nav .btn { text-decoration: none; }

.landing-hero {
  max-width: 720px;
  margin: 0 auto;
  padding: 72px 24px 56px;
  text-align: center;
}
.landing-hero h1 {
  font-family: var(--font-display);
  font-size: 42px;
  line-height: 1.15;
  font-weight: 600;
  color: var(--heading);
  margin: 0 0 20px;
}
.landing-lead {
  font-size: 17px;
  color: var(--muted);
  margin: 0 0 32px;
  line-height: 1.6;
}
.landing-cta-row {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  flex-wrap: wrap;
}
.landing-cta-row .btn { text-decoration: none; width: auto; }
.landing-trust {
  margin: 18px 0 0;
  font-size: 13px;
  color: var(--muted);
}

.btn-lg { padding: 14px 28px; font-size: 16px; }

.landing-features {
  max-width: 1080px;
  margin: 0 auto;
  padding: 8px 24px 64px;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 16px;
}
.landing-feature-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 22px 20px;
}
.landing-feature-card h2 {
  font-family: var(--font-display);
  font-size: 16px;
  font-weight: 600;
  color: var(--heading);
  margin: 0 0 6px;
}
.landing-feature-card p {
  font-size: 14px;
  color: var(--muted);
  margin: 0;
  line-height: 1.5;
}

.landing-steps {
  background: var(--surface);
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
  padding: 56px 24px;
}
.landing-section-title {
  text-align: center;
  font-family: var(--font-display);
  font-size: 26px;
  font-weight: 600;
  color: var(--heading);
  margin: 0 0 36px;
}
.landing-steps-row {
  max-width: 960px;
  margin: 0 auto;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 24px;
}
.landing-step { text-align: center; }
.landing-step-num {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background: var(--ink);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-mono);
  font-weight: 600;
  margin: 0 auto 14px;
}
.landing-step h3 {
  font-family: var(--font-display);
  font-size: 16px;
  font-weight: 600;
  color: var(--heading);
  margin: 0 0 6px;
}
.landing-step p {
  font-size: 14px;
  color: var(--muted);
  margin: 0;
  line-height: 1.5;
}

.landing-bottom-cta {
  background: var(--ink);
  color: #fff;
  text-align: center;
  padding: 56px 24px;
}
.landing-bottom-cta h2 {
  font-family: var(--font-display);
  font-size: 26px;
  font-weight: 600;
  margin: 0 0 24px;
}
.landing-bottom-cta .btn { text-decoration: none; width: auto; }

.landing-footer {
  text-align: center;
  padding: 32px 24px 40px;
  font-size: 13px;
  color: var(--muted);
}
.landing-footer p { margin: 4px 0; }
.landing-footer a { color: var(--muted); text-decoration: underline; }
.landing-footer a:hover { color: var(--heading); }

/* ---------- Die Landeseite nach E7.8 (20.09.2026) ---------- */
/*
   Vier neue Flaechen zwischen den vorhandenen. Kein neuer Grundton, keine
   neue Schrift: die Leitidee oben in dieser Datei - das Rechnungsbuch eines
   Handwerksbetriebs - traegt auch hier.
*/

/* Der Montagabend. Der Leser soll sich wiedererkennen, bevor ihm jemand
   etwas verspricht - also Fliesstext in Lesebreite, keine Karte. */
.landing-stapel {
  max-width: 720px;
  margin: 0 auto;
  padding: 8px 24px 48px;
  font-size: 16px;
  line-height: 1.6;
  color: var(--text);
}
/* Eine angestrichene Stelle im Buch, kein Kasten. Der Akzent steht als
   KANTE, nicht als Schrift: als Schrift kommt er auf 3,06:1 und faellt
   damit unter die Grenze (tests/test_kontrast.py). */
.landing-stapel > p:last-child {
  border-left: 3px solid var(--accent);
  padding-left: 16px;
}

/* Die Massgabe in jeder Karte, an der Stelle des alten gruenen Hakens.
   Vier gleiche Haken sagten viermal "erledigt"; vier Zahlen sagen vier
   verschiedene Dinge. Zahl in der Zifferschrift, damit sie als Messwert
   gelesen wird und nicht als Zierat. */
.landing-mass {
  display: inline-flex;
  align-items: center;
  min-height: 36px;
  padding: 0 10px;
  border-radius: 999px;
  background: var(--stamp-accent-bg);
  color: var(--accent-ink);
  font-family: var(--font-mono);
  font-size: 14px;
  font-weight: 600;
  margin-bottom: 12px;
}

/* Die Zeile unter den vier Karten - sie nennt den Preis des Fehlers. */
.landing-beweis-schluss {
  max-width: 660px;
  margin: 0 auto;
  padding: 0 24px 48px;
  text-align: center;
  font-size: 16px;
  line-height: 1.6;
  color: var(--heading);
}

/* Die Nebenlinie (Selbstzahler) und der Preis - beide Fliesstext. */
.landing-privat,
.landing-preis {
  max-width: 720px;
  margin: 0 auto;
  padding: 0 24px 48px;
  font-size: 16px;
  line-height: 1.6;
  color: var(--text);
}

/* "Was Krankenfahrt-abrechnen.de heute noch nicht tut". Im Entwurfs-Stempelton, weil hier
   steht, was noch nicht fertig ist - die Farbe sagt dasselbe wie der Text. */
.landing-grenzen {
  max-width: 720px;
  margin: 0 auto 48px;
  padding: 24px;
  background: var(--stamp-draft-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
}
.landing-grenzen ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.landing-grenzen li { font-size: 14px; line-height: 1.55; }
.landing-grenzen strong { color: var(--heading); display: block; }

/* ---------- Plan-Karten (Abo-Seite in der App + Landingpage) ---------- */

.plan-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 16px;
  margin-top: 16px;
}
.plan-card { display: flex; flex-direction: column; text-align: left; }
.plan-card-current { border-color: var(--heading); box-shadow: 0 0 0 1px var(--ink), var(--shadow); }
.plan-card h2 {
  font-family: var(--font-body);
  letter-spacing: -0.005em;
  font-size: 18px;
  font-weight: 600;
  color: var(--heading);
  margin: 0 0 6px;
}
.plan-price {
  font-family: var(--font-mono);
  font-size: 26px;
  font-weight: 700;
  color: var(--heading);
  margin-bottom: 16px;
}
.plan-price span { font-size: 13px; font-weight: 500; color: var(--muted); }
.plan-features {
  list-style: none;
  margin: 0 0 20px;
  padding: 0;
  flex: 1;
  font-size: 13px;
  color: var(--muted);
}
.plan-features li { padding: 5px 0 5px 20px; position: relative; }
.plan-features li::before { content: "✓"; position: absolute; left: 0; color: var(--success); font-weight: 700; }
.plan-card .btn { width: 100%; }

/* ---------- Auth Screen ---------- */

#auth-screen,
#verify-screen {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
}

.auth-card {
  width: 100%;
  max-width: 400px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 40px 36px;
  transition: max-width 0.15s ease;
}
/* Registrieren-Modus: die Unternehmensdaten (#auth-company-fields, zwei
   Spalten wie .form-grid) brauchen deutlich mehr Platz als die schmale
   Login-Karte - siehe app.js: applyAuthMode() setzt/entfernt diese Klasse. */
.auth-card--wide { max-width: 720px; }

/* Am Schreibtisch stand die Anmeldekarte als 400px-Spalte in einem leeren
   Feld - gemessen am 12.09.2026: 15% der Flaeche bei 1920px, 31% bei 1280px,
   und trotzdem 801px hoch, also scrollend in einem 800px hohen Fenster. Eine
   vergroesserte Telefonansicht.

   Kopf (Zurueck, Marke, Ueberschrift, Vorzeile) und Formular treten deshalb
   NEBENEINANDER. Es wird nichts hinzuerfunden - dieselben Elemente stehen in
   zwei Spalten statt untereinander. Die Reihenfolge im Markup bleibt
   unangetastet, damit Tastatur und Vorlesehilfe weiter Zurueck -> Marke ->
   Ueberschrift -> Felder gehen.

   ZWEI GRENZEN, und die zweite ist teuer bezahlt: der erste Anlauf schaltete
   beides ab 900px um und machte die REGISTRIERUNG dort laenger statt kuerzer
   (gemessen: 1725px -> 2101px bei 900px Fenster). Der Grund ist die
   Kopfspalte: sie nimmt dem Formular den Platz, den dessen eigenes Raster
   (.form-grid, auto-fit ab 260px) fuer seine zweite Spalte braucht.

   Gerechnet statt geraten:
     2 Feldspalten  = 2x260 + 16 gap          = 536px Formular
     + Kopfspalte   = 300 + 44 gap            = 344px
     + Karteninnenrand 2x36 + Schirmrand 2x24 = 120px
     -------------------------------------------------
     = 1000px Fenster. Gewaehlt ist 1024px - ein gaengiges Mass, und dort
       gemessen: Karte 976px, Felder zweispaltig, 1534px hoch. */
@media (min-width: 900px) {
  /* Die Anmeldung hat keine Unternehmensdaten - fuer sie reicht der Platz
     schon hier. */
  #auth-screen .auth-card:not(.auth-card--wide) {
    max-width: 820px;
    display: grid;
    grid-template-columns: 300px minmax(0, 1fr);
    column-gap: 44px;
    align-items: start;
  }
}
@media (min-width: 1024px) {
  #auth-screen .auth-card--wide {
    max-width: 1020px;
    display: grid;
    grid-template-columns: 300px minmax(0, 1fr);
    column-gap: 44px;
    align-items: start;
  }
}
@media (min-width: 900px) {
  .auth-kopf { grid-column: 1; grid-row: 1; }
  /* Alles ausser dem Kopf nach rechts. Versteckte Formulare (display:none)
     belegen im Raster keine Zeile. Die Regel gilt auch unter 1024px
     schadlos: ohne `display: grid` ist grid-column wirkungslos. */
  #auth-screen .auth-card > :not(.auth-kopf) { grid-column: 2; }
  .auth-kopf .lead { margin-bottom: 0; }
}

.auth-section-title {
  font-family: var(--font-body);
  letter-spacing: -0.005em;
  font-size: 16px;
  font-weight: 600;
  color: var(--heading);
  margin: 22px 0 12px;
  padding-top: 18px;
  border-top: 1px solid var(--border);
}

.brand-mark {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 28px;
}

.brand-stamp {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  border: 2px solid var(--ink);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 18px;
  color: var(--heading);
  flex-shrink: 0;
}

/* Logo-Bild (favicon.svg) statt CSS-Kreis mit Buchstabe: eigene, bereits
   im SVG enthaltene Form/Farbe - Kreis-Rahmen & Schrift-Styling von
   .brand-stamp werden hier bewusst zurückgesetzt. */
.brand-stamp-logo {
  border-radius: 22%;
  border: none;
  display: block;
}
/* Das Logo hat selbst einen dunkelblauen Hintergrund (var(--ink)) - auf
   der ebenfalls dunkelblauen Sidebar/Topbar würde die Kachel sonst mit
   dem Hintergrund verschmelzen, deshalb hier ein dezenter heller Ring. */
.sidebar .brand-stamp-logo,
.mobile-topbar-logo {
  box-shadow: 0 0 0 1.5px rgba(255, 255, 255, 0.3);
}

.brand-name {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 20px;
  color: var(--heading);
  letter-spacing: -0.01em;
}

.brand-sub {
  font-size: 12px;
  color: var(--muted);
  margin-top: -2px;
}

.auth-card h1 {
  font-family: var(--font-display);
  font-size: 24px;
  font-weight: 600;
  margin: 0 0 4px;
  color: var(--heading);
}

.auth-card p.lead {
  color: var(--muted);
  font-size: 14px;
  margin: 0 0 24px;
}

.field {
  margin-bottom: 14px;
}

/* Versalien waren hier falsch: deutsche Beschriftungen sind lang und
   zusammengesetzt ("NOTIZ (OPTIONAL, ERSCHEINT AUF DER RECHNUNG)"), und in
   Großbuchstaben verliert ein Wort seine Umrissform - man buchstabiert es
   statt es zu erkennen. In Tabellenköpfen bleiben Versalien, dort stehen
   einzelne kurze Wörter und sie kennzeichnen die Kopfzeile als solche. */
.field label {
  display: block;
  font-size: 13px;
  font-weight: 600;
  line-height: 1.4;
  color: var(--muted);
  margin-bottom: 6px;
}

.field input,
.field select,
.field textarea {
  width: 100%;
  padding: 10px 12px;
  border: 1px solid var(--rand-bedienelement);
  border-radius: 8px;
  font-family: var(--font-body);
  font-size: 14px;
  background: var(--surface);
  color: var(--text);
}

.field input:focus,
.field select:focus,
.field textarea:focus {
  border-color: var(--ink-light);
}

/* „Bitte waehlen" steht IM Feld, aber nicht IN der Liste (N13, neu gebaut
   am 19.09.2026 - siehe static/js/13-wahlfelder.js). Dieselbe Bauart wie
   .passwortfeld darunter: eine Huelle, die erst im Browser entsteht.

   Die Beschriftung liegt UEBER dem leeren Feld und nimmt keine Klicks an -
   sonst oeffnete ein Tipp auf den Text die Liste nicht. Masse und Schrift
   sind die des Felds (.field select: 10px 12px, 14px), damit der Text an
   genau derselben Stelle steht wie spaeter die Auswahl. */
.wahlfeld {
  display: block;
  position: relative;
}
.wahlfeld-platzhalter {
  position: absolute;
  inset: 0;
  display: none;
  align-items: center;
  padding: 0 12px;
  font-family: var(--font-body);
  font-size: 14px;
  color: var(--muted);
  pointer-events: none;
}
.wahlfeld.leer .wahlfeld-platzhalter { display: flex; }

/* Passwort sichtbar machen (L8). Die Huelle entsteht erst im Browser -
   passwortAugenNachruesten() schiebt sie zwischen .field und das Feld,
   damit der Knopf IM Feld sitzen kann statt daneben. Ohne sie muesste das
   Markup an acht Stellen dasselbe wiederholen.

   display: block, nicht inline: ein <span> ist von Haus aus inline und
   nimmt dann nicht die volle Breite an, die .field input erwartet. */
.passwortfeld {
  display: block;
  position: relative;
}
/* Platz fuer den Knopf, sonst laeuft das Passwort darunter hindurch.
   32px Knopf + 8px Abstand rechts + 4px Luft. */
.passwortfeld input { padding-right: 44px; }

.passwort-auge {
  position: absolute;
  top: 50%;
  right: 6px;
  transform: translateY(-50%);
  width: 32px;
  height: 32px;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: none;
  border-radius: 6px;
  background: none;
  color: var(--muted);
  cursor: pointer;
}
.passwort-auge svg { width: 18px; height: 18px; display: block; }
.passwort-auge:hover { color: var(--heading); }

/* Native <select>-Pfeile sehen je nach Browser/OS unterschiedlich aus und
   wirken neben den sonst durchgestalteten Formularfeldern (Radius, Border,
   Schrift) fremd - hier durch ein eigenes, zur Marke passendes Chevron-Icon
   ersetzt. Gilt für ALLE Selects der App (Formularfelder wie auch
   eigenständige, z.B. den Zeitraum-Filter im Admin-Bereich), damit
   Dropdowns überall einheitlich aussehen. */
select {
  appearance: none;
  -webkit-appearance: none;
  -moz-appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill='none' stroke='%232D4372' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round' d='M4 6l4 4 4-4'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 12px center;
  background-size: 12px;
  padding-right: 34px !important;
  cursor: pointer;
}
select::-ms-expand { display: none; }
select:disabled { cursor: not-allowed; opacity: 0.65; }

/* ============================================================
   Aufgeklappte Auswahlliste
   ------------------------------------------------------------
   Der GESCHLOSSENE Zustand war schon immer gestaltet (oben:
   appearance:none plus eigener Pfeil). Die aufgeklappte Liste dagegen
   zeichnete bisher das Betriebssystem: Systemschrift, grellblaue
   Markierung, eckiger weisser Kasten - mitten in einer Anwendung mit
   Serifen-Ueberschriften, warmen Papiertoenen und abgerundeten Feldern ein
   deutlicher Bruch. Klassisch war daran nichts zu aendern: die Liste lag
   ausserhalb der Reichweite von CSS.

   appearance:base-select aendert das - damit werden Auswahlfeld UND Liste
   zu regulaer gestaltbaren Elementen. Alles steht in einem
   @supports-Block: Browser ohne Unterstuetzung (derzeit Firefox und
   Safari) ueberspringen ihn vollstaendig und behalten den bisherigen,
   funktionierenden Zustand - gestaltetes Feld, System-Liste. Es geht also
   nichts verloren, es kommt nur etwas hinzu.
   ============================================================ */
@supports (appearance: base-select) {
  select,
  ::picker(select) {
    appearance: base-select;
  }

  select {
    /* Der eigene Hintergrund-Pfeil von oben entfaellt hier - in dieser
       Betriebsart gibt es dafuer ::picker-icon, sonst staenden zwei
       Pfeile nebeneinander. */
    background-image: none;
    padding-right: 14px !important;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    text-align: left;
  }
  select::picker-icon {
    color: var(--ink-light);
    transition: transform 0.18s ease;
  }
  select:open::picker-icon { transform: rotate(180deg); }

  /* Die Liste selbst */
  ::picker(select) {
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface);
    box-shadow: var(--shadow);
    padding: 6px;
    margin-top: 6px;
    max-height: 320px;
    overflow-y: auto;
  }

  option {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 9px 12px;
    border-radius: 7px;
    font-family: var(--font-body);
    font-size: 14px;
    color: var(--text);
    background: transparent;
    cursor: pointer;
  }
  /* Grellblaue System-Markierung ersetzt durch den ruhigen Blauton, der
     in der Anwendung ohnehin fuer Hinweisflaechen steht. */
  option:hover,
  option:focus { background: var(--info-bg); color: var(--heading); }
  option:checked { background: var(--stamp-accent-bg); color: var(--accent-ink); font-weight: 600; }
  option:disabled { color: var(--muted); cursor: not-allowed; }

  /* Der Haken vor dem gewaehlten Eintrag bekommt eine feste Breite, damit
     die Beschriftungen aller Eintraege buendig untereinander stehen -
     ohne das ruecken ausgewaehlte Zeilen sichtbar ein. */
  option::checkmark {
    width: 14px;
    flex-shrink: 0;
    color: var(--accent);
  }
}

.field-hint {
  font-size: 12px;
  color: var(--muted);
  margin-top: 4px;
}

.req-mark {
  color: var(--danger);
  margin-left: 2px;
}

.password-requirements {
  list-style: none;
  margin: 0 0 14px;
  padding: 0;
  font-size: 12px;
  color: var(--muted);
}
.password-requirements li { padding: 2px 0 2px 20px; position: relative; }
.password-requirements li::before {
  content: "○";
  position: absolute; left: 0;
}
.password-requirements li.met { color: var(--success); }
.password-requirements li.met::before { content: "●"; }

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  border: none;
  border-radius: 8px;
  padding: 10px 18px;
  font-size: 14px;
  font-weight: 600;
  transition: transform 0.05s ease, opacity 0.15s ease;
}

.btn:active { transform: translateY(1px); }

.btn-primary {
  background: var(--ink);
  color: #fff;
  width: 100%;
}
.btn-primary:hover { background: var(--ink-light); }

.btn-secondary {
  background: transparent;
  color: var(--heading);
  border: 1px solid var(--rand-bedienelement);
  width: 100%;
  margin-top: 8px;
}
.btn-secondary:hover { border-color: var(--heading); }

.btn-accent {
  background: var(--accent);
  /* Nicht weiss: gemessen 3,36:1 hell und 2,17:1 dunkel. Siehe
     --auf-akzent bei :root. */
  color: var(--auf-akzent);
}
.btn-accent:hover { opacity: 0.9; }

/* Sekundäre Aktionen ("Bearbeiten", "Löschen", "Abbrechen", "Alle
   ansehen", "+ Position hinzufügen"): früher komplett ohne Rahmen und
   Hintergrund - dadurch waren sie in den Tabellenzeilen von normalem
   Text nicht zu unterscheiden und wurden schlicht nicht als anklickbar
   erkannt. Ein dezenter Rahmen gibt ihnen eine erkennbare Schaltflächen-
   Form, ohne der Hauptaktion (btn-accent) die Aufmerksamkeit zu nehmen. */
.btn-ghost {
  background: var(--surface);
  color: var(--heading);
  border: 1px solid var(--rand-bedienelement);
  padding: 8px 14px;
}
.btn-ghost:hover { background: var(--info-bg); border-color: var(--muted); }

.btn-danger-ghost {
  background: var(--surface);
  color: var(--danger);
  border: 1px solid var(--rand-bedienelement);
  padding: 7px 12px;
  font-size: 13px;
}
.btn-danger-ghost:hover { background: var(--danger-bg); border-color: var(--danger); }

.btn-danger {
  background: var(--danger-flaeche);
  color: #fff;
}
.btn-danger:hover { opacity: 0.9; }

.btn-sm { padding: 6px 12px; font-size: 13px; }

.auth-toggle {
  text-align: center;
  font-size: 13px;
  color: var(--muted);
  margin-top: 18px;
}
.auth-toggle button {
  background: none;
  border: none;
  color: var(--heading);
  font-weight: 600;
  text-decoration: underline;
  padding: 0;
}

.turnstile-field {
  margin-top: 14px;
  display: flex;
  justify-content: center;
}

.error-banner {
  background: var(--danger-bg);
  color: var(--danger);
  border-radius: 8px;
  padding: 10px 12px;
  font-size: 13px;
  margin-bottom: 14px;
}

.info-banner {
  background: var(--info-bg);
  color: var(--heading);
  border-radius: 8px;
  padding: 10px 12px;
  font-size: 13px;
  margin-bottom: 14px;
}

/* ---------- App Shell ---------- */

#app-shell {
  display: grid;
  grid-template-columns: 232px 1fr;
  min-height: 100vh;
}

.sidebar {
  background: var(--ink);
  color: #fff;
  padding: 24px 16px;
  display: flex;
  flex-direction: column;
  /* Ohne "sticky" ist die Sidebar nur ein normales Grid-Item: wird der
     Hauptinhalt (z.B. das lange Firmenprofil-Formular) höher als der
     Viewport, wächst #app-shell insgesamt mit - die Sidebar wächst als
     Grid-Item gleich mit und scrollt komplett aus dem Bild, sodass
     Nutzer:in-Kennung/"Abmelden" im sidebar-footer erst nach Runterscrollen
     sichtbar sind. "position: sticky" + "height: 100vh" hält die Sidebar
     dagegen dauerhaft am Viewport-Rand fixiert, unabhängig davon, wie lang
     der Inhalt daneben ist. */
  position: sticky;
  top: 0;
  height: 100vh;
  overflow-y: auto;
}

.sidebar .brand-mark {
  padding: 0 8px;
  margin-bottom: 32px;
  /* Ist jetzt ein <button> (führt zur Übersicht), nicht mehr nur ein <div> -
     Button-Grundstile zurücksetzen, damit es weiterhin wie reine Markenoptik
     aussieht statt wie ein Formular-Button. */
  background: none;
  border: none;
  cursor: pointer;
  width: 100%;
  text-align: left;
  font: inherit;
}
/* OFFEN (17.09.2026): --accent auf dem Navy der Seitenleiste kommt auf
   4,23:1, und der Markenname steht in 20px/600 - nach WCAG ist das noch
   normaler Text, verlangt also 4,5. Nicht geaendert, weil beide Auswege
   eine Markenentscheidung waeren: ein helleres Gold oder gar kein
   Farbwechsel. Dem Betrieb vorgelegt. Siehe AKZENT_AUSNAHMEN in
   tests/test_kontrast.py. */
.sidebar .brand-mark:hover .brand-name { color: var(--accent); }
.sidebar .brand-name { color: #fff; }
.sidebar .brand-sub { color: rgba(255,255,255,0.55); }

.nav-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  border-radius: 8px;
  color: rgba(255,255,255,0.75);
  font-size: 14px;
  font-weight: 500;
  background: transparent;
  border: none;
  width: 100%;
  text-align: left;
  margin-bottom: 2px;
}
.nav-item:hover { background: rgba(255,255,255,0.08); color: #fff; }
.nav-item.active { background: rgba(255,255,255,0.14); color: #fff; }
.nav-item .dot { width: 6px; height: 6px; border-radius: 50%; background: var(--accent); opacity: 0; }
.nav-item.active .dot { opacity: 1; }

/* Die einzige Schaltflaeche in der Leiste - und die einzige Stelle dort,
   die die Akzentfarbe traegt. Genau das ist ihr Zweck: sie ist keine der
   Zeilen darunter, sondern der Anfang von Arbeit. */
.nav-tat {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  width: 100%;
  border: none;
  border-radius: 8px;
  background: var(--accent);
  color: var(--auf-akzent);
  font-family: inherit;
  font-size: 14px;
  font-weight: 600;
  padding: 12px;
  cursor: pointer;
  margin-bottom: 14px;
}
.nav-tat:hover { background: #A0701F; }
.nav-tat-kreuz { font-size: 17px; line-height: 1; }

/* Schiebt "Einstellungen" ans untere Ende. Der Strich darunter gehoert zum
   Fussbereich - deshalb traegt AUSSCHLIESSLICH dieser Punkt das
   margin-top:auto: haetten beide es, teilten sie sich den freien Platz und
   "Einstellungen" landete auf halber Hoehe. */
.nav-unten { margin-top: auto; }

.sidebar-footer {
  padding-top: 16px;
  border-top: 1px solid rgba(255,255,255,0.12);
}
/* Die E-Mail-Adresse steht auf DERSELBEN Linie wie „Einstellungen" darueber
   und „Abmelden" darunter (N6, vom Betrieb am 17.09.2026 gemeldet).
   Gemessen stand sie bei 16px, die Beschriftungen bei 44px - das Auge liest
   eine linke Kante, und eine, die um 28px danebenliegt, sieht nach Versehen
   aus.
   Die 28px sind keine geratene Zahl, sondern die drei Teile, die einen
   Menuepunkt einruecken: sein Innenabstand, der Punkt davor und der Abstand
   dazwischen. Aendert sich einer davon, wandert die Adresse mit. */
.sidebar-user {
  font-size: 12px;
  line-height: 1.35;
  color: rgba(255,255,255,0.55);
  padding: 0 8px 10px calc(12px + 6px + 10px);
  /* Seit N10 steht hier der FIRMENNAME, und der Betrieb hat dazu eine
     klare Vorgabe gemacht: der ganze Name muss zu sehen sein, egal wie
     lang er ist. Also KEINE Auslassung - er bricht um.
     Am 17.09.2026 stand hier noch das Gegenteil (nowrap + ellipsis) fuer
     die E-Mail-Adresse: eine Adresse ist eine Kennung, die man wiedererkennt;
     ein Name ist ein Name, und ein halber Name ist falsch.
     `hyphens: auto` wirkt, weil das Dokument lang="de" traegt - deutsche
     Zusammensetzungen ("Krankentransportunternehmen") werden damit an der
     richtigen Stelle getrennt statt mitten in der Silbe.
     `overflow-wrap: break-word` ist nur die Notbremse fuer ein einzelnes
     Wort, das breiter ist als die Leiste. */
  hyphens: auto;
  overflow-wrap: break-word;
}

/* Der Inhaltsbereich füllt die volle Fensterbreite neben der Sidebar.
   Früher stand hier ein harter Deckel von 1080px - auf einem üblichen
   1920px-Bildschirm blieben dadurch rund 500px rechts dauerhaft
   ungenutzt, während Rechnungs- und Kundentabellen daneben umbrachen.
   Damit der gewonnene Platz nicht zu überlangen Zeilen führt, wachsen
   die Formularraster jetzt in der Spaltenzahl mit (siehe .form-grid) -
   statt dieselben zwei Spalten immer breiter zu ziehen.
   min-width:0 ist im Grid-Kontext nötig, damit breite Tabellen den
   Bereich nicht über die Fensterbreite hinaus aufdehnen, sondern in
   ihrem eigenen Scroll-Container bleiben (siehe .card:has(.data-table)). */
.main {
  padding: 32px 40px 60px;
  min-width: 0;
}

.page-header {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  margin-bottom: 24px;
  gap: 16px;
  flex-wrap: wrap;
}

/* Auch der Seitentitel laeuft in Inter: die Serifenschrift wirkte hier
   selbst bei 28px aufgesetzt, weil direkt darunter alles sachlich weiter
   geht. Fraunces bleibt der Marke vorbehalten - Wortmarke, Startseite,
   Anmeldung. Damit traegt der Titel ueber Gewicht und engeren Satz statt
   ueber eine zweite Schriftart. */
/* Der Kopf eines REITERS, nicht einer Seite. Unter der Überschrift
   „Einstellungen" darf kein zweites h1 stehen - für eine Vorlesehilfe wären
   das zwei gleichrangige Titel auf einer Seite. Die Zeile trägt trotzdem
   ihre Bedienelemente weiter (Knopf „Neuen Kunden anlegen", Kundennummer),
   deshalb bleibt sie ein .page-header. */
.page-header h2 {
  font-size: 21px;
  font-weight: 700;
  line-height: 1.25;
  letter-spacing: -0.015em;
  color: var(--heading);
  margin: 0 0 4px;
}

.page-header h1 {
  font-size: 28px;
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: -0.022em;
  color: var(--heading);
  margin: 0 0 4px;
}
.page-header p { color: var(--muted); font-size: 14px; margin: 0; }

.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 24px;
  margin-bottom: 24px;
}

.card h2 {
  font-family: var(--font-body);
  font-size: 16px;
  font-weight: 600;
  line-height: 1.35;
  letter-spacing: -0.005em;
  color: var(--heading);
  margin: 0 0 18px;
}

/* ---------- Dashboard ---------- */

.dashboard-alert {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  background: var(--info-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 14px 18px;
  margin-bottom: 16px;
  font-size: 14px;
  color: var(--text);
}
.dashboard-alert.warn { background: var(--danger-bg); }
.dashboard-alert p { margin: 0; }

/* ---------- Einstiegsführung ("Erste Schritte") ----------
   Ersetzt die frueheren, einzeln nacheinander auftauchenden Hinweiskaesten
   (siehe app.js: renderOnboarding). Alle Schritte sind gleichzeitig
   sichtbar, damit man von Anfang an weiss, was noch kommt. */
.onboarding-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 22px 24px;
  margin-bottom: 20px;
}
.onboarding-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 18px;
}
.onboarding-head h2 {
  font-family: var(--font-body);
  letter-spacing: -0.005em;
  font-size: 18px;
  font-weight: 600;
  color: var(--heading);
  margin: 0 0 4px;
}
.onboarding-head p { margin: 0; font-size: 13px; color: var(--muted); }
.onboarding-progress {
  flex-shrink: 0;
  font-family: var(--font-mono);
  font-size: 13px;
  font-weight: 600;
  color: var(--accent-ink);
  background: var(--stamp-accent-bg);
  border-radius: 999px;
  padding: 5px 13px;
}

.onboarding-steps { list-style: none; margin: 0; padding: 0; }
.onboarding-step {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 13px 0;
  border-top: 1px solid var(--border);
}
.onboarding-step:first-child { border-top: none; }

/* Rundes Feld links: Schrittnummer, nach Erledigung ein Haken. */
.onboarding-marke {
  flex-shrink: 0;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 13px;
  font-weight: 600;
  font-family: var(--font-mono);
  background: var(--info-bg);
  color: var(--muted);
  border: 1px solid var(--border);
}
.onboarding-marke svg { width: 15px; height: 15px; }
.onboarding-step.aktiv .onboarding-marke {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--auf-akzent);
}
.onboarding-step.erledigt .onboarding-marke {
  background: var(--success-bg);
  border-color: var(--success);
  color: var(--success);
}

.onboarding-inhalt { flex: 1; min-width: 0; }
.onboarding-titel { font-weight: 600; color: var(--heading); font-size: 14px; }
.onboarding-text { font-size: 13px; color: var(--muted); margin-top: 2px; line-height: 1.45; }
/* Erledigte Schritte treten zurueck, ohne zu verschwinden - so bleibt der
   Fortschritt sichtbar. */
.onboarding-step.erledigt .onboarding-titel { color: var(--muted); text-decoration: line-through; }
.onboarding-fertig {
  flex-shrink: 0;
  font-size: 12px;
  font-weight: 600;
  color: var(--success);
}

@media (max-width: 620px) {
  .onboarding-step { flex-wrap: wrap; }
  .onboarding-step .btn { margin-left: 42px; }
  /* Ohne eine Untergrenze schrumpft der Inhalt beliebig, statt umzubrechen:
     „flex-wrap: wrap" springt nie an, und der Text quetschte sich am Telefon
     auf 71px und elf Zeilen neben den Knopf (gemessen, 16.09.2026). 160px ist
     die Breite, unter der ein Satz nicht mehr zu lesen ist; das kurze Wort
     „Erledigt" passt daneben weiterhin in dieselbe Zeile. */
  .onboarding-inhalt { min-width: 160px; }
}

.metric-cards {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 14px;
  margin-bottom: 24px;
}
.metric-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 16px 18px;
}
/* "Umsatz im September" ist eine Bildunterschrift, keine Spaltenüberschrift -
   in Versalien las sie sich als drei zusammenhanglose Wörter. */
.metric-card .metric-label {
  font-size: 12px;
  color: var(--muted);
  font-weight: 600;
  margin-bottom: 6px;
}
.metric-card .metric-value {
  font-size: 26px;
  font-weight: 700;
  line-height: 1.15;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
  color: var(--heading);
}
.metric-card .metric-value.metric-warn { color: var(--danger); }
.metric-card .metric-sub { font-size: 12px; color: var(--muted); margin-top: 2px; }

@media (max-width: 900px) {
  .metric-cards { grid-template-columns: 1fr 1fr; }
}

/* Spaltenzahl wächst mit der verfügbaren Breite mit (2 Spalten bei ~600px,
   4 bei ~1200px, 5-6 auf sehr breiten Bildschirmen), statt zwei feste
   Spalten immer weiter auseinanderzuziehen. 260px ist die Untergrenze,
   ab der ein Eingabefeld mit Label noch bequem lesbar bleibt. */
.form-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 14px 16px;
}
.form-grid .field.full { grid-column: 1 / -1; }

/* Ein einzelnes kurzes Feld über einer Paarzeile (der Tag über „Von/Ort"):
   allein im Raster zöge es sich über die ganze Karte, während darunter zwei
   Felder nebeneinander stehen. Es soll so breit sein wie das Feld darunter -
   halbe Karte minus halber Spaltenabstand (16px, siehe .form-grid). */
.form-grid.einzelfeld { grid-template-columns: minmax(0, calc(50% - 8px)); }

.checkbox-field {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  grid-column: 1 / -1;
  background: var(--info-bg);
  padding: 12px 14px;
  border-radius: 8px;
}
.checkbox-field input { width: auto; margin-top: 3px; }
.checkbox-field .label-text { font-size: 13px; }
.checkbox-field .label-text strong { display: block; font-size: 14px; color: var(--heading); margin-bottom: 2px; }

/* ---------- Tables / Lists ---------- */

.card:has(.data-table) {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

.data-table { width: 100%; border-collapse: collapse; }
.data-table th {
  text-align: left;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--muted);
  font-weight: 600;
  padding: 0 10px 10px;
  border-bottom: 1px solid var(--border);
}
.data-table td {
  padding: 14px 10px;
  border-bottom: 1px solid var(--border);
  font-size: 14px;
  vertical-align: middle;
}
.data-table tr:last-child td { border-bottom: none; }
/* Rechnungsnummern bleiben in der Schreibmaschinenschrift - sie sind
   Kennungen, die man Zeichen für Zeichen abgleicht. Beträge nicht: dort
   sorgt schon font-variant-numeric fuer gleich breite Ziffern, waehrend
   IBM Plex Mono das Eurozeichen auf dieselbe Breite zwaengt und "26,75 €"
   auseinanderreisst. */
.mono { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
.data-table .num { font-variant-numeric: tabular-nums; letter-spacing: -0.01em; }
/* NICHT display:flex direkt auf die <td class="actions">: ein Flex-
   Container ist kein table-cell mehr und nimmt dadurch nicht mehr an der
   normalen Höhenangleichung der Tabellenzeile teil - die Zelle blieb dann
   kürzer als ihre Geschwisterzellen, wodurch die Trennlinien zwischen den
   Zeilen sichtbar versetzt waren. Der Flex-Layout sitzt stattdessen auf
   einem inneren Wrapper (.actions-inner), die <td> selbst bleibt ein
   normales, höhenangeglichenes table-cell. */
.data-table .actions-inner { display: flex; gap: 6px; justify-content: flex-end; align-items: center; flex-wrap: wrap; position: relative; }
/* Am Telefon sind DIESE Knöpfe die Arbeit an einer Rechnung - „PDF",
   „Transportscheine", „Abrechnen", „Per E-Mail senden". Mit den 28px von
   .btn-sm trifft man sie mit dem Daumen schlecht, und das Dreipunktmenü
   steht unmittelbar daneben: daneben zu greifen heißt hier, das falsche
   zu treffen (WCAG SC 2.5.5 verlangt 44px).
   Vom Betrieb am 17.09.2026 entschieden, nachdem der Funktionsdurchlauf
   sie gemessen und die Gegenüberstellung vorgelegen hatte. Gemessener
   Preis: die Rechnungsliste wächst von 3661 auf 3835px, also 4,8 % -
   weniger als eine halbe Bildschirmhöhe über neun Rechnungen.
   640px wie bei .trip-block-actions und .belege-aktionen, den beiden
   Stellen, an denen dieselbe Entscheidung schon getroffen wurde -
   .btn-sm bleibt ÜBERALL SONST klein, so ist sie gemeint. */
@media (max-width: 640px) {
  .data-table .actions-inner .btn { min-height: 44px; }
  /* Das Dreipunktmenü ist quadratisch - ohne die Breite bliebe es ein
     schmaler hoher Streifen zwischen zwei breiten Knöpfen. */
  .data-table .actions-inner .btn-icon { min-width: 44px; }
}
.data-table .row-title { font-weight: 600; color: var(--heading); }
.data-table .row-sub { font-size: 12px; color: var(--muted); }

/* Zeilen-Aktionen (Rechnungsliste): statt bis zu 6 nebeneinander
   gestapelten Text-Buttons pro Zeile (unübersichtlich, besonders in der
   mobilen Kartenansicht) nur noch die wichtigste nächste Aktion + PDF
   direkt sichtbar, alles Weitere (XML, Mahnung, Löschen) hinter einem
   "Weitere Aktionen"-Menü (siehe renderInvoices/toggleRowMenu in app.js). */
.btn-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  padding: 0;
  border-radius: var(--radius);
  border: 1px solid var(--rand-bedienelement);
  background: var(--surface);
  color: var(--heading);
  cursor: pointer;
  flex-shrink: 0;
}
.btn-icon:hover { background: var(--info-bg); }
.btn-icon svg { width: 17px; height: 17px; }
.btn-with-icon { display: inline-flex; align-items: center; gap: 6px; }
.btn-with-icon svg { width: 15px; height: 15px; flex-shrink: 0; }

.row-menu { display: inline-flex; }
/* position:fixed statt absolute + JS-berechnete top/left (siehe
   toggleRowMenu in app.js): die Rechnungstabelle steckt in einer Karte mit
   overflow-x:auto (siehe .card:has(.data-table) oben) - sobald EINE Achse
   eines Elements nicht "visible" ist, rechnet der Browser laut CSS-Spec
   automatisch auch die andere Achse als "auto" statt "visible", auch wenn
   nur overflow-x gesetzt wurde. Ein absolut positioniertes Menü innerhalb
   dieser Karte wurde dadurch am unteren Kartenrand abgeschnitten
   (unsichtbarer zweiter Menüpunkt). position:fixed entzieht sich jeder
   Vorfahren-Overflow-Begrenzung, da es relativ zum Viewport positioniert
   wird.
*/
.row-menu-list {
  position: fixed;
  /* Breiter als früher (220px): die Einträge benennen jetzt zusätzlich das
     Ergebnis der Aktion ("Stornieren - erzeugt eine Gutschrift") und
     tragen ein Symbol, damit man sie im Menü auch ohne Lesen wiederfindet. */
  width: 290px;
  max-width: calc(100vw - 16px);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 6px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  z-index: 200;
}
.row-menu-list.hidden { display: none; }
.row-menu-list button {
  display: flex;
  align-items: center;
  gap: 9px;
  width: 100%;
  text-align: left;
  padding: 9px 10px;
  border: none;
  background: none;
  border-radius: 6px;
  font-size: 13px;
  line-height: 1.35;
  color: var(--heading);
  cursor: pointer;
  font-family: inherit;
}
.row-menu-list button svg {
  width: 15px;
  height: 15px;
  flex-shrink: 0;
  color: var(--muted);
}
.row-menu-list button:hover { background: var(--info-bg); }
.row-menu-list button:hover svg { color: inherit; }
.row-menu-list button.danger { color: var(--danger); }
.row-menu-list button.danger svg { color: var(--danger); }
.row-menu-list button.danger:hover { background: var(--danger-bg); }

/* Leerzustaende bieten jetzt eine Handlung an, statt den Zustand nur zu
   beschreiben (siehe app.js: renderInvoices/renderCustomers) - der Knopf
   braucht deshalb etwas Luft nach oben. */
/* Der leere Anfang. OHNE Zeichen darueber: bis zum 11.09.2026 stand in
   allen zehn Leerzustaenden ein "§" in 32px Fraunces. Ob das Absicht war -
   die Anwendung rechnet nach § 302 SGB V ab - oder ein nie ersetzter
   Platzhalter, liess sich am Code nicht entscheiden. Der Betrieb hat
   entschieden: ganz weg. Ein Leerzustand braucht kein Bild, um verstanden
   zu werden; der Satz sagt es. */
.empty-state {
  text-align: center;
  padding: 48px 20px;
  color: var(--muted);
}
.empty-state .btn { margin-top: 16px; }
.empty-state p { margin: 4px 0; font-size: 14px; }

/* ---------- Status Stamp (Signature-Element) ---------- */

.stamp {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 4px 10px;
  border-radius: 20px;
  border: 1.5px dashed currentColor;
  transform: rotate(-1.5deg);
}
.stamp.draft { color: var(--muted); background: var(--stamp-draft-bg); }
/* Abgeschlossen: dasselbe Feld wie der Entwurf, aber mit DURCHGEZOGENEM
   Rand und in Textfarbe statt gedaempft. Der gestrichelte Rand ist das
   Zeichen fuer "vorlaeufig" - ein Dokument mit Nummer und Papier ist das
   nicht mehr. Bewusst NICHT die Akzentfarbe von .sent: verschickt ist es
   ja gerade noch nicht, und zwei gleich aussehende Staende waeren schlimmer
   als der falsche Text vorher. Kein neues Farbtoken (20.09.2026, E2.1). */
.stamp.final {
  color: var(--heading);
  background: var(--stamp-draft-bg);
  border-style: solid;
}
.stamp.sent { color: var(--accent-ink); background: var(--stamp-accent-bg); }
.stamp.paid { color: var(--success); background: var(--success-bg); }
.stamp.cancelled { color: var(--danger); background: var(--danger-bg); }
/* Gekuerzt: die Kasse hat weniger ueberwiesen, als auf der Rechnung steht
   (E7.7, 20.09.2026). Bewusst NICHT die Aufmachung von .cancelled -
   storniert und gekuerzt sind zwei verschiedene Dinge, und zwei gleich
   aussehende Staende waeren schlimmer als gar keine Marke (dieselbe
   Ueberlegung wie bei .final gegen .sent). Rot als SCHRIFT auf dem ruhigen
   Feld des Entwurfs, mit durchgezogenem Rand: es ist eine festgestellte
   Tatsache, kein Vorbehalt. Gemessen: 4,66:1 im Hellen, 4,56:1 im
   Dunklen. Kein neues Farbtoken. */
.stamp.gekuerzt {
  color: var(--danger);
  background: var(--stamp-draft-bg);
  border-style: solid;
}
.stamp.credit-note { color: var(--accent-ink); background: var(--stamp-accent-bg); font-size: 10px; padding: 2px 8px; transform: none; }

.toolbar { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }

/* ---------- In-App-Bestätigungsdialog (statt window.confirm) ---------- */

.confirm-dialog-overlay {
  position: fixed;
  inset: 0;
  background: rgba(15, 23, 42, 0.5);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  z-index: 500;
}
.confirm-dialog-card {
  background: var(--surface);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 24px;
  max-width: 380px;
  width: 100%;
}
.confirm-dialog-card p {
  margin: 0 0 20px;
  font-size: 14px;
  color: var(--text);
  line-height: 1.5;
}
.confirm-dialog-actions {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
}
.confirm-dialog-actions .btn { width: auto; }

/* Hell-/Dunkelmodus-Umschalter - fest positioniert, auf jedem Screen
   sichtbar (siehe index.html: einmalig direkt nach <body>). Zeigt per CSS
   (nicht JS) je nach aktivem Modus Sonne oder Mond - ein Icon ist per
   Default versteckt, [data-theme] auf <html> blendet das jeweils
   passende ein/aus. */
/* Rückweg zur Startseite auf der Anmelde-/Registrier-/Bestätigungsseite.
   Vorher gab es dort GAR KEINEN Weg zurück - wer aus Versehen auf
   "Anmelden" geklickt hatte, kam nur über die Zurück-Taste des Browsers
   wieder heraus.
   Sitzt oben links und spiegelt damit den Hell-/Dunkel-Umschalter oben
   rechts. Liegt fest im Sichtfenster (nicht in der Karte), damit er auch
   bei der langen Registrierungsmaske immer sichtbar bleibt - dort ist der
   Karteninhalt deutlich höher als der Bildschirm. */
/* Der Rückweg (L9). Bis zum 11.09.2026 eine schwebende Pille oben links,
   position: fixed - sie klebte am Fensterrand, nicht an der Karte, und
   stand damit diagonal gegenüber dem Hell-/Dunkel-Knopf oben rechts wie
   ein zweiter Hauptknopf. Auf schmalen Displays verlor sie zudem ihre
   Beschriftung und wurde zum blossen Pfeil im Nichts.

   Jetzt steht er IN der Karte, über dem Markenzeichen: ein leiser
   Textverweis, der zur Karte gehört, mitwandert und seine Beschriftung
   in jeder Breite behält. */
.auth-back {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin: -6px 0 18px -4px;
  padding: 4px;
  border-radius: 8px;
  color: var(--muted);
  font-family: var(--font-body);
  font-size: 13px;
  font-weight: 600;
  text-decoration: none;
  transition: color 0.15s ease;
}
.auth-back svg { width: 15px; height: 15px; transition: transform 0.15s ease; }
.auth-back:hover { color: var(--heading); }
/* Der Pfeil wandert beim Zeigen leicht nach links - eine kleine
   Rückmeldung, die die Richtung der Aktion unterstreicht. */
.auth-back:hover svg { transform: translateX(-2px); }

.theme-toggle-btn {
  position: fixed;
  top: 16px;
  right: 16px;
  z-index: 200;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--heading);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  box-shadow: var(--shadow);
  font-size: 16px;
  line-height: 1;
  padding: 0;
}
.theme-toggle-btn:hover { border-color: var(--heading); }
/* Echte Strichzeichnungen statt der Textzeichen ☀/☾. Die sassen schief
   im Kreis, weil jede Schrift sie anders setzt - und neben den uebrigen
   Symbolen der Anwendung (alle 2px Strich, 24er Raster) sahen sie wie ein
   Fremdkoerper aus. */
.theme-toggle-btn svg { width: 18px; height: 18px; display: block; }
.theme-toggle-icon { display: inline-flex; }

/* Der Mond GROESSER als die Sonne - und das ist kein Versehen.
   Eine Sichel fuellt ihr Quadrat deutlich schlechter als eine Scheibe mit
   acht Strahlen: bei gleicher Kantenlaenge wirkt sie kleiner. Ausgeglichen
   wird optisch, nicht rechnerisch, wie bei Schriftgraden auch. */
.theme-zeichen-mond svg { width: 21px; height: 21px; }
/* Dreifachwahl fuers Erscheinungsbild: drei Schalter nebeneinander in einem
   Rahmen. Die Beschriftung steht daneben, deshalb ist hier - anders als beim
   Knopf oben rechts - eine Zustandsanzeige richtig. */
.segmentwahl {
  display: inline-flex;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--surface);
  max-width: 100%;
}
.segmentwahl label {
  position: relative;
  flex: 1 1 auto;
  min-width: 92px;
  text-align: center;
  padding: 10px 16px;
  font-size: 14px;
  font-weight: 600;
  color: var(--muted);
  cursor: pointer;
  white-space: nowrap;
  transition: background 0.12s, color 0.12s;
}
.segmentwahl label + label { border-left: 1px solid var(--border); }
/* Der eigentliche Schalter bleibt bedienbar und fuer Vorlesehilfen sichtbar,
   liegt aber unter der Beschriftung - display:none nimmt ihn sonst aus der
   Tastaturbedienung. */
.segmentwahl input {
  position: absolute;
  inset: 0;
  opacity: 0;
  margin: 0;
  cursor: pointer;
}
.segmentwahl label:hover { background: var(--stamp-draft-bg); color: var(--heading); }
/* Der gewaehlte Schalter kehrt die Farben um. --ink waere im Dunkelmodus
   fast so dunkel wie die Karte gewesen und die Wahl damit kaum erkennbar;
   --heading dreht in beiden Themes auf die Gegenseite. */
.segmentwahl label:has(input:checked) {
  background: var(--heading);
  color: var(--surface);
}
.segmentwahl label:has(input:focus-visible) {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}
@media (max-width: 480px) {
  .segmentwahl { display: flex; width: 100%; }
  .segmentwahl label { min-width: 0; padding: 12px 8px; }
}

/* Das Symbol zeigt die AKTION, nicht den Zustand: im Dunkelmodus steht dort
   die Sonne ("hierhin wechseln"), im Hellmodus der Mond. Andersherum - der
   Knopf zeigt, wo man gerade ist - liest sich ein Knopf ohne Beschriftung
   falsch: ein Mond im dunklen Bild legt nahe, es werde noch dunkler. Die
   Zustandsanzeige funktioniert nur, wenn ein Wort danebensteht; genau das
   leistet die Dreifachwahl im Konto. */
/* Gezeigt wird, wohin man WECHSELT, nicht wo man ist: im Hellmodus der
   Mond („zum Dunkelmodus"), im Dunkelmodus die Sonne. Deshalb trägt die
   Zeile in der Leiste auch einen Namen - ein Symbol allein lässt offen,
   ob es den Zustand zeigt oder das Ziel.

   Die beiden Klassen gelten für das Symbol UND für seine Beschriftung,
   damit beide immer zusammen umschalten. Zwei getrennte Regeln liefen
   irgendwann auseinander, und dann stünde die Sonne neben
   „Dunkelmodus". */
.theme-zeichen-sonne { display: none; }
:root[data-theme="dark"] .theme-zeichen-mond { display: none; }
:root[data-theme="dark"] .theme-zeichen-sonne { display: inline-flex; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .theme-zeichen-mond { display: none; }
  :root:not([data-theme="light"]) .theme-zeichen-sonne { display: inline-flex; }
}
/* Auf Mobile verdeckte die feste Topbar (z-index 220) den Umschalter oben
   rechts. Er wich deshalb nach UNTEN LINKS aus - schwebte dort aber
   dauerhaft über dem Inhalt und verdeckte je nach Scrollposition Text in
   den Karten.
   Jetzt sitzt er stattdessen IN der Topbar: deren rechte Hälfte ist ohnehin
   leer (Menüknopf und Marke enden bei ~167px von 390px), und mit einem
   höheren z-index sowie auf den dunklen Untergrund abgestimmten Farben
   wirkt er wie ein regulärer Bestandteil der Leiste statt wie ein
   Fremdkörper davor. */
@media (max-width: 780px) {
  body:has(#app-shell) .theme-toggle-btn {
    top: 9px;
    right: 12px;
    bottom: auto;
    left: auto;
    z-index: 230;
    background: rgba(255, 255, 255, 0.10);
    border-color: rgba(255, 255, 255, 0.22);
    color: #fff;
  }
  body:has(#app-shell) .theme-toggle-btn:hover {
    background: rgba(255, 255, 255, 0.18);
    border-color: rgba(255, 255, 255, 0.45);
  }
  /* Öffentliche Seiten (Landing/Anmeldung) haben keine Topbar - für sie
     stand hier bis zum 11.09.2026 noch der alte Ausweichplatz UNTEN LINKS.
     Der Grund dafür war längst weg: ausgewichen wurde ursprünglich vor der
     festen Topbar, und die gibt es hier gar nicht. Übrig blieb ein Knopf,
     der am Telefon woanders saß als am Schreibtisch (L13, vom Betrieb
     bestätigt: "oben rechts").

     Die Regel ist ersatzlos gestrichen - ohne sie greift der Grundwert
     oben (top/right 16px), derselbe wie am Schreibtisch. */
}

/* Worauf sich die Zahlen im Summenkasten beziehen (E3.8, 20.09.2026).
   Leise: es ist eine Einordnung, keine Zahl. Dieselben Marken wie
   .field-hint - ein eigener Ton waere hier eine Behauptung von
   Wichtigkeit, die der Satz nicht hat. */
/* Tag und Betrag unter der Fahrtenzeile am Schein (E6.4, 20.09.2026).
   Dieselbe Groesse wie die Zeile darueber, aber mit Ziffernsatz: die
   Betraege stehen untereinander und sollen sich vergleichen lassen. */
.fahrt-tag-betrag {
  font-variant-numeric: tabular-nums;
}

.summen-kopf {
  font-size: 12px;
  color: var(--muted);
  padding-bottom: 6px;
  margin-bottom: 6px;
  border-bottom: 1px solid var(--border);
}

.toast {
  position: fixed;
  bottom: 24px;
  right: 24px;
  background: var(--ink);
  color: #fff;
  padding: 12px 18px;
  border-radius: 8px;
  font-size: 14px;
  box-shadow: var(--shadow);
  /* UEBER allem, was sich sonst ueber die Seite legt (E3.1, 20.09.2026).
     Bis dahin lag die Meldung auf 100 und jeder Dialog auf 500 - eine
     Meldung, die WAEHREND eines offenen Dialogs kam, war unsichtbar. Das
     traf ausgerechnet die Faelle, in denen sie am noetigsten ist: die
     Saetze, die fehlerZeigen() in die Ecke schickt, wenn er im Dialog kein
     Feld dazu findet (N15), und jeden Serverfehler beim Bestaetigen.
     1000 statt 501, damit zwischen Dialog und Meldung Platz fuer weitere
     Ebenen bleibt; hoeher liegt heute nichts (gemessen: Maximum war 500). */
  z-index: 1000;
  max-width: 360px;
  /* Mehrere Saetze stehen untereinander (toastFehler in 10-foundation.js,
     N15 am 19.09.2026). pre-line und nicht pre: Umbrueche gelten, aber ein
     langer Satz bricht weiterhin selbst um. */
  white-space: pre-line;
}
.toast.error { background: var(--danger); }
.toast-undo { display: flex; align-items: center; gap: 16px; }
.toast-action {
  flex-shrink: 0;
  background: none;
  border: none;
  color: #fff;
  font-weight: 700;
  font-size: 14px;
  text-decoration: underline;
  text-underline-offset: 2px;
  cursor: pointer;
  padding: 0;
  font-family: inherit;
}
.toast-action:hover { opacity: 0.85; }

/* Mobile-Topbar (Logo -> Startseite, Menü-Button -> öffnet Sidebar als
   Drawer) - auf Desktop nie sichtbar, siehe app-shell/app-shell-Regel
   oben ("display:grid") und hier drunter "display:none" als Default. */
.mobile-topbar { display: none; }
.mobile-drawer-backdrop { display: none; }

@media (max-width: 780px) {
  /* display:block statt grid-template-columns:1fr - sonst verteilt CSS Grid
     die durch min-height:100vh entstehende Resthöhe ungleich zwischen der
     (jetzt eigenen) Sidebar-Zeile und der Main-Zeile, statt die Sidebar an
     ihrem tatsächlichen Inhalt auszurichten. */
  #app-shell { display: block; padding-top: 56px; }

  .mobile-topbar {
    display: flex;
    align-items: center;
    gap: 12px;
    position: fixed;
    top: 0; left: 0; right: 0;
    height: 56px;
    padding: 0 16px;
    background: var(--ink);
    z-index: 220;
  }
  .mobile-menu-btn {
    width: 36px;
    height: 36px;
    flex-shrink: 0;
    /* Bezugspunkt fuer den Punkt "es steht etwas an", siehe .menue-punkt. */
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 5px;
    background: none;
    border: none;
    padding: 0;
  }
  .mobile-menu-btn span {
    display: block;
    width: 20px;
    height: 2px;
    border-radius: 2px;
    background: #fff;
    transition: transform 0.2s ease, opacity 0.2s ease;
  }
  /* Vierter <span> im Knopf, deshalb ausdruecklich aus dem Fluss genommen -
     die Regel darueber macht sonst einen vierten Balken daraus. Der Ring in
     der Leistenfarbe setzt ihn vom Zeichen ab, auch wenn er einen Balken
     beruehrt. */
  .mobile-menu-btn .menue-punkt {
    position: absolute;
    top: 2px;
    right: 2px;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: #B3452C;
    box-shadow: 0 0 0 2px var(--ink);
    transition: none;
  }
  /* Im geoeffneten Zustand ist das Zeichen ein Kreuz - der Punkt daran
     waere dann eine Meldung ueber eine Schublade, die bereits offen ist. */
  .mobile-menu-btn.open .menue-punkt { display: none; }

  .mobile-menu-btn.open span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
  .mobile-menu-btn.open span:nth-child(2) { opacity: 0; }
  .mobile-menu-btn.open span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

  .mobile-topbar-brand {
    display: flex;
    align-items: center;
    gap: 9px;
    background: none;
    border: none;
    padding: 0;
  }
  .mobile-topbar-logo { width: 30px; height: 30px; flex-shrink: 0; }
  .mobile-topbar-name {
    font-family: var(--font-display);
    font-weight: 600;
    font-size: 16px;
    color: #fff;
  }

  .mobile-drawer-backdrop.open {
    display: block;
    position: fixed;
    inset: 0;
    background: rgba(15, 23, 42, 0.45);
    z-index: 210;
  }

  /* Die Sidebar bleibt strukturell/optisch die gleiche vertikale Spalte
     wie am Desktop (siehe .sidebar-Basisregel oben: flex-direction:column
     etc. bleibt unverändert gültig) - hier wird sie nur zu einem fixen,
     standardmäßig ausgeblendeten Drawer von links positioniert. */
  .sidebar {
    position: fixed;
    /* Startet UNTER der Topbar (56px), sonst läge die Topbar (höherer
       z-index) über dem oberen Sidebar-Bereich und würde ihn optisch
       abschneiden. */
    top: 56px;
    left: 0;
    bottom: 0;
    /* Setzt die "height: 100vh" der Desktop-Basisregel (siehe .sidebar
       oben, für den sticky-Fix dort) explizit zurück: mit top+bottom UND
       einer festen height von 100vh gleichzeitig ragte die Sidebar 56px
       (die Höhe der Topbar) über den unteren Viewport-Rand hinaus - genau
       so viel fehlte dann von "Abmelden" im sidebar-footer. Ohne feste
       height ergibt sich die Höhe bei position:fixed korrekt aus
       top+bottom (= Viewport-Höhe minus Topbar). */
    height: auto;
    width: 260px;
    max-width: 82vw;
    transform: translateX(-100%);
    transition: transform 0.25s ease;
    z-index: 215;
    overflow-y: auto;
    /* Verhindert Scroll-Chaining: erreicht ein Swipe im Drawer dessen
       oberes/unteres Ende, soll die Geste NICHT an den (jetzt zusätzlich
       per JS gesperrten, siehe _lockBodyScroll in app.js) Hintergrund
       weitergereicht werden. */
    overscroll-behavior: contain;
    box-shadow: 4px 0 24px rgba(0, 0, 0, 0.25);
  }
  .sidebar.open { transform: translateX(0); }
  /* Logo/Markenname stehen bereits dauerhaft in der Topbar - im Drawer
     selbst wäre das doppelt. */
  .sidebar .brand-mark { display: none; }

  .main { padding: 20px; }
  .form-grid { grid-template-columns: 1fr; }
  .form-grid.einzelfeld { grid-template-columns: 1fr; }
  /* Leere Spacer-Felder dienen nur der 2-Spalten-Ausrichtung am Desktop -
     auf Mobile (1 Spalte) erzeugen sie sonst eine unmotivierte Lücke. */
  .form-grid .field:empty { display: none; }
  .metric-cards { grid-template-columns: 1fr 1fr; }
  .dashboard-alert { flex-direction: column; align-items: stretch; }

  /* Tabellen (Rechnungen, Kunden, Admin-Nutzer/-Blog/-Abos/-Zahlungen) auf
     einer 390px-Breite mit 4-5 Spalten liefen bisher nur mit unsichtbarem
     Horizontal-Scroll (siehe .card:has(.data-table) oben) - Status und vor
     allem die Aktions-Buttons (Bearbeiten/Löschen/Sperren/PDF/Senden...)
     lagen dadurch faktisch verborgen außerhalb des sichtbaren Bereichs,
     ohne jeden Hinweis, dass dort noch etwas ist. Jede Zeile wird hier
     stattdessen zu einer eigenen, vertikal gestapelten Karte - jede Zelle
     bekommt ihre Spaltenüberschrift als kleines Label direkt über sich
     (per data-label-Attribut in app.js/admin.js, ausgegeben über
     ::before/attr()), außer der ersten Zelle (Titel+Unterzeile, z.B.
     Rechnungsnummer oder Kundenname - selbsterklärend, kein Label nötig). */
  .data-table thead { display: none; }
  .data-table, .data-table tbody, .data-table tr, .data-table td {
    display: block;
    width: 100%;
  }
  .data-table tr {
    padding: 12px 0;
    border-bottom: 1px solid var(--border);
  }
  .data-table tr:last-child { border-bottom: none; }
  .data-table td {
    padding: 3px 0;
    border-bottom: none;
    text-align: left;
  }
  .data-table td[data-label]::before {
    content: attr(data-label);
    display: block;
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--muted);
    font-weight: 600;
    margin-top: 10px;
  }
  .data-table td.actions { margin-top: 4px; }
  .data-table .actions-inner { justify-content: flex-start; }
}

@media (max-width: 480px) {
  #auth-screen, #verify-screen { padding: 16px; }
  .metric-cards { grid-template-columns: 1fr; }
  .auth-card { padding: 28px 20px; }
  .toast { left: 16px; right: 16px; bottom: 16px; max-width: none; }
}

@media (max-width: 780px) {
  .landing-hero { padding: 48px 20px 40px; }
  .landing-stapel,
  .landing-privat,
  .landing-preis { padding: 0 20px 40px; }
  .landing-beweis-schluss { padding: 0 20px 40px; }
  .landing-grenzen { margin: 0 20px 40px; }
  .landing-hero h1 { font-size: 30px; }
  .landing-features { grid-template-columns: 1fr 1fr; padding: 8px 20px 48px; }
  .landing-steps-row { grid-template-columns: 1fr; gap: 28px; }
  .landing-nav { gap: 12px; }
  .plan-grid { grid-template-columns: 1fr; }
}

@media (max-width: 480px) {
  .landing-header-inner { flex-direction: column; align-items: flex-start; gap: 12px; }
  .landing-nav { width: 100%; justify-content: space-between; }
  .landing-features { grid-template-columns: 1fr; }
  .landing-cta-row { flex-direction: column; align-items: stretch; }
  .landing-cta-row .btn { width: 100%; }
}

/* ============================================================
   Logo-Bereich im Firmenprofil
   ------------------------------------------------------------
   Vorher stand dort das rohe Dateifeld des Browsers ("Datei auswählen |
   Keine ausgewählt") in Systemschrift, dazu ein zweiter Knopf zum
   Hochladen und eine Textzeile, die lediglich BEHAUPTETE, ob ein Logo
   hinterlegt ist. Jetzt: Vorschau des tatsächlichen Bildes, eine Fläche
   zum Anklicken oder Hineinziehen, und das Hochladen passiert sofort -
   der zweite Schritt war überflüssig, denn nach dem Auswählen einer Datei
   gibt es keine andere Absicht.
   ============================================================ */
.logo-bereich {
  display: flex;
  align-items: stretch;
  gap: 18px;
  flex-wrap: wrap;
}

.logo-vorschau {
  flex-shrink: 0;
  width: 168px;
  min-height: 116px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--info-bg);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 12px;
  overflow: hidden;
}
/* display:block hier NICHT unbedingt setzen: es würde die Standardregel
   [hidden] { display: none } überstimmen, und das Bild bliebe trotz
   hidden-Attribut sichtbar - mit kaputtem Bildsymbol und Ersatztext, weil
   ohne Logo gar keine Quelle gesetzt ist. Genau das war zu sehen. */
.logo-vorschau img:not([hidden]) { display: block; }
.logo-vorschau img { max-width: 100%; max-height: 92px; object-fit: contain; }
.logo-platzhalter { color: var(--muted); font-size: 13px; }

/* Ablagefläche. <label for> statt eines eigenen Klick-Handlers: damit
   öffnet ein Klick die Dateiauswahl ganz ohne JavaScript, und die Fläche
   bleibt über die Tastatur erreichbar. */
.logo-ablage {
  position: relative;
  flex: 1;
  min-width: 260px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 22px 18px;
  border: 1.5px dashed var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--muted);
  text-align: center;
  cursor: pointer;
  transition: border-color 0.15s ease, background 0.15s ease, color 0.15s ease;
}
.logo-ablage:hover { border-color: var(--accent); color: var(--heading); }
/* Sichtbar, während eine Datei darüber schwebt. */
.logo-ablage.darueber {
  border-color: var(--accent);
  border-style: solid;
  background: var(--stamp-accent-bg);
  color: var(--accent-ink);
}
.logo-ablage.laedt { opacity: 0.6; pointer-events: none; }
.logo-ablage svg { width: 26px; height: 26px; opacity: 0.7; }
.logo-ablage-haupt { font-size: 14px; font-weight: 600; color: inherit; }
/* Ebenfalls ohne opacity, gleicher Grund: .logo-ablage setzt --muted, das
   reicht. Mit der Durchsichtigkeit waren es 3,28:1. */
.logo-ablage-neben { font-size: 12px; }

/* Das eigentliche Dateifeld bleibt im Markup - für Tastaturbedienung und
   Hilfsmittel -, wird aber nicht angezeigt. display:none würde es aus der
   Tastaturreihenfolge nehmen, deshalb stattdessen unsichtbar machen. */
.logo-dateifeld {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}
.logo-dateifeld:focus-visible + * { outline: 2px solid var(--ink); }
.logo-ablage:focus-within { border-color: var(--accent); outline: 2px solid var(--ink); outline-offset: 2px; }

.logo-fusszeile {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  margin-top: 14px;
}

@media (max-width: 560px) {
  .logo-vorschau { width: 100%; }
}

/* ---------- Bestätigung nach dem Hochladen ----------
   Sichtbare Rückmeldung, dass das Bild tatsächlich angekommen ist.
   Bewusst an der Vorschau statt nur als Meldung am Bildschirmrand: dort
   schaut man in diesem Moment ohnehin hin. */

/* Kurzer grüner Rahmen um die Vorschau, unmittelbar nach dem Speichern. */
.logo-vorschau {
  position: relative;
  transition: border-color 0.25s ease, box-shadow 0.25s ease;
}
.logo-vorschau.gespeichert {
  border-color: var(--success);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--success) 22%, transparent);
}

/* Runder Haken, der in die Ecke der Vorschau einspringt. */
.logo-haken {
  position: absolute;
  top: 8px;
  right: 8px;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: var(--success);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  transform: scale(0.4);
  pointer-events: none;
  transition: opacity 0.2s ease, transform 0.25s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.logo-haken svg { width: 15px; height: 15px; }
.logo-vorschau.gespeichert .logo-haken { opacity: 1; transform: scale(1); }

/* Dauerhafte Statuszeile: grün mit Haken, solange ein Logo hinterlegt ist. */
.logo-status {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  color: var(--muted);
}
.logo-status.hinterlegt { color: var(--success); font-weight: 600; }
.logo-status svg { width: 15px; height: 15px; }

/* Bestätigung am Knopf selbst statt als Meldung in der Bildschirmecke.
   Steht bewusst NACH .btn-accent (Zeile ~674): gleiche Spezifität, damit
   die Quellreihenfolge entscheidet und kein !important nötig ist. */
.btn.btn-gespeichert {
  background: var(--success);
  border-color: var(--success);
  /* NICHT hart #fff: im Dunkelmodus ist --success ein helles Grün, auf dem
     weiße Schrift nur 2,7:1 erreicht. --success-fg kippt deshalb pro Modus
     (weiß im Hellmodus, dunkle Tinte im Dunkelmodus). */
  color: var(--success-fg);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  cursor: default;
}
.btn.btn-gespeichert:hover { opacity: 1; }
/* Das Haken-Kaestchen ist genau eine Textzeile hoch - nicht so hoch wie
   sein Bild.
   Der Betrieb am 13.09.2026: *„der gespeichert Knopf ist dadurch minimal
   höher geworden, wodurch sich alles, was sich unter diesem Knopf
   befindet, leicht nach unten bewegt."* Nachgemessen: 28 px vorher, 29 px
   nachher - das SVG ist 17 px, die Textzeile bei 13 px Schrift nur 16.
   Der Knopf richtet sich nach dem Groesseren, und alles darunter rutscht
   mit.
   `height: 1em` nimmt dem Kaestchen die Stimme bei der Zeilenhoehe; das
   Bild darf darueber hinausragen (`overflow: visible`) und bleibt so
   gross, wie es war. Die BREITE friert bestaetigeAmKnopf() schon lange
   ein (10-foundation.js) - hier fehlte das Gegenstueck. */
.knopf-haken {
  display: inline-flex;
  align-items: center;
  height: 1em;
  overflow: visible;
  animation: haken-auf 260ms cubic-bezier(0.34, 1.56, 0.64, 1);
}
.knopf-haken svg { width: 17px; height: 17px; display: block; }
@keyframes haken-auf {
  from { transform: scale(0.4); opacity: 0; }
  to   { transform: scale(1); opacity: 1; }
}

/* Nur für Screenreader: trägt die Erfolgsmeldung, die visuell am Knopf
   steht (siehe melde() in app.js). Kein display:none - das würde den
   Inhalt auch für Screenreader entfernen. */
.nur-vorlesen {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ---------- Speichern je Abschnitt ---------- */

/* Sitzt am unteren Rand der Karte, abgesetzt durch eine feine Linie: der
   Knopf gehört sichtbar zu DIESER Karte und nicht zur Seite. */
.karten-fuss {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 14px;
  margin-top: 22px;
  padding-top: 18px;
  border-top: 1px solid var(--border);
}
.ungespeichert {
  white-space: nowrap;   /* sonst bricht es neben einer Fehlermeldung um */
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: 13px;
  font-weight: 600;
  color: var(--accent-ink);
}
/* Der Punkt ersetzt ein Symbol - er zieht Aufmerksamkeit, ohne zu mahnen. */
.ungespeichert::before {
  content: "";
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--accent);
}

/* ---------- Steuernummer / USt-IdNr. ---------- */

/* Die Rueckmeldung unter einem Feld, das der Server waehrend des Tippens
   prueft - Steuernummer, IBAN, IK, E-Mail. Drei Namen, eine Gestalt: die
   min-height haelt den Platz frei, damit das Formular nicht springt, wenn
   die erste Antwort eintrifft. */
.steuer-hinweis,
.iban-hinweis,
.pruef-hinweis { display: block; margin-top: 6px; min-height: 16px; }
.steuer-hinweis.ok,
.iban-hinweis.ok,
.pruef-hinweis.ok { color: var(--success); font-weight: 600; }
.steuer-hinweis.fehler,
.iban-hinweis.fehler,
.pruef-hinweis.fehler { color: var(--danger); font-weight: 600; }

/* Die Fehlermeldung eines Abschnitts, direkt beim Speichern-Knopf.
   Nicht als Meldung in der Ecke: die verdeckt etwas, verschwindet nach
   Sekunden von selbst und steht weit weg von dem Knopf, der sie ausgelöst
   hat. Hier bleibt sie stehen, bis der Grund behoben ist.

   mr:auto schiebt sie nach LINKS, weg von Marke und Knopf - der
   Kartenfuß ist rechtsbündig. */
/* Ein Kartenfuss ohne Trennstrich. Bei der IK-Sektion gehoert der Knopf
   zu dem EINEN Feld darueber - eine Linie dazwischen macht daraus zwei
   Dinge und laesst den Knopf wie den Abschluss der ganzen Karte wirken
   (Betrieb, 13.09.2026). Der kleinere Abstand zieht ihn zusaetzlich an
   das Feld heran. */
.karten-fuss.ohne-linie {
  border-top: none;
  margin-top: 10px;
  padding-top: 0;
}

/* Die Fehlermeldung eines Formulars - im Anmeldebereich (siehe
   renderAuthError in 20-auth.js). Dieselben Farben wie .karten-fehler,
   aber über die volle Breite: hier gibt es keinen rechtsbündigen Fuß,
   in den sie sich einreihen müsste. */
.formular-fehler {
  margin: 0 0 14px;
  padding: 10px 14px;
  border-radius: 8px;
  color: var(--danger);
  background: var(--danger-bg);
  font-size: 14px;
  font-weight: 600;
  line-height: 1.45;
}

/* Die Ueberschrift einer Untergruppe INNERHALB einer Karte. Seit dem
   13.09.2026 gliedert sie die Stammdaten (Firma / Ansprechpartner / Logo)
   und die Finanzen (Steuer / Bankverbindung). Klein und ruhig: sie ordnet,
   sie ruft nicht. */
.abschnitt-gruppe {
  margin: 20px 0 12px;
  padding-bottom: 6px;
  border-bottom: 1px solid var(--border);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--muted);
}
.abschnitt-gruppe:first-child { margin-top: 0; }
/* In einem Raster nimmt sie die ganze Zeile - sonst stuende sie als
   schmale Spalte neben einem Feld. */
.form-grid > .abschnitt-gruppe { grid-column: 1 / -1; }

.karten-fehler {
  margin-right: auto;
  color: var(--danger);
  background: var(--danger-bg);
  border-radius: 8px;
  padding: 8px 12px;
  font-size: 13px;
  font-weight: 600;
  line-height: 1.4;
  text-align: left;
}
@media (max-width: 560px) {
  /* Am Telefon steht sie über den Knöpfen statt neben ihnen - daneben
     bliebe für keinen von beiden genug Breite. */
  .karten-fuss { flex-wrap: wrap; }
  .karten-fehler { flex: 1 1 100%; margin-right: 0; }
}
/* Der Knopf im Kartenfuß schließt ein Formular von zwanzig Feldern ab -
   „Stammdaten speichern", „Steuer & Bank speichern", „Nummer speichern".
   Mit 28px sah er aus wie ein Knopf in einer Werkzeugleiste und sagte
   damit das Falsche über seinen Rang; am Telefon ist er außerdem der
   Abschluss einer langen Tipparbeit und muss zu treffen sein.
   Vom Betrieb am 17.09.2026 entschieden. Preis: 16px mehr Seitenlänge.
   An der Klasse und nicht an den drei Kennungen: die nächste Karte mit
   eigenem Speichern-Knopf bekommt es dann von selbst. 640px wie bei den
   übrigen Ausnahmen. */
@media (max-width: 640px) {
  .karten-fuss .btn { min-height: 44px; }
}

/* Unauffälliger Textknopf - "zweite Nummer" ist der Ausnahmefall und soll
   den Normalfall nicht überlagern. */
.link-knopf {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  margin-top: 6px;
  padding: 4px 0;
  border: none;
  background: none;
  color: var(--muted);
  font-family: inherit;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
}
.link-knopf:hover { color: var(--heading); }
.link-knopf svg { width: 14px; height: 14px; }
.link-knopf:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; border-radius: 4px; }

/* ---------- IBAN und automatisch ermittelte Bankdaten ---------- */

/* Ein falsch ausgefülltes Feld. Bis zum 13.09.2026 nur eine
   Rahmenfarbe - auf einem hellen Ground und neben lauter gleich
   aussehenden Feldern fiel das kaum auf. Der Betrieb: „Zudem soll das
   Feld farblich hervorgehoben werden, welches falsch ist."

   Rahmen UND Fläche, damit es auch beim Überfliegen auffällt; die Farbe
   ist dieselbe wie in der Fehlermeldung daneben, damit erkennbar bleibt,
   dass beide dasselbe meinen. */
input.ungueltig,
input.ungueltig:focus {
  border-color: var(--danger);
  border-width: 2px;
  background: var(--danger-bg);
}

/* Automatisch gefüllt und gesperrt: erkennbar anders, aber NICHT wie ein
   Fehler und nicht wie ein totes Feld - der Inhalt ist ja richtig und
   soll gut lesbar bleiben. */
input.automatisch {
  background: var(--success-bg);
  border-color: color-mix(in srgb, var(--success) 40%, var(--border));
  cursor: default;
}
.bank-automatik { margin-top: 8px; }

/* Stift zum Übernehmen eines automatisch belegten Feldes. Sitzt IM Feld,
   damit klar ist, welches der beiden er betrifft - ein gemeinsamer Knopf
   darunter ließ das offen. */
.feld-mit-stift { position: relative; display: block; }
.feld-mit-stift input { width: 100%; }
input.automatisch { padding-right: 42px; }
.stift {
  position: absolute;
  right: 6px;
  top: 50%;
  transform: translateY(-50%);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  padding: 0;
  border: none;
  border-radius: 6px;
  background: transparent;
  color: var(--success);
  cursor: pointer;
}
.stift svg { width: 16px; height: 16px; }
.stift:hover { background: color-mix(in srgb, var(--success) 18%, transparent); }
.stift:focus-visible { outline: 2px solid var(--ink); outline-offset: 1px; }
.bank-automatik-text {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: 13px;
  color: var(--success);
  font-weight: 600;
}
.bank-automatik-text svg { width: 15px; height: 15px; }

/* Bestätigung an der Ablagefläche - gleiches Prinzip wie am Speichern-Knopf.
   Steht bewusst NACH .logo-ablage:hover und .darueber (gleiche Spezifität),
   damit die Quellreihenfolge entscheidet und ein zufälliges Überfahren mit
   der Maus die Bestätigung nicht überfärbt. */
.logo-ablage.gespeichert {
  border-color: var(--success);
  border-style: solid;
  background: var(--surface);
}
.logo-ablage-erfolg {
  position: absolute;
  inset: 0;
  display: none;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
  border-radius: var(--radius);
  background: var(--success);
  color: var(--success-fg);
  font-size: 14px;
  font-weight: 600;
}
.logo-ablage.gespeichert .logo-ablage-erfolg {
  display: flex;
  animation: erfolg-auf 240ms ease-out;
}
/* Der Haken soll voll deckend sein - .logo-ablage svg setzt sonst 0.7. */
.logo-ablage .logo-ablage-erfolg svg { width: 30px; height: 30px; opacity: 1; }
@keyframes erfolg-auf {
  from { opacity: 0; transform: scale(0.96); }
  to   { opacity: 1; transform: scale(1); }
}

/* Wer Bewegung reduziert haben möchte, bekommt denselben Zustand ohne
   Animation - die Information geht dabei nicht verloren, nur die
   Bewegung. */
@media (prefers-reduced-motion: reduce) {
  .logo-vorschau, .logo-haken { transition: none; }
  .logo-vorschau.gespeichert .logo-haken { transform: scale(1); }
  .knopf-haken, .logo-ablage-erfolg { animation: none; }
}

/* Kennzahlenzeile in der Nutzer-Detailansicht des Admin-Bereichs. */
.metric-row {
  display: flex;
  flex-wrap: wrap;
  gap: 26px;
  margin-top: 12px;
  font-size: 14px;
}
.metric-row > div { min-width: 110px; }

/* ---------- Verwaltungsansicht ----------
   Lag früher inline in app/templates/admin.html. Seit die Verwaltung eine
   gewöhnliche Ansicht der App ist, gehört ihr Aussehen hierher - sonst
   sähen die Reiter dort unformatiert aus. */

.reiter,
.admin-tabs { display: flex; gap: 8px; margin-bottom: 20px; border-bottom: 1px solid var(--border, #e5e0d5); overflow-x: auto; -webkit-overflow-scrolling: touch; }

/* Am Telefon UMBRECHEN statt scrollen.
   Gemessen am 13.09.2026: die Leiste der Einstellungen brauchte 562 px,
   sichtbar waren 337 - vier von sechs Reitern lagen ausserhalb des Bildes,
   ohne jeden Hinweis darauf. (Schon mit den vier alten Reitern fehlten
   9 px.) Umgebrochen stehen alle da; es kostet eine zweite Zeile. */
@media (max-width: 640px) {
  .reiter,
  .admin-tabs {
    flex-wrap: wrap;
    overflow-x: visible;
    gap: 4px 6px;
  }
  .reiter .reiter-knopf,
  .admin-tabs .admin-tab { padding: 9px 12px; }
}

.reiter-knopf,
.admin-tab { padding: 10px 16px; border: none; background: none; cursor: pointer; font-weight: 600; color: var(--muted); border-bottom: 2px solid transparent; white-space: nowrap; flex-shrink: 0; }

/* --heading, nicht --ink: --ink ist die feste Farbe der Seitenleiste und
   bleibt im Dunkelmodus dasselbe dunkle Marineblau. Der aktive Reiter stand
   damit dunkel auf dunklem Grund - bei rund 1,4:1 praktisch unlesbar, und es
   sah aus, als sei der GEWAEHLTE Reiter der ausgegraute. --heading dreht mit
   dem Modus (#1B2A4A hell, #F2F0E4 dunkel) und ist im Hellmodus derselbe
   Wert wie vorher. */
/* Die Zahl am Reiter - wie am Menuepunkt, nur kleiner. */
.reiter-knopf .nav-zaehler { margin-left: 6px; }

.reiter-knopf.active,
.admin-tab.active { color: var(--heading); border-bottom-color: var(--accent, #b8862b); }

.admin-panel { display: none; }

.admin-panel.active { display: block; }

@media (max-width: 700px) {
      .metric-cards { grid-template-columns: 1fr 1fr; }
    }

/* Suchleiste im Nutzer-Tab der Verwaltung. */
.admin-search {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  margin-bottom: 16px;
}
.admin-search input[type="search"] {
  flex: 1 1 260px;
  min-width: 0;
  padding: 8px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm, 6px);
  background: var(--surface);
  color: var(--text);
  font-size: 0.95rem;
}
.admin-search input[type="search"]:focus {
  outline: 2px solid var(--accent);
  outline-offset: -1px;
}

/* Kundennummer im Seitenkopf des Kontos: da, wenn man sie braucht,
   aber nicht als Blickfang. Monospace und Zeichenabstand, weil sie
   vorgelesen und abgetippt wird; user-select:all, damit ein Klick sie
   ganz markiert. */
.page-header p.kundennummer,
.kundennummer {
  margin: 0;
  display: flex;
  align-items: baseline;
  gap: 8px;
  font-size: 12px;
  color: var(--muted);
  white-space: nowrap;
}

.kundennummer #account-customer-number {
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
  font-size: 13px;
  letter-spacing: 0.04em;
  color: var(--text);
  user-select: all;
  cursor: text;
}

/* Hinweis in der Rechnungsliste, wenn die Mail zurueckkam. Bewusst in der
   Warnfarbe und nicht als weiterer Statusstempel: der Rechnungsstatus
   (gesendet/bezahlt) bleibt gueltig - nur die Zustellung ist gescheitert. */
/* Kennzeichen (L10). Ein Vermerk, der NEBEN dem Status steht und ihn nicht
   ersetzt: der Rückläufer sagt nichts darüber, ob eine Rechnung bezahlt
   ist - er sagt, dass sie nie angekommen ist.

   Vorher war er nur roter Text in halbfett unter dem Stempel. Gemessen:
   keine Fläche, keine Form, kein Umriss - in einer Liste von 110 Zeilen
   ging er unter. Dabei ist eine zurückgekommene Rechnung genau der Fall,
   bei dem jemand auf Geld wartet, das nie kommt.

   Gebaut wie die Statusstempel (.stamp), aber mit durchgezogenem Rand und
   ohne deren Drehung: verwandt genug, um dazuzugehören, verschieden genug,
   um nicht für einen zweiten Status gehalten zu werden. */
.kennzeichen {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  margin-top: 5px;
  padding: 3px 8px;
  border-radius: 6px;
  font-size: 11.5px;
  font-weight: 600;
  line-height: 1.35;
}
.kennzeichen svg { width: 14px; height: 14px; flex: none; }

.zustellfehler {
  color: var(--danger);
  background: var(--danger-bg);
  /* Der Rand trägt die Form. Die Fläche allein steht mit 1,18:1 (hell)
     bzw. 1,11:1 (dunkel) zum Untergrund - sichtbar, aber keine Kante.
     var(--danger) auf var(--surface) misst 5,52:1 bzw. 5,29:1. */
  border: 1px solid var(--danger);
  cursor: help;
}

/* Ladeschirm beim Rechnungsversand. Zeigt die beiden Schritte, die es
   wirklich gibt - Uebergabe und Warten auf einen Rueckläufer. Bewusst
   nuechtern: der Nutzer soll erkennen, dass gearbeitet wird, ohne dass
   eine Zustellung versprochen wird, die niemand garantieren kann. */
.versand-dialog { max-width: 30rem; }

.versand-schritte {
  list-style: none;
  margin: 18px 0 14px;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.versand-schritte li {
  display: flex;
  align-items: center;
  gap: 10px;
  color: var(--muted);
  font-size: 14px;
}
.versand-schritte li.laeuft,
.versand-schritte li.fertig { color: var(--text); }
.versand-schritte li.fehler { color: var(--danger); }

/* Der Zustandspunkt vor jedem Schritt: leer - pulsierend - Haken - Kreuz. */
.versand-marke {
  width: 18px; height: 18px;
  flex: 0 0 18px;
  border-radius: 50%;
  border: 2px solid var(--border);
  display: inline-block;
  position: relative;
}
.versand-schritte li.laeuft .versand-marke {
  border-color: var(--accent);
  animation: versand-puls 1.1s ease-in-out infinite;
}
.versand-schritte li.fertig .versand-marke {
  border-color: var(--success);
  background: var(--success);
}
.versand-schritte li.fertig .versand-marke::after {
  content: "";
  position: absolute; left: 4px; top: 1px;
  width: 4px; height: 9px;
  border: solid var(--success-fg);
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}
.versand-schritte li.fehler .versand-marke {
  border-color: var(--danger);
  background: var(--danger);
}
.versand-schritte li.fehler .versand-marke::after {
  content: "!";
  position: absolute; inset: 0;
  color: #fff; font-size: 12px; font-weight: 700;
  line-height: 14px; text-align: center;
}
@keyframes versand-puls {
  0%, 100% { box-shadow: 0 0 0 0 rgba(184, 134, 43, 0.45); }
  50%      { box-shadow: 0 0 0 5px rgba(184, 134, 43, 0); }
}
/* Wer Bewegung im Betriebssystem abgestellt hat, bekommt keine. */
@media (prefers-reduced-motion: reduce) {
  .versand-schritte li.laeuft .versand-marke { animation: none; }
  .versand-balken-fuellung { transition: none; }
}

.versand-zaehler { margin-left: auto; font-variant-numeric: tabular-nums; color: var(--muted); }

.versand-balken {
  height: 4px;
  background: var(--border);
  border-radius: 2px;
  overflow: hidden;
}
.versand-balken-fuellung {
  height: 100%;
  width: 0;
  background: var(--accent);
  transition: width 0.4s linear;
}
/* Bei einem Rueckläufer faerbt sich der Balken, statt sich zu fuellen: ein
   voller Balken liest sich wie "erfolgreich abgeschlossen" - genau das
   Gegenteil dessen, was gerade passiert ist. */
.versand-balken-fuellung.fehler { background: var(--danger); }

.versand-ergebnis { margin: 14px 0 0; font-size: 14px; color: var(--text); }
.versand-ergebnis.fehler  { color: var(--danger); }
.versand-ergebnis.neutral { color: var(--muted); }

/* Zaehler am Navigationspunkt "Rechnungen": wie viele Rechnungen ein offenes
   Zustellproblem haben. Bewusst eine feste Rotfaerbung statt var(--danger):
   die Seitenleiste ist in BEIDEN Themes dunkel, die Marke braucht also nicht
   zwei Varianten - weiss auf #B3452C liegt bei 5,5:1 und damit klar ueber
   der Anforderung. */
.nav-zaehler {
  margin-left: auto;
  min-width: 20px;
  height: 20px;
  padding: 0 6px;
  border-radius: 10px;
  background: #B3452C;
  color: #fff;
  font-size: 12px;
  font-weight: 700;
  line-height: 20px;
  text-align: center;
  font-variant-numeric: tabular-nums;
  cursor: help;
  flex: 0 0 auto;
}

/* Übersicht der Rechnungen mit Zustellproblem, über der Liste.
   Getönter Grund statt eines roten Rahmens: die Karte soll auffallen, ohne
   die ganze Ansicht wie einen Fehlerzustand aussehen zu lassen - die
   Rechnungen selbst sind ja in Ordnung, nur der Versand ist gescheitert. */
.zustellprobleme {
  background: var(--danger-bg);
  border-color: var(--danger);
  margin-bottom: 18px;
}
.zustellprobleme-titel {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0 0 4px;
  font-size: 16px;
  line-height: 1.35;
  color: var(--danger);
}
/* Das Zeichen wächst mit der Überschrift mit, statt auf einer festen
   Pixelgröße zu kleben - sonst steht es bei 16px zu klein daneben. */
.zustellprobleme-titel svg { width: 1.25em; height: 1.25em; flex: none; }
.zustellprobleme-liste {
  list-style: none;
  margin: 14px 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.zustellprobleme-liste li {
  padding: 12px 14px;
  border-radius: var(--radius-sm, 6px);
  background: var(--surface);
  border: 1px solid var(--border);
}
.zustellprobleme-kopf {
  display: flex;
  align-items: baseline;
  gap: 10px;
  flex-wrap: wrap;
}
/* Die Erklärung ist die eigentliche Information dieser Karte - sie sagt dem
   Nutzer, ob er die Adresse korrigieren oder nichts tun muss. Deshalb in
   normaler Textfarbe und nicht als Fußnote in --muted wie der Rohtext
   darunter. Umbruch, weil eine Domain lang sein kann. */
.zustellprobleme-grund {
  margin: 6px 0 10px;
  font-size: 14px;
  color: var(--text);
  overflow-wrap: anywhere;
}
/* Der Wortlaut des fremden Servers bleibt erreichbar, aber zugeklappt: als
   Beleg, falls ein Kunde den Empfang bestreitet, und fuer Codes, die die
   Zuordnung in app.js nicht kennt. Zugeklappt, WEIL er an einen
   Mailadministrator gerichtet ist und nicht an den Nutzer. */
.zustellprobleme-roh {
  margin: 0 0 10px;
  font-size: 12px;
}
.zustellprobleme-roh summary {
  cursor: pointer;
  color: var(--muted);
  padding: 4px 0;
}
.zustellprobleme-roh p {
  margin: 6px 0 0;
  color: var(--muted);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  overflow-wrap: anywhere;
  line-height: 1.5;
}
/* Auf dem Handy sind die beiden Tasten die eigentliche Aufgabe dieser
   Karte - mit den 28px von .btn-sm trifft man sie mit dem Daumen schlecht.
   Nur hier vergrößert, nicht global: .btn-sm sitzt überall in der Anwendung
   in Werkzeugleisten, wo die kleine Höhe gewollt ist. */
@media (max-width: 620px) {
  .zustellprobleme-liste .toolbar { gap: 8px; }
  .zustellprobleme-liste .toolbar .btn-sm {
    min-height: 44px;
    flex: 1 1 auto;
  }
  .zustellprobleme-roh summary { padding: 10px 0; }
}
/* Offene Kassenabrechnung: bewusst RUHIG gestaltet, nicht als Warnung wie
   die Zustellprobleme darueber. Hier ist nichts schiefgegangen - es liegt
   nur Arbeit an, die man ohnehin monatlich macht. Zwei rote Kaesten
   uebereinander wuerden beide entwerten. */
.kassenabrechnung {
  background: var(--info-bg);
  margin-bottom: 18px;
}
.kassenabrechnung-titel {
  margin: 0 0 4px;
  font-size: 16px;
  line-height: 1.35;
}
.kassenabrechnung-liste {
  list-style: none;
  margin: 14px 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.kassenabrechnung-liste li {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto auto;
  align-items: baseline;
  gap: 14px;
  padding: 8px 0;
  border-bottom: 1px solid var(--border);
}
.kassenabrechnung-liste li:last-child { border-bottom: none; }
.kassenabrechnung-name { font-weight: 600; color: var(--heading); overflow-wrap: anywhere; }
.kassenabrechnung-zahl { color: var(--muted); font-size: 13px; white-space: nowrap; }
.kassenabrechnung-summe { font-weight: 600; font-variant-numeric: tabular-nums; white-space: nowrap; }
/* Auf dem Handy passen vier Spalten nicht nebeneinander. */
@media (max-width: 620px) {
  .kassenabrechnung-liste li {
    grid-template-columns: minmax(0, 1fr) auto;
    row-gap: 2px;
  }
  .kassenabrechnung-name { grid-column: 1 / -1; }
}

/* Kennzeichnung in der Kundenliste - ein Stempel wie bei den
   Rechnungsstatus, nur ohne Farbsignal: es ist keine Wertung. */
.stamp.kostentraeger {
  background: var(--info-bg);
  color: var(--heading);
  border-color: var(--border);
}

/* Beiseitegelegt: der Vermerk bleibt in der Zeile stehen, aber ruhig -
   der Nutzer hat die Entscheidung ja bewusst getroffen. */
/* Beiseitegelegt: der Rückläufer IST passiert. Ihn aus der Zeile zu tilgen,
   hieße die eigenen Unterlagen zu schönen - er wird nur ruhiger
   dargestellt: ohne Fläche, ohne Alarmfarbe, aber weiter lesbar. */
.zustellfehler.beiseite {
  color: var(--muted);
  background: none;
  border-color: var(--rand-bedienelement);
  font-weight: 400;
}

/* ---------- Transportscheine einer Kassenrechnung ----------
   Seit 14.09.2026 eine gewoehnliche Ansicht statt eines Dialogs (Betrieb:
   "keine darueberliegende Schicht"). Die Breite bleibt die des Dialogs:
   hier wird ein Papierbeleg abgetippt, und die Felder gehoeren in derselben
   Anordnung nebeneinander wie auf dem Formular - sonst springt der Blick
   beim Abtippen zwischen Papier und Bildschirm hin und her. Gescrollt wird
   jetzt die Seite selbst; eine eigene Hoehe braucht es nicht mehr. */
.belege-seite { max-width: 46rem; width: 100%; text-align: left; }
/* Ueberschrift und Rechnungsnummer bleiben stehen: auf der gescrollten
   Seite sieht man sonst nicht mehr, zu welcher Rechnung man gerade tippt.
   Am Telefon unter der festen Kopfzeile (56px). */
.belege-seite > .page-header {
  position: sticky; top: 0; z-index: 5; background: var(--paper);
  margin-bottom: 1rem; padding-block: .5rem;
}
@media (max-width: 780px) { .belege-seite > .page-header { top: 56px; } }
.belege-hinweis { color: var(--muted); font-size: 13px; margin: .2rem 0 0; }
.belege-liste { list-style: none; margin: 0 0 1rem; padding: 0; }
.belege-zeile {
  display: flex; align-items: center; justify-content: space-between; gap: .75rem;
  padding: .55rem .7rem; border: 1px solid var(--border); border-radius: 8px;
  margin-bottom: .4rem; background: var(--surface);
}
.belege-nummer { font-variant-numeric: tabular-nums; color: var(--muted); margin-right: .6rem; }
.belege-person { font-weight: 600; }
.belege-detail { color: var(--muted); margin-left: .6rem; font-variant-numeric: tabular-nums; }
/* Mit den Quittungsknoepfen (15.09.2026) sind es bis zu sechs Knoepfe. Mit
   flex-shrink: 0 und ohne Umbruch blieb der Text links auf wenigen Zeichen
   Breite stehen, Wort unter Wort. Die Knoepfe bleiben rechts, wo sie waren -
   sie brechen nur in eine zweite Zeile um, wenn der Platz nicht reicht. */
.belege-aktionen { display: flex; gap: .25rem; flex-wrap: wrap; justify-content: flex-end; }
.belege-zeile > div:first-child { flex: 1 1 14rem; min-width: 0; }
.belege-leer { color: var(--muted); padding: .75rem 0; }

/* Der Serienkalender (K7, 18.09.2026).
 *
 * Eine Dialysepatientin faehrt dreimal die Woche; mit Rueckfahrt sind das 26
 * Fahrten im Monat. Der Kalender macht daraus vier Griffe - Mo, Mi, Fr und
 * anlegen. Deshalb sind die WOCHENTAGE oben Schaltflaechen und nicht bloss
 * Beschriftungen: sie sind die eigentliche Abkuerzung.
 */
.serie { flex: 1 0 100%; border: 1px solid var(--border); border-radius: var(--radius);
         background: var(--surface); padding: 10px; margin-top: 6px; }
.serie-kopf { display: flex; align-items: center; justify-content: space-between;
              gap: 8px; margin-bottom: 8px; }
.serie-kopf strong { font: 600 14px/1.2 var(--font-body); color: var(--heading); }
.serie-raster { display: grid; grid-template-columns: repeat(7, 1fr); gap: 4px; }
/* MIT Rahmen, obwohl es nur Beschriftungen sein koennten: sie sind
   Schaltflaechen, und ein Bedienelement muss als solches zu erkennen sein -
   genau das hat der Betrieb am 11.09.2026 als „nicht anschaulich" gemeldet,
   und --rand-bedienelement ist die Antwort darauf (3,34:1 gegen die Seite).
   Auf dem Telefon gibt es kein Hover, das die Frage nachtraeglich klaert. */
.serie-wochentag {
  font: 600 11px/1 var(--font-body); color: var(--accent-ink);
  background: var(--stamp-accent-bg); border: 1px solid var(--rand-bedienelement);
  border-radius: var(--radius-sm); padding: 8px 0; cursor: pointer; text-align: center;
}
.serie-wochentag:hover { background: var(--accent); color: var(--auf-akzent); }
.serie-leer { display: block; }
/* 40px hoch: die Zellen sind das, was am haeufigsten getroffen werden muss,
   und 44px waeren sieben nebeneinander auf 320px Breite nicht mehr. Mit dem
   Abstand kommt die Beruehrflaeche auf 44px. */
.serie-tag {
  min-height: 40px; font: 500 14px/1 var(--font-body); font-variant-numeric: tabular-nums;
  color: var(--text); background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-sm); cursor: pointer; position: relative;
}
.serie-tag:hover { border-color: var(--rand-bedienelement); }
.serie-tag.gewaehlt { background: var(--accent); border-color: var(--accent);
                      color: var(--auf-akzent); font-weight: 700; }
/* Schon erfasst: ein Punkt, keine Sperre - an einem Tag faehrt dieselbe
   Strecke durchaus zweimal (hin und zurueck sind zwei Fahrten). */
.serie-tag.belegt::after {
  content: ""; position: absolute; left: 50%; bottom: 6px; transform: translateX(-50%);
  width: 4px; height: 4px; border-radius: 50%; background: var(--muted);
}
.serie-tag.gewaehlt.belegt::after { background: var(--auf-akzent); }
.serie-stand { font-size: 13px; color: var(--muted); margin: 8px 0 0; }
.serie-fuss { display: flex; justify-content: flex-end; gap: 8px; margin-top: 10px; }

/* Ein zurueckgestellter Schein (K3, 18.09.2026). Er ist NICHT durchgestrichen
   und nicht ausgegraut: er ist nicht erledigt und nicht fehlerhaft, er wartet.
   Der linke Balken sagt "diese Zeile ist anders", der Text daneben sagt
   worauf - Farbe allein traegt die Aussage nicht (WCAG SC 1.4.1). */
.beleg-zurueckgestellt { border-left: 3px solid var(--accent); background: var(--stamp-accent-bg); }
.beleg-wartet { color: var(--accent-ink); font-variant-numeric: normal; }
/* Die Frage steht als Beschriftung fuer Vorleseprogramme da; im Bild traegt
   der Platzhalter sie, damit die Zeile nicht zwei Zeilen hoch wird. */
.zurueckstellen-zeile { display: flex; align-items: center; gap: .4rem; flex: 1 1 12rem; }
.zurueckstellen-zeile input { flex: 1 1 8rem; min-width: 0; }
.belege-abschnitt {
  font-size: 13px; text-transform: none; letter-spacing: 0; color: var(--heading);
  margin: 1.1rem 0 .5rem; padding-bottom: .3rem; border-bottom: 1px solid var(--border);
}
/* Die Ersatzregel steht zwischen den beiden Blöcken, nicht als Fußnote:
   sie erklärt, warum die Anschrift überhaupt dasteht. */
.belege-ersatzregel {
  color: var(--muted); font-size: 13px; margin: .2rem 0 .6rem;
  padding-left: .7rem; border-left: 2px solid var(--border);
}
/* Der Dialog ist schmaler als eine Seite - zwei Spalten statt drei,
   sonst werden die Felder zu eng zum Abtippen. */
.belege-form .form-grid { gap: .6rem 1rem; }
@media (max-width: 640px) {
  .belege-zeile { flex-direction: column; align-items: flex-start; }
  /* In der Zeile ist „flex: 1 1 14rem" eine BREITE. Sobald die Zeile zur
     Spalte wird, ist dieselbe Angabe eine HÖHE: der Textblock wurde 224px
     hoch und stand als leerer Kasten über den Knöpfen (gemessen am Telefon,
     16.09.2026). In der Spalte bestimmt der Inhalt die Höhe. */
  .belege-zeile > div:first-child { flex: 0 1 auto; }
  .belege-aktionen button { min-height: 44px; }
  /* Umbrechen statt überstehen. Bei vier Knöpfen ragte der letzte schon
     über den Rand des Dialogs hinaus und war nicht mehr erreichbar - mit
     „Nochmal" (N6) sind es fünf. Das Fenster scrollt NICHT waagerecht,
     der Knopf war also nicht bloß weit weg, sondern weg. */
  .belege-aktionen { flex-wrap: wrap; }
}

/* Rückweg aus der Fahrtenansicht: unauffällig, aber immer sichtbar - der
   Dialog hat sonst keinen Ausgang außer "Schließen", und das verlöre den
   Beleg. */
.belege-zurueck { padding-left: 0; margin-bottom: .4rem; }

/* Die zusammengesetzte Positionsnummer: sie entsteht aus vier Auswahlfeldern
   und soll sofort sichtbar sein - sonst wählt man vier Werte, ohne zu sehen,
   was daraus wird. */
.posten-nummer {
  font-variant-numeric: tabular-nums; letter-spacing: .04em;
  color: var(--heading); font-weight: 600; font-size: 14px;
  margin: .2rem 0 .8rem; padding: .4rem .7rem;
  background: var(--info-bg, var(--surface)); border-radius: 6px;
  border: 1px solid var(--border);
}
.posten-nummer:empty { display: none; }

/* Woher die Schlüssel stammen (K5, 18.09.2026). Kein Kasten und keine Farbe:
   es ist eine Auskunft unter der Nummer, keine Meldung. Nur die Zeile
   „steht nicht im Vertrag" färbt sich - die ist eine. */
.posten-vertrag {
  font-size: 13px; color: var(--muted); margin: -.5rem 0 .8rem;
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 10px;
}
.posten-vertrag .btn { padding: 0; min-height: 0; font-size: 13px; }
.posten-vertrag-fremd { color: var(--accent-ink); font-weight: 600; }

/* Die Marke „gerechnet" neben der Überschrift der Postenliste (K6,
   18.09.2026). Grün und nicht golden: sie meldet nichts, was Aufmerksamkeit
   braucht - sie sagt, dass etwas schon erledigt ist. Dieselbe Farbe wie die
   erledigten Zustände in der Rechnungsliste. */
.marke-gerechnet {
  /* OHNE Versalien: die Anwendung fuehrt sie nur noch an Spaltenkoepfen und
     Stempeln (tests/test_typografie.py). Ein Wort in Grossbuchstaben liest
     sich langsamer, und hier steht nur eine Auskunft. */
  font: 600 11px/1 var(--font-body);
  background: var(--success-bg); color: var(--success); border-radius: 999px;
  padding: 4px 8px; white-space: nowrap;
}
/* Der Betrag einer Position - bis K6 stand dort nur „1 × 12,20 €" und die
   Zeilensumme musste man selbst bilden.

   Er nimmt in der Postenliste die GANZE Breite seiner Zeile und steht rechts:
   auf dem Telefon teilen sich sonst Betrag und zwei Knoepfe eine Zeile, der
   Betrag rutscht zwischen sie und ist als Zahl nicht mehr zu finden. So
   steht er in einer eigenen Zeile ueber den Knoepfen, buendig rechts wie in
   jeder Abrechnung. */
.belege-betrag { font-variant-numeric: tabular-nums; font-weight: 600; color: var(--heading);
                 white-space: nowrap; }
#posten-liste .belege-aktionen { align-items: flex-end; }
#posten-liste .belege-betrag { flex: 1 0 100%; text-align: right; margin-bottom: .3rem; }

/* Lücken in der Kassenübersicht: eingerückt unter der jeweiligen Kasse und
   in ruhigem Grau statt Rot. Es ist keine Störung, sondern Arbeit, die noch
   ansteht - ein rotes Feld daneben würde die echten Zustellprobleme
   darüber entwerten. */
.kassen-luecke-kopf { color: var(--muted); font-size: 13px; margin: .6rem 0 .2rem; }
/* Selektor mit Element davor, nicht nur die Klasse: ".kassenabrechnung-liste
   li" ist spezifischer als ".kassen-luecke" und setzt sonst weiter sein
   Raster durch - der Knopf landete dann in der breiten ersten Spalte und
   zog sich ueber die halbe Karte. */
.kassenabrechnung-liste li.kassen-luecke {
  display: flex; align-items: center; gap: .6rem; flex-wrap: wrap;
  padding-left: 1rem; color: var(--muted); font-size: 13px;
  border-bottom: none;
}
/* Der Knopf traegt nur die Rechnungsnummer - er darf nicht wachsen, sonst
   schiebt er den eigentlichen Hinweis an den Rand und dominiert die Zeile. */
.kassenabrechnung-liste li.kassen-luecke .btn {
  font-variant-numeric: tabular-nums;
  flex: 0 0 auto; padding: .2rem .5rem; min-height: 0;
}

/* Kassenabrechnung: die fertigen Rechnungen mit ihren drei Aktionen.
   Wie .kassen-luecke mit der Kennung am Element und nicht nur am Kind -
   sonst gewinnt .kassenabrechnung-liste li (0,1,1) gegen .kassen-fertig
   (0,1,0), egal in welcher Reihenfolge die Regeln stehen. */
.kassenabrechnung-liste li.kassen-fertig {
  display: flex;
  align-items: center;
  gap: .5rem;
  flex-wrap: wrap;
  padding-left: 1rem;
}
.kassen-aktionen {
  display: flex;
  gap: .25rem;
  flex-wrap: wrap;
  margin-left: auto;
}
.kassen-testdatei { margin-top: .75rem; }

.pruefung-dialog {
  max-height: min(88vh, 60rem);
  overflow-y: auto;
  max-width: 46rem;
}
.pruefung-liste { list-style: none; margin: .5rem 0 0; padding: 0; }
.pruefung-liste li {
  display: grid;
  grid-template-columns: 4.5rem 12rem 1fr;
  gap: .5rem;
  padding: .4rem 0;
  border-top: 1px solid var(--border);
  align-items: baseline;
}
.pruefung-stufe { font-weight: 600; }
.pruefung-stelle { font-size: .85em; opacity: .8; word-break: break-word; }
.pruefung-ohne-befund { margin: .5rem 0 0; font-weight: 600; }
/* Der Weg aus einer Beanstandung heraus (E7.6, 20.09.2026). Er ERSETZT die
   Stelle-Spalte, er tritt nicht daneben - die Zeile behält ihre drei
   Spalten. Bewusst KEIN .btn: ein Flächenknopf nähme hier der Meldung den
   Platz, genau die Enge, an der E3.10 einen zweiten Knopf verworfen hat.
   Ein Wort in seiner Zeile ist ein Textlink und lebt von der Zeile
   (pruefung/messen.js misst deshalb nur Knöpfe mit der Klasse btn). Voll
   deckend statt
   der .8 der Nachbarspalte: was man anfassen soll, darf nicht blasser sein
   als das, was nur dasteht (Ä2). */
.pruefung-weg {
  border: none;
  background: none;
  padding: 0;
  font: inherit;
  font-size: 13px;
  opacity: 1;
  color: var(--heading);
  text-align: left;
  text-decoration: underline;
  text-underline-offset: 2px;
  word-break: break-word;
  cursor: pointer;
}
.pruefung-weg:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; border-radius: var(--radius-sm); }
/* Die weiteren Werte derselben Beanstandung - sie erklären den Satz
   daneben, sie sind nicht selbst einer. */
.pruefung-werte { opacity: .75; }

/* „Nächste Schritte" ist seit dem Zuschnitt vom 09.09.2026 ein gewöhnlicher
   Menüpunkt - er trägt nur zusätzlich eine Zahl und verschwindet ganz, wenn
   nichts ansteht. Der eigene Textknopf in der Telefon-Kopfzeile (.schritte-
   knopf) ist damit weggefallen; dort steht jetzt der rote Punkt am
   Menüzeichen, siehe .menue-punkt. */
/* Eine Zeile je Schritt: links der Satz, rechts das Tatwort.
   Der Satz sagt, WAS ansteht; das Wort daneben, was man damit tut. Bis zum
   10.09.2026 war die ganze Zeile ein Knopf ohne Beschriftung - man musste
   ihn drücken, um zu erfahren, wohin er führt. */
/* Seit dem 13.09.2026 eine LEISTE mit eigener Kopfzeile, kein Kasten mehr
   unter mehreren. Der Betrieb: „auf der Startseite oben eine Leiste, die
   alle Aufgaben, die noch nicht erledigt sind, auflistet - übersichtlich
   und für den Nutzer schön." Vorher trug sie weder Überschrift noch
   Zähler und war von den drei Karten darunter nicht zu unterscheiden. */
.schritte-leiste { padding: 0; overflow: hidden; }

.schritte-kopf {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 12px 20px;
  border-bottom: 1px solid var(--border);
}

/* Wie jede andere Kartenüberschrift (.card h2) - also Fließschrift und
   nicht die Auszeichnungsschrift. Im Entwurf stand hier die Display-
   Schrift; tests/test_typografie.py hat das abgefangen: sie gehört der
   Marke und den Seitentiteln, nicht dem Arbeitsbereich. Eine Ausnahme
   hätte die Regel für alle künftigen Karten aufgeweicht. */
.schritte-kopf h2 {
  margin: 0;
  font-family: var(--font-body);
  font-size: 15px;
  font-weight: 600;
  letter-spacing: -0.005em;
  color: var(--heading);
}

.schritte-zaehler { font-size: 13px; color: var(--muted); }

.schritte-liste { list-style: none; margin: 0; padding: 0; }
.schritt {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 11px 20px;
  border-bottom: 1px solid var(--border);
}
.schritt:last-child { border-bottom: none; }
.schritt-text { flex: 1; font-size: 14px; color: var(--text); }

/* Der Punkt sagt dasselbe wie die Farbe der Zeile - nur ohne Farbe
   auszukommen. Er ist aria-hidden: eine Vorlesehilfe bekäme sonst ein
   Element ohne Text, und die Aussage steht ohnehin im Satz daneben. */
.schritt-punkt {
  flex: none;
  width: 8px;
  height: 8px;
  border-radius: 999px;
  background: var(--muted);
}

/* Was die Abrechnung sperrt, sieht anders aus - und zwar an drei Stellen
   zugleich (Grund, Schriftschnitt, Punkt), damit die Aussage nicht an der
   Farbe allein hängt. */
.schritt-sperrt { background: var(--danger-bg); }
.schritt-sperrt .schritt-punkt { background: var(--danger); }
.schritt-sperrt .schritt-text { font-weight: 600; color: var(--danger); }
/* Kein .btn: eine Schaltfläche mit Rahmen je Zeile ergäbe eine Leiter aus
   Kästen. Das Wort trägt die Akzentfarbe und ist damit als Weg erkennbar. */
.schritt-tat {
  flex: 0 0 auto;
  background: none;
  border: none;
  padding: 4px 0;
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  /* --accent ist eine FLAECHENfarbe: sie traegt den Knopf, und die Schrift
     darauf ist --auf-akzent. Als Schrift auf hellem Grund schafft sie nur
     2,84:1 - fuer Fliesstext verlangt WCAG SC 1.4.3 vier­einhalb.
     --accent-ink ist genau dafuer gemacht und kommt auf 7,13:1; sie stand
     an dieser Stelle schon im Hover, nur nicht im Ruhezustand.
     Gemessen im Bildlauf (Etappe Ae2), vom Betrieb am 17.09.2026
     entschieden. */
  color: var(--accent-ink);
  cursor: pointer;
  white-space: nowrap;
}
/* Der Unterstrich ist die Rueckmeldung - die Farbe wechselt nicht mehr, weil
   sie im Ruhezustand schon die richtige ist. */
.schritt-tat:hover { text-decoration: underline; }

/* Der zuklappbare Abschnitt der Belegmaske. Er sieht aus wie die übrigen
   Zwischenüberschriften - nur dass man ihn öffnen muss. Der Dreipunkt-
   Marker der Vorgabe wird ersetzt, damit die Zeile ruhig bleibt. */
.belege-weiteres > summary {
  cursor: pointer;
  list-style: none;
  padding: .3rem 0;
  margin-top: 1.4rem;
  border-top: 1px solid var(--border);
}
.belege-weiteres > summary::-webkit-details-marker { display: none; }
.belege-weiteres > summary > span:first-child {
  font-weight: 600;
  display: inline-flex;
  align-items: center;
  gap: .4rem;
}
.belege-weiteres > summary > span:first-child::before {
  content: "›";
  display: inline-block;
  transition: transform .15s ease;
  font-size: 1.1em;
  line-height: 1;
}
.belege-weiteres[open] > summary > span:first-child::before { transform: rotate(90deg); }
.belege-weiteres > summary > .field-hint { display: block; margin-top: .15rem; }
.belege-weiteres > summary:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
@media (prefers-reduced-motion: reduce) {
  .belege-weiteres > summary > span:first-child::before { transition: none; }
}

/* Gruppenüberschriften der Seitenleiste. Sie sind keine Zierde: sie
   tragen die Gewichtung, die vorher niemand sehen konnte - oben die
   tägliche Arbeit, unten das Nachschlagewerk. Klein, ruhig und nicht
   anklickbar, damit sie nicht mit den Punkten selbst verwechselt werden. */
/* Der Wegweiser, der von der Rechnungsliste zur Abrechnung führt. Ruhiger
   als die Karte, die dort stand - er meldet nichts, er zeigt nur den Weg. */
.kassen-wegweiser .kassen-luecke-kopf { margin-top: 0; }
/* Regel 10 (18.09.2026): „Abrechnen" ist der einzige Weg aus dieser Karte
   heraus - ohne ihn ist sie eine Sackgasse mit Erklaerung. Er traegt die
   Akzentfarbe nicht, ist aber der Hauptknopf seiner Karte. */
@media (max-width: 640px) {
  .kassen-wegweiser .btn { min-height: 44px; }
}

/* Ein Ankreuzfeld sitzt neben seiner Beschriftung, nicht darüber wie die
   übrigen Felder - sonst steht das Häkchen allein in einer Zeile. */
.feld-ankreuz {
  display: flex;
  align-items: center;
  gap: .5rem;
  min-height: 2.6rem;
  cursor: pointer;
}
.feld-ankreuz input { width: auto; margin: 0; }

/* Hinweise zur Schreibweise sind KEINE Beanstandungen: die Datei ist in
   Ordnung. Sie stehen darum ruhiger da - zwei Spalten statt drei, weil es
   keine Prüfstufe gibt, und ohne die warnende Farbe der Befunde. Sähen sie
   aus wie Fehler, würde eine tadellose Abrechnung als fehlerhaft gelesen. */
.pruefung-hinweise li { grid-template-columns: 14rem 1fr; }
.pruefung-hinweis-fuss {
  margin: .5rem 0 0;
  font-size: .9em;
  opacity: .75;
}

@media (max-width: 640px) {
  .pruefung-liste li { grid-template-columns: 1fr; gap: .15rem; }
  .pruefung-hinweise li { grid-template-columns: 1fr; }
  /* Am Telefon steht der Weg allein in seiner Zeile - dort ist er zu
     treffen wie ein Knopf und bekommt die 44px aus Regel 10, ohne dass er
     jemandem den Platz nimmt (doku/gestaltung.md, WCAG SC 2.5.5). */
  .pruefung-weg { min-height: 44px; }
  .kassen-aktionen { margin-left: 0; }
  /* Dieselbe Sache wie in der Rechnungsliste, nur an der anderen Liste:
     „Prüfen", „Abrechnung abschließen", „Paket", „Begleitzettel", „Als
     eingereicht markieren" sind DIE Arbeit an einer Kassenabrechnung.
     Vom Betrieb am 17.09.2026 nachgezogen, nachdem die Zeilenaktionen der
     Rechnungsliste entschieden waren (Regel 10 in doku/gestaltung.md).
     Die Knöpfe mit der blossen Rechnungsnummer bleiben davon unberührt:
     sie haengen an li.kassen-luecke und nicht in .kassen-aktionen. */
  .kassen-aktionen .btn { min-height: 44px; }
}

/* Hinweise zu den Kostenträgerdateien - sie stehen ÜBER der Kassenliste,
   weil sie den Weg betreffen und nicht die einzelne Rechnung. */
.kassen-verzeichnis { margin: .25rem 0 .75rem; }

/* Die Startseite (L12). Aus „Heute" und „Nächste Schritte" geworden -
   dieselben Bausteine, nur an einem Ort. Die Klassen heissen seit dem
   12.09.2026 start-*, damit der Name die Ansicht nennt, in der sie
   stehen. */
.start-zahlen { display: flex; align-items: baseline; gap: 32px; flex-wrap: wrap; }
.start-gross { display: flex; flex-direction: column; gap: 2px; }
/* Die grosse Zahl ist seit dem 17.09.2026 ein WEG: „noch nicht abgerechnet"
   fuehrt in die Fahrten, wo die Arbeit liegt. Sie sieht deshalb aus wie der
   Geldzeiger daneben - gleiche Rolle, gleiche Gestalt (Regel 2). */
.start-offen {
  align-items: flex-start;
  padding: 6px 10px;
  margin: -6px 0 -6px -10px;
  background: none;
  border: none;
  border-radius: var(--radius-sm);
  cursor: pointer;
  font: inherit;
  text-align: left;
}
.start-offen:hover, .start-offen:focus-visible { background: var(--paper); }
.start-offen .start-wofuer { text-decoration: underline; text-underline-offset: 2px; }
/* „aus neun Fahrten" - die Herkunft der Summe, eine Stufe leiser als ihre
   Aufschrift. */
.start-dazu { font-size: 12px; color: var(--muted); }
.start-zahl {
  /* KEIN var(--font-display): Fraunces bleibt der Marke und den
     Seitentiteln vorbehalten (siehe tests/test_typografie.py). Die Zahl
     traegt dieselbe Gestalt wie die grosse Summe der Einnahmen - zwei
     Ansichten, die dasselbe tun, sollen nicht verschieden aussehen. */
  font-size: 40px;
  font-weight: 700;
  line-height: 1.05;
  letter-spacing: -0.025em;
  color: var(--heading);
  font-variant-numeric: tabular-nums;
}
.start-zahl-klein {
  font-size: 24px;
  font-weight: 600;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}
.start-wofuer { font-size: 13px; color: var(--muted); }

/* Das Geld des Monats steht NEBEN den Fahrten, sieht aber anders aus:
   es ist ein Weg, keine eigene Zahl dieser Seite. Zu Hause ist es unter
   „Meine Einnahmen", hier steht nur der Zeiger darauf. */
.start-geld {
  display: flex;
  flex-direction: column;
  gap: 2px;
  align-items: flex-start;
  padding: 6px 10px;
  margin: -6px 0 -6px -10px;
  background: none;
  border: none;
  border-radius: var(--radius-sm);
  cursor: pointer;
  font: inherit;
  text-align: left;
}
.start-geld:hover, .start-geld:focus-visible { background: var(--paper); }
.start-geld .start-wofuer { text-decoration: underline; text-underline-offset: 2px; }

.start-kopf { margin: 0 0 10px; font-size: 15px; }
.start-liste, .start-kassen { list-style: none; margin: 0; padding: 0; }
.start-fahrt {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  border-bottom: 1px solid var(--border);
}
.start-fahrt:last-of-type { border-bottom: none; }
.start-fahrt-knopf, .start-kasse-knopf {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 11px 6px;
  margin-left: -6px;
  text-align: left;
  background: none;
  border: none;
  border-radius: var(--radius-sm);
  cursor: pointer;
  font: inherit;
  color: inherit;
}
.start-fahrt-knopf:hover, .start-fahrt-knopf:focus-visible,
.start-kasse-knopf:hover, .start-kasse-knopf:focus-visible { background: var(--paper); }
.start-person, .start-kasse-name { font-size: 15px; font-weight: 600; color: var(--text); }
.start-wann { flex: 0 0 auto; font-size: 12px; color: var(--muted); }
.start-kassen li { border-bottom: 1px solid var(--border); }
.start-kassen li:last-of-type { border-bottom: none; }
.start-kasse-knopf { width: 100%; }

@media (max-width: 780px) {
  .start-zahlen { gap: 22px; }
}

/* Der Weg zurück ins Konto (L1). Unauffällig - er ist der Ausweg, nicht
   das Angebot: wer ihn sucht, findet ihn; wer ihn nicht braucht, wird
   nicht darauf gestoßen. */
.auth-vergessen { margin: 10px 0 0; text-align: center; }
.auth-vergessen button {
  background: none;
  border: none;
  padding: 4px;
  font: inherit;
  font-size: 13px;
  color: var(--muted);
  text-decoration: underline;
  cursor: pointer;
}
.auth-vergessen button:hover { color: var(--heading); }

/* Die Suche (L11). Ein Feld über der Liste, nicht in einer Leiste versteckt:
   wer sucht, sucht das Feld zuerst. Die Haus-Eingabegestaltung greift nur
   INNERHALB von .field - deshalb hier eigens gesetzt. */
.suchzeile { display: flex; gap: 8px; align-items: center; margin-bottom: 16px; }
/* Am Telefon ist das Feld schmaler als mancher Platzhalter (Betrieb,
   15.09.2026): dann drei Punkte statt eines abgeschnittenen Wortes. */
.suchzeile input {
  text-overflow: ellipsis;
  flex: 1 1 auto;
  max-width: 420px;
  padding: 10px 12px;
  border: 1px solid var(--rand-bedienelement);
  border-radius: 8px;
  font-family: var(--font-body);
  font-size: 14px;
  background: var(--surface);
  color: var(--text);
}
.suchzeile input:focus { border-color: var(--ink-light); outline: none; }
/* Wie viele Treffer - über der Liste, nicht darunter: die Zahl gehört zur
   Frage, nicht zum Ergebnis. */
.suchergebnis { margin: 0 0 10px; font-size: 13px; color: var(--muted); }

@media (max-width: 560px) {
  .suchzeile input { max-width: none; }
}

/* „Neue Fahrt" als Tür (Entwurf „Eine Tür, ein Bildschirm", 20.09.2026;
   gebaut 23.09.2026): nur die Wahl, ohne Kundenliste und ohne eigene Stufe
   für die Person - die kommt im Formular über die Lupe. Die Seite nimmt die
   968 px des Entwurfs - eine telefonbreite Spalte in der Mitte verschenkte
   am PC die Hälfte. */
.fahrtwahl-seite { max-width: 60.5rem; width: 100%; }
.fahrtwahl-kopf { display: flex; justify-content: space-between; align-items: flex-start; gap: 16px; flex-wrap: wrap; }
/* Die zwei Türen - und sonst nichts (Betrieb, 23.09.2026: „nur zwischen
   Kassen- und Privatfahrt wählen, in einem modernen Design"). Große Karten
   mit ruhigem Schatten, das Zeichen in einem getönten Kreis; beim Zeigen
   hebt sich die Karte an, den Fokus trägt der Akzent. */
.fahrtwahl-tueren { display: grid; grid-template-columns: 1fr 1fr; gap: 24px; margin-top: 8px; }
.fahrtwahl-tuer {
  position: relative; display: flex; flex-direction: column; align-items: flex-start; gap: 12px;
  min-height: 240px; padding: 28px; text-align: left; font: inherit; color: inherit; cursor: pointer;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
  box-shadow: var(--shadow);
  transition: transform 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease;
}
.fahrtwahl-tuer:hover { transform: translateY(-2px); border-color: var(--accent); }
.fahrtwahl-tuer:focus { outline: none; border-color: var(--accent); box-shadow: var(--shadow), 0 0 0 3px var(--stamp-accent-bg); }
.fahrtwahl-tuer:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.fahrtwahl-tuer-icon {
  display: inline-flex; align-items: center; justify-content: center; width: 72px; height: 72px;
  border-radius: 50%; background: var(--stamp-accent-bg); color: var(--accent-ink);
}
.fahrtwahl-tuer-icon svg { width: 44px; height: 44px; }
/* Die Hausschrift, nicht die Display-Schrift des Entwurfs: die bleibt Marke
   und Seitentitel vorbehalten (tests/test_typografie.py). */
.fahrtwahl-tuer-titel { margin-top: 4px; font-size: 24px; font-weight: 600; color: var(--heading); }
.fahrtwahl-tuer-text { font-size: 14px; line-height: 1.45; color: var(--muted); }
/* .toolbar setzt display:flex und schluege das [hidden] des Browsers - an
   der Tuer steht aber kein „Abbrechen" (dieselbe Falle wie der Hausknopf,
   .af-pick > .feld-knopf[hidden]). */
.fahrtwahl-seite > .toolbar[hidden] { display: none; }
@media (prefers-reduced-motion: reduce) {
  .fahrtwahl-tuer { transition: none; }
  .fahrtwahl-tuer:hover { transform: none; }
}
@media (max-width: 640px) {
  /* Am Telefon untereinander. */
  .fahrtwahl-tueren { grid-template-columns: 1fr; gap: 12px; }
  .fahrtwahl-tuer { min-height: 0; }
}
/* „+ Neuer Fahrgast" (E5, 16.09.2026; seit 23.09.2026 nur auf dem
   Privatweg). Nach den Regeln aus doku/gestaltung.md: Farben und Ecken aus
   den Marken, Abstände auf dem 2-px-Raster, Schrift auf der Leiter, ein
   Hauptknopf je Karte. */
.new-name { margin-bottom: 16px; }
.new-name h4 { margin: 0 0 12px; }
/* Die kleine Überschrift über einem Abschnitt einer Karte - in der
   Kundenfahrt die Abschnitte, beim neuen Fahrgast die Anschrift. */
.panel-label { margin: 0 0 8px; font-size: 14px; font-weight: 600; color: var(--heading); }

/* Die Kundenfahrt (E7). Oben das Band, das sagt, wohin die Fahrt geht.
   Darunter die
   Fahrten, die schon auf der offenen Rechnung stehen, mit ihrer Summe:
   wer eine Woche nachträgt, sieht, was schon drin ist. */
/* Die Maske springt beim Öffnen an den oberen Rand, wenn ihr Anfang nicht
   im Bild ist (siehe customerTripOpen). Am Telefon liegt dort die feste Kopfleiste (56px hoch) -
   ohne diesen Rand verschwände die erste Zeile der Maske darunter
   (Browserprobe, 16.09.2026). */
#customer-trip-panel, #new-name-panel { scroll-margin-top: 12px; }
@media (max-width: 780px) { #customer-trip-panel, #new-name-panel { scroll-margin-top: 68px; } }
.customer-trip { margin-bottom: 16px; }
.customer-trip-band {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 10px;
  align-items: baseline;
  margin: 0 0 14px;
  padding: 10px 12px;
  background: var(--stamp-accent-bg);
  border-radius: var(--radius-sm);
  font-size: 14px;
  color: var(--text);
}
.customer-trip-band strong { color: var(--heading); }
/* Die Fahrzeugwahl braucht Luft nach unten, sonst klebt das Kilometerfeld
   daran (Browserprobe, 16.09.2026). */
.customer-trip .segmentwahl { margin-bottom: 14px; }
.customer-trip-invoice { margin-top: 18px; padding-top: 14px; border-top: 1px solid var(--border); }
.customer-trip-list { list-style: none; margin: 0; padding: 0; }
.customer-trip-row {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 12px;
  align-items: center;
  padding: 8px 0;
  border-bottom: 1px solid var(--border);
}
.customer-trip-row-text { display: flex; flex-direction: column; gap: 2px; flex: 1 1 220px; font-size: 14px; }
.customer-trip-row-amount { font-size: 14px; font-weight: 600; font-variant-numeric: tabular-nums; color: var(--heading); }
.customer-trip-total { margin: 10px 0 0; font-size: 14px; font-weight: 600; color: var(--heading); font-variant-numeric: tabular-nums; }
/* Abschließen und Verschicken stehen in eigenen Karten unter der Maske: es
   sind andere Vorgänge als „Fahrt speichern", und jeder trägt seinen eigenen
   Hauptknopf (doku/gestaltung.md, Regel 3). */
.customer-invoice-close, .customer-invoice-done { margin-bottom: 16px; }
.customer-invoice-done { border-left: 2px solid var(--success); }

.kunde-schnell { margin-top: 14px; }
.kunde-schnell h4 { margin: 0 0 12px; }
/* Was nicht jedes Mal gebraucht wird, steht zugeklappt - wer es jedes Mal
   sähe, tippte irgendwann etwas hinein, weil ein leeres Feld nach einer
   Lücke aussieht. */
.kunde-schnell-weiteres { margin-top: 6px; }
.kunde-schnell-weiteres > summary {
  cursor: pointer;
  padding: 8px 0;
  font-size: 13px;
  color: var(--muted);
}
.kunde-schnell-weiteres[open] > summary { color: var(--text); }

/* Die Kassensuche über den Feldern, die sie füllt (E1, 16.09.2026).

   Sie steht IN der Maske, nicht als Überlagerung: die Trefferliste soll die
   Felder nicht verdecken, die sich gleich von selbst füllen. Die Suchzeile
   ist dieselbe wie bei den Fahrten - gleiche Dinge sehen gleich aus. */
.payer-search { margin-bottom: 14px; }
.payer-search .suchzeile { margin-bottom: 6px; }
.payer-search-results {
  list-style: none;
  margin: 0 0 6px;
  padding: 4px;
  max-width: 420px;
  max-height: 268px;
  overflow-y: auto;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
}
.payer-search-hit {
  display: flex;
  flex-direction: column;
  gap: 1px;
  width: 100%;
  padding: 8px 10px;
  text-align: left;
  background: none;
  border: 0;
  border-radius: var(--radius-sm);
  cursor: pointer;
  font: inherit;
  color: inherit;
}
.payer-search-hit:hover,
.payer-search-results li[aria-selected="true"] .payer-search-hit {
  background: var(--stamp-draft-bg);
}
.payer-search-name { font-size: 14px; font-weight: 600; color: var(--heading); }
.payer-search-meta { font-size: 12.5px; color: var(--muted); }
/* Das Kennzeichen in der Kennungsschrift, weil man es Zeichen für Zeichen
   mit der Versichertenkarte vergleicht. */
.payer-search-ik { font-family: var(--font-mono); }
.payer-search-note { margin: 0; font-size: 13px; color: var(--muted); }
.payer-search-note.fehler { color: var(--danger); }

@media (max-width: 560px) {
  .payer-search-results { max-width: none; }
}

/* Der Stand des Kostenträgerabrufs im Verwaltungsbereich. Ein Kasten, kein
   Alarm: an den allermeisten Tagen steht hier die gute Nachricht, und die
   soll nicht aussehen wie eine schlechte. Erst .gestoert färbt um. */
.admin-abruf {
  margin-top: 18px;
  padding: 12px 14px;
  border-left: 3px solid var(--accent);
  background: var(--paper);
  border-radius: 4px;
}
.admin-abruf p { margin: 0; }
.admin-abruf p + p, .admin-abruf ul { margin-top: 6px; }
.admin-abruf.gestoert { border-left-color: var(--danger); }
/* Der Satz zum roten Strich. Ohne ihn trug die Farbe die Aussage allein -
   die Meldungen darunter betreffen einzelne Dateien und fehlen gerade
   dann, wenn gar nichts mehr laeuft. */
.admin-abruf-stumm { color: var(--danger); font-weight: 600; }

/* Fahrgäste - wer bei diesem Betrieb fährt, und wie oft (N12a).
   Drei Spalten am Schreibtisch: wer, wie viel, wohin. Am Telefon
   untereinander, weil 420px für eine Zahl rechts außen nicht reichen. */
.fahrgast-liste { list-style: none; margin: 0; padding: 0; }
/* Die ganze Zeile ist EIN Knopf (N4, 17.09.2026).
   Vorher standen hier drei - „Scheine ansehen", „Bearbeiten", „Löschen" -,
   jeder 30px hoch, und daneben eine Zeile, die nichts tat. Jetzt tut die
   Zeile etwas, und die drei stehen im Fenster, das sie öffnet. */
.fahrgast {
  display: flex;
  align-items: center;
  gap: 16px;
  width: 100%;
  padding: 14px 8px 14px 0;
  border: none;
  border-bottom: 1px solid var(--border);
  background: none;
  font: inherit;
  color: inherit;
  text-align: left;
  cursor: pointer;
  border-radius: var(--radius-sm);
}
li:last-child > .fahrgast { border-bottom: none; }
.fahrgast:hover { background: var(--stamp-accent-bg); }
.fahrgast:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
/* Das Zeichen sagt, dass sich hier etwas öffnet - eine anklickbare Fläche
   ohne Zeichen sieht aus wie Text. */
.fahrgast-pfeil { flex: 0 0 auto; color: var(--muted); font-size: 18px; line-height: 1; }
.fahrgast-person { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.fahrgast-name { font-size: 15px; font-weight: 600; color: var(--text); }
.fahrgast-kasse { font-size: 13px; color: var(--text); }
.fahrgast-detail { font-size: 12px; color: var(--muted); }
.fahrgast-zahlen {
  flex: 0 0 auto;
  text-align: right;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
/* Die Zahl der Fahrten ist die Antwort auf die Frage dieser Liste - sie
   trägt deshalb als einzige Ziffernbreite und Gewicht. */
.fahrgast-fahrten {
  font-size: 15px;
  font-weight: 600;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}
@media (max-width: 780px) {
  .fahrgast { flex-wrap: wrap; }
  .fahrgast-person { flex: 1 1 100%; }
  .fahrgast-zahlen { flex: 1 1 auto; text-align: left; flex-direction: row; gap: 10px; align-items: baseline; }
  /* Das Zeichen bleibt rechts stehen, auch wenn der Rest umbricht. */
  .fahrgast-pfeil { margin-left: auto; }
}

/* --- Das Fenster zu einem Versicherten (N4) --------------------------- */

/* Breiter als eine Rückfrage und hoch genug für den Bogen: die Karte des
   Bestätigungsdialogs trägt einen Satz, diese hier dreiundzwanzig Felder. */
.fahrgast-fenster {
  width: min(560px, 100%);
  max-height: min(86vh, 48rem);
  display: grid;
  grid-template-rows: auto minmax(0, 1fr);
  padding: 0;
  text-align: left;
}
.fahrgast-fenster-kopf {
  display: grid;
  gap: 2px;
  padding: 16px 20px 12px;
  border-bottom: 1px solid var(--border);
}
.fahrgast-fenster-kopf b { font-size: 18px; font-weight: 600; color: var(--heading); }
.fahrgast-fenster-kopf span { font-size: 13px; color: var(--muted); }
/* Gescrollt wird INNEN: der Kopf mit dem Namen soll stehenbleiben, damit
   man auf Feld neunzehn noch weiss, wessen Angaben man ändert. */
.fahrgast-fenster-mitte { overflow-y: auto; padding: 16px 20px 18px; }
.fahrgast-fenster-fuss {
  margin-top: 18px;
  padding-top: 14px;
  border-top: 1px solid var(--border);
  justify-content: flex-start;
}
.fahrgast-fenster-rechts { margin-left: auto; display: flex; flex-wrap: wrap; gap: .25rem; }

/* Die Übersicht: Wort und Wert als Paare.
   Was FEHLT, steht als Gedankenstrich da - in einem Bogen sieht ein leeres
   Feld genauso aus wie eines, das man noch nicht gelesen hat. */
.paarliste { margin: 0; display: grid; }
.paarzeile {
  display: grid;
  grid-template-columns: 11rem minmax(0, 1fr);
  gap: 4px 16px;
  padding: 8px 0;
  border-bottom: 1px solid var(--border);
  font-size: 14px;
}
.paarzeile:last-child { border-bottom: none; }
.paarzeile dt { color: var(--muted); font-size: 13px; }
.paarzeile dd { margin: 0; color: var(--text); overflow-wrap: break-word; }
.paarzeile dd.leer { color: var(--muted); }
@media (max-width: 480px) {
  .paarzeile { grid-template-columns: 1fr; gap: 0; padding: 8px 0; }
}

/* Der Vorschlag „aus deinen Scheinen übernehmen". Ein Angebot, keine
   Warnung - deshalb die gewöhnliche Kartenfarbe und kein Rot. */
.hinweis-karte {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 14px;
  margin-bottom: 18px;
  border-left: 3px solid var(--accent);
}
.hinweis-karte p { margin: 0; }
.hinweis-karte p + p { margin-top: 4px; }

/* The "Trips" area (design A, 15.09.2026): toolbar with search, status and
   month; below it months, days and one block per trip or pair. */
.trips-toolbar { display: flex; flex-wrap: wrap; gap: 10px 12px; align-items: center; margin-bottom: 14px; }
.trips-toolbar .suchzeile { flex: 1 1 260px; margin-bottom: 0; }
.status-filter { display: inline-flex; flex-wrap: wrap; gap: 2px; padding: 3px; background: var(--stamp-draft-bg); border: 1px solid var(--border); border-radius: 10px; }
.status-filter-button { font: inherit; font-size: 13px; font-weight: 600; color: var(--muted); background: none; border: 0; border-radius: 7px; padding: 6px 11px; cursor: pointer; white-space: nowrap; }
.status-filter-button.active { background: var(--surface); color: var(--heading); box-shadow: 0 1px 2px rgba(27, 42, 74, .14); }
/* OHNE opacity: die Zahl traegt ueber .status-filter-button bereits --muted.
   Beides uebereinander ist zweimal dasselbe Mittel - und das zweite Mal
   rechnet keine Marke mit. Gemessen kam dabei 2,74:1 heraus, der
   schlechteste Wert der ganzen Anwendung (Ae2, 17.09.2026). */
.status-filter-count { margin-left: 6px; font-size: 11px; font-variant-numeric: tabular-nums; }
.trips-month { font: inherit; font-size: 13px; font-weight: 600; color: var(--heading); background: var(--surface); border: 1px solid var(--rand-bedienelement); border-radius: 8px; padding: 7px 10px; }
.trips-hint { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 14px; background: var(--info-bg); border-radius: 8px; padding: 8px 12px; margin-bottom: 14px; font-size: 13px; }
.trips-hint-gap { color: var(--danger); font-weight: 600; }
.trips-open-view { margin-bottom: 18px; }
.trip-month { margin-bottom: 22px; }
.trip-month-head { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: baseline; gap: 4px 12px; margin: 0 0 4px; padding-bottom: 4px; border-bottom: 2px solid var(--heading); font-size: 15px; font-weight: 700; color: var(--heading); }
.trip-month-figures { font-size: 13px; font-weight: 500; color: var(--muted); font-variant-numeric: tabular-nums; }
.trip-day-head { display: flex; justify-content: space-between; gap: 12px; margin: 14px 2px 6px; font-size: 12px; font-weight: 600; color: var(--muted); font-variant-numeric: tabular-nums; }
.trip-skeleton { display: grid; gap: 8px; }
.trip-skeleton-block { height: 92px; border: 1px solid var(--border); border-radius: 10px; background: var(--stamp-draft-bg); }
.trip-block { background: var(--surface); border: 1px solid var(--border); border-radius: 10px; margin-bottom: 8px; overflow: hidden; }
.trip-block-head { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 12px; padding: 9px 12px 6px; }
.trip-block-person { font-weight: 600; color: var(--heading); }
.trip-block-payer { flex: 1 1 8rem; min-width: 0; font-size: 12px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.trip-block-total { font-weight: 600; color: var(--heading); font-variant-numeric: tabular-nums; }
.trip-status { display: inline-flex; align-items: center; gap: 5px; font-size: 11.5px; font-weight: 600; padding: 3px 8px; border-radius: 999px; white-space: nowrap; }
.trip-status::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
.trip-status-open { background: var(--stamp-accent-bg); color: var(--accent-ink); }
.trip-status-gap { background: var(--danger-bg); color: var(--danger); }
.trip-status-payer { background: var(--info-bg); color: var(--heading); }
/* „Beim Kunden" (E8): dieselbe Stelle im Ablauf wie „bei der Kasse", aber ein
   anderer Schuldner - deshalb der messingfarbene Grund der Selbstzahler statt
   des blauen der Kassen. Das Wort steht daneben; die Farbe trägt nichts
   allein (L3). */
.trip-status-customer { background: var(--stamp-accent-bg); color: var(--accent-ink); }

/* Den Zahler einer Fahrt ändern (E9). Die Tafel öffnet UNTER der Fahrt, um
   die es geht - nicht als Überlagerung: man soll die Fahrt weiter sehen,
   während man entscheidet, wohin sie gehört. */
.payer-change-slot:empty { display: none; }
.payer-change {
  margin-top: 8px;
  padding: 12px 14px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
}
.payer-change-title { margin: 0 0 2px; font-size: 13px; color: var(--muted); }
.payer-change-target { margin: 0 0 10px; font-size: 15px; font-weight: 600; color: var(--heading); }
.payer-change-blocker { margin: 0 0 10px; font-size: 13px; color: var(--danger); }
.payer-change select { width: 100%; max-width: 420px; margin-bottom: 10px; }

.trip-status-paid { background: var(--success-bg); color: var(--success); }
.trip-status-cancelled { background: var(--stamp-draft-bg); color: var(--muted); }
.trip-leg { display: grid; grid-template-columns: 3.2rem minmax(0, 1fr) auto; gap: 10px; align-items: baseline; width: 100%; padding: 8px 12px; border: 0; border-top: 1px solid var(--border); background: none; font: inherit; text-align: left; color: var(--text); cursor: pointer; }
.trip-leg:hover { background: var(--stamp-draft-bg); }
.trip-leg-kind { font-size: 12px; font-weight: 600; color: var(--muted); }
.trip-leg-route { font-size: 13px; overflow-wrap: anywhere; }
.trip-leg-amount { font-size: 13px; font-weight: 600; font-variant-numeric: tabular-nums; white-space: nowrap; }
.trip-block-actions { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; justify-content: flex-end; padding: 5px 12px 7px; border-top: 1px solid var(--border); }
.repeat-field { display: inline-flex; gap: 6px; align-items: center; font-size: 12px; color: var(--muted); }
/* No line items means no amount. The note carries the warning colour - this is
   the trip that leaves the voucher incomplete. */
.fahrten-offen { font-size: 12px; font-weight: 600; color: var(--danger); }
.trip-header { display: grid; gap: 6px; margin: 0 0 12px; }
.trip-header-person { margin: 0; font-weight: 600; color: var(--heading); }
.trip-header-links { margin: 0; display: flex; flex-wrap: wrap; gap: 4px 16px; }

@media (max-width: 640px) {
  .status-filter { width: 100%; }
  .trip-block-payer { flex-basis: 100%; order: 3; }
  .trip-leg { grid-template-columns: 2.6rem minmax(0, 1fr) auto; }
  .trip-block-actions .btn { min-height: 44px; }
  /* Regel 10 (18.09.2026): „Ansehen" springt in den Filter der offenen
     Fahrten. Die knappste der vier Entscheidungen - auf 44px wiegt er in
     der schmalen Hinweiszeile fast so schwer wie der Hinweis selbst, genau
     das Argument, mit dem die Merken-Knoepfe klein geblieben sind. Der
     Betrieb hat anders entschieden: ein Hinweis, der eine Aktion traegt,
     ist keine Beigabe. */
  .trips-hint .btn { min-height: 44px; }
  /* Regel 10 (21.09.2026): „Logo entfernen" stand mit 30px da und wurde vom
     Bildlauf gemeldet. Er ist KEINE Beigabe zu einem Feld - er steht allein
     in seiner Fusszeile und loescht etwas. Nach derselben Ueberlegung wie
     bei „Ansehen" darueber: was eine Handlung traegt, bekommt die Flaeche. */
  .logo-fusszeile .btn { min-height: 44px; }
}

/* „Nochmal" - der Tag ist das Einzige, was sich zwischen zwei Dialysefahrten
   ändert, und er wird dort gefragt, wo der Knopf steht. Ein eigenes Fenster
   für ein einziges Feld wäre der falsche Preis (wir haben schon vier). */
.wiederholen-zeile {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  color: var(--muted);
}
.wiederholen-zeile input { width: auto; margin: 0; padding: 5px 8px; font-size: 13px; }
.wiederholen-wort { white-space: nowrap; }

/* Gespeicherte Orte (N7). Die Zeile steht unter der Abschnittsüberschrift,
   über den Feldern, die sie füllt - dort, wo man hinsieht, bevor man tippt. */
.ortwahl {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin-bottom: .7rem;
}
.ortwahl select { width: auto; min-width: 12rem; max-width: 100%; }
.ortmerken { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.ortmerken input { width: auto; min-width: 11rem; }

.ortliste { list-style: none; margin: 0; padding: 0; }
.ortzeile {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  padding: 12px 0;
  border-bottom: 1px solid var(--border);
}
.ortzeile:last-child { border-bottom: none; }
.ortzeile-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.ortzeile-name { font-size: 14px; font-weight: 600; color: var(--text); }
.ortzeile-anschrift { font-size: 12px; color: var(--muted); }

/* Ein Feld, das der Server abgelehnt hat (N1, 17.09.2026).
   Nicht nur Farbe: der Rand wird auch DICKER, und der Satz steht darunter -
   wer Rot und Grau nicht auseinanderhaelt, sieht trotzdem, welches Feld
   gemeint ist (WCAG SC 1.4.1). Die Marke setzt feldFehlerZeigen in
   static/js/12-feldfehler.js. */
/* !important, und zwar mit Absicht - der eine Fall, in dem es richtig ist.

   Die Marke ist ein ZUSTAND, keine Gestaltung: ein Feld, das der Server
   abgelehnt hat, muss rot sein, in welchem Kasten es auch steht. Jede
   Regel, die ein Feld nach seinem Ort gestaltet (`.field input`,
   `.suchzeile input`, `.hilfe-suche input`, `.admin-search
   input[type="search"]`), ist spezifischer als eine einzelne Klasse und
   gewaenne sonst. Genau das ist am 19.09.2026 zweimal passiert: erst im
   Firmenprofil (Rand grau, Flaeche weiss, obwohl die Klasse am Feld hing),
   dann - nach einer Ausnahme nur fuer `.field` - im Suchfeld der
   Fahrtenliste (Gegenlesen). Eine Liste von Ausnahmen veraltet mit dem
   naechsten Kasten; `!important` nicht.

   background-COLOR und nicht die Kurzform `background`: die Kurzform
   setzt auch das Hintergrundbild zurueck, und bei einem Auswahlfeld haengt
   daran der Pfeil. */
.feld-fehler,
.feld-fehler:focus,
.feld-fehler:focus-visible {
  border-color: var(--danger) !important;
  /* Auch die FLAECHE, nicht nur der Rand (N15, 19.09.2026). Ein roter
     Rand allein geht zwischen zwanzig gleich aussehenden Feldern unter -
     derselbe Grund, aus dem input.ungueltig seit dem 13.09.2026 beides
     setzt. Der Betrieb: „sodass der nutzer direkt weiss welches feld
     betroffen ist." */
  background-color: var(--danger-bg) !important;
  /* Der zweite Ring kommt als INNERER Schatten, nicht als dickerer Rand:
     ein Rand von 2px liesse das Feld wachsen und die Zeile darunter
     springen - und der Ausgleich ueber den Innenabstand ergaebe 9px, also
     einen Wert neben dem 2-px-Raster (Regel 5). Ein Schatten kostet kein
     Layout. */
  box-shadow: inset 0 0 0 1px var(--danger);
}
.feld-fehler-text {
  margin: 6px 0 0;
  font-size: 13px;
  line-height: 1.45;
  font-weight: 500;
  color: var(--danger);
}

/* MEHRERE Fehler an einem Formular (N15, 19.09.2026). Sie standen bis
   dahin in einer Zeile, mit "; " aneinandergeklebt:

     Bitte die Anrede ausfuellen.; Bitte die Unternehmensform ausfuellen.

   Der Betrieb: „fehler sollen untereinander aufgereiht werden."

   Ohne Aufzaehlungspunkte: die Fehlerstelle ist bereits rot hinterlegt
   und hebt sich ab; Punkte davor waeren ein zweites Signal fuer dasselbe.
   Der Abstand zwischen den Zeilen trennt sie deutlicher als ein Punkt es
   koennte. Bei EINEM Satz entsteht diese Liste gar nicht erst (siehe
   fehlerListeSetzen in static/js/12-feldfehler.js). */
.fehlerliste {
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.fehlerliste > [role="listitem"] { display: block; }

/* IM DIALOG setzt `.confirm-dialog-card p` jeden Absatz auf Textfarbe - und
   ist spezifischer als eine einzelne Klasse. Der Satz unter dem Feld stand
   dort also schwarz, und die Fehlerstellen der Dialoge „Quittung" und
   „Einreichen" (beides <p class="karten-fehler">) ebenso: roter Grund,
   schwarze Schrift. Gemessen am 19.09.2026 an den Bildern des
   Fahrgastbogens; beim Fahrgastbogen war es schon seit N1 (17.09.) so. */
.confirm-dialog-card .feld-fehler-text,
.confirm-dialog-card .karten-fehler {
  color: var(--danger);
}

/* Ein abgelehntes AUSWAHLFELD steckt in seiner Huelle, und darueber liegt
   der Platzhalter „Bitte waehlen" (13-wahlfelder.js). Bliebe er grau,
   stuende auf roter Flaeche ein Text in der Farbe fuer Nebensaechliches -
   und genau er ist hier die Ursache. */
.wahlfeld:has(select.feld-fehler) .wahlfeld-platzhalter {
  color: var(--danger);
}

/* Die FILTERLEISTE - „diese Woche", „letzter Monat", eine Belegart, eine
   Gruppe der Hilfe. Dieselbe Leiste an drei Stellen: Einnahmen, Dokumente,
   Hilfe.

   Bis zum 17.09.2026 gab es dafür KEIN CSS. Der Browser malte also seine
   eigenen Knöpfe: weiße Kästchen mit schwarzer Schrift, im Dunkelmodus ein
   Fremdkörper, am Telefon knapp zwanzig Pixel hoch und in zerfranste Reihen
   umgebrochen. Der Betrieb hat es mit einem Bild der Einnahmenseite
   gemeldet. Dass .hilfe-frag-uns darunter nur noch `border-color` und
   `color` setzt, zeigt: Rahmen und Fläche waren hier immer gemeint.

   Gleiche Form wie .btn-ghost - eine Leiste ist eine Reihe von Knöpfen und
   soll nicht aussehen wie eine zweite Erfindung. */
.monatsleiste {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 16px;
}
.monatsknopf {
  font: inherit;
  font-size: 14px;
  font-weight: 500;
  line-height: 1.2;
  min-height: 36px;
  padding: 8px 14px;
  border: 1px solid var(--rand-bedienelement);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--heading);
  cursor: pointer;
  transition: background .15s ease, border-color .15s ease, color .15s ease;
}
.monatsknopf:hover { background: var(--info-bg); border-color: var(--muted); }
.monatsknopf:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* Der gewählte Zeitraum ist kein Hauptknopf, sondern eine ANZEIGE: er
   trägt die Akzentfläche, damit man ohne Vergleichen sieht, welcher gilt.
   Nicht nur die Farbe - der Knopf trägt zusätzlich aria-pressed, und im
   Hellmodus trennt ihn auch das Gewicht der Schrift von den übrigen
   (WCAG SC 1.4.1). */
.monatsknopf.aktiv {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--auf-akzent);
  font-weight: 600;
}
.monatsknopf.aktiv:hover { background: var(--accent); border-color: var(--accent); }
@media (prefers-reduced-motion: reduce) { .monatsknopf { transition: none; } }
@media (max-width: 640px) {
  /* Am Telefon IST die Leiste die Bedienung dieser Seite - mit dem Daumen
     trifft man sie erst ab 44px (WCAG SC 2.5.5). Und die Knöpfe füllen
     ihre Reihe aus, statt als ungleich lange Schnipsel umzubrechen. */
  .monatsknopf { min-height: 44px; flex: 1 1 auto; }
}

/* Meine Einnahmen (N9). Die Summe groß, alles andere klein daneben - eine
   Seite mit fünf gleich großen Zahlen hat keine Antwort, sondern nur
   Angebote. */
.einnahmen-kopf { display: flex; flex-direction: column; gap: 20px; }
.einnahmen-summe { display: flex; flex-direction: column; gap: 2px; }
.einnahmen-betrag {
  font-size: 40px;
  font-weight: 700;
  line-height: 1.05;
  letter-spacing: -0.025em;
  color: var(--heading);
  font-variant-numeric: tabular-nums;
}
.einnahmen-spanne { font-size: 13px; color: var(--muted); }
.einnahmen-kennzahlen { display: flex; flex-wrap: wrap; gap: 28px; }
.einnahmen-kennzahl { display: flex; flex-direction: column; gap: 1px; }
.einnahmen-kennzahl-wert {
  font-size: 19px; font-weight: 600; color: var(--text);
  font-variant-numeric: tabular-nums;
}
.einnahmen-kennzahl-wort { font-size: 12px; color: var(--muted); }

/* Woher das Geld steht - ein Balken statt dreier Zahlen: die Verhältnisse
   sieht man, die Zahlen stehen daneben. */
.einnahmen-stand { display: flex; flex-direction: column; gap: 10px; }
.standbalken {
  display: flex;
  height: 10px;
  border-radius: 5px;
  overflow: hidden;
  background: var(--border);
}
.standteil { display: block; }

/* Die drei Staende unterscheiden sich NICHT nur in der Farbe (L3, WCAG
   SC 1.4.1). Vorher tat genau das: drei Segmente in Gruen, Gold und Grau,
   und daneben eine Legende aus drei Punkten in denselben drei Farben. Wer
   Gruen und Gold nicht auseinanderhaelt, konnte weder die Segmente
   zuordnen noch die Legende lesen - und die Legende war selbst nichts
   anderes als eine Farbzuordnung.

   Jetzt trennt sie zusaetzlich die FUELLART, und die ist in Balken und
   Legende dieselbe:

     bezahlt   volle Flaeche
     gestellt  Schraffur
     offen     nur Umriss

   Die Farben bleiben, wie sie waren - sie tragen jetzt nur nicht mehr
   allein. */
.stand-bezahlt { background: var(--success, #3F7159); }
.stand-gestellt {
  background: var(--accent);
  background-image: repeating-linear-gradient(
    45deg,
    rgba(255, 255, 255, 0.55) 0 2px,
    transparent 2px 5px);
}
.stand-offen {
  background: transparent;
  box-shadow: inset 0 0 0 1.5px var(--muted);
}
.standlegende { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 16px; }
.standlegende li { display: flex; align-items: center; gap: 6px; font-size: 12px; color: var(--muted); }
.standlegende strong { color: var(--text); font-variant-numeric: tabular-nums; }
/* Ein Rechteck, kein Punkt: auf 9px rund ist eine Schraffur nicht zu
   erkennen, und die Legende soll genau das zeigen, was im Balken steht. */
.standpunkt { width: 16px; height: 10px; border-radius: 3px; flex: 0 0 auto; }

/* Der Verlauf: reine CSS-Säulen. Ein Diagramm aus zwölf Werten braucht kein
   Fremdpaket, und die Farben sollen die des Hauses sein. */
.verlauf {
  display: flex;
  align-items: flex-end;
  gap: 4px;
  height: 160px;
  margin-top: 6px;
}
.verlauf-saeule {
  flex: 1 1 0;
  min-width: 0;
  height: 100%;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  align-items: stretch;
  gap: 5px;
}
.verlauf-balken {
  background: var(--accent);
  border-radius: 3px 3px 0 0;
  /* Ohne Mindesthöhe verschwindet ein kleiner Betrag ganz und sieht aus
     wie eine Null - der Unterschied zwischen „wenig" und „nichts". */
  min-height: 2px;
}
.verlauf-saeule:hover .verlauf-balken { background: var(--accent-ink, var(--accent)); }
.verlauf-marke {
  font-size: 10px;
  color: var(--muted);
  text-align: center;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  overflow: hidden;
}

/* Wer bezahlt - Name, Balken, Betrag. */
.zahlerliste { list-style: none; margin: 6px 0 0; padding: 0; }
.zahlerzeile {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 9px 0;
  border-bottom: 1px solid var(--border);
}
.zahlerzeile:last-child { border-bottom: none; }
.zahlername { flex: 1 1 40%; min-width: 0; font-size: 14px; color: var(--text); }
.zahlerart {
  display: inline-block;
  margin-left: 8px;
  font-size: 11px;
  color: var(--muted);
}
.zahlerbalken {
  flex: 1 1 30%;
  height: 8px;
  border-radius: 4px;
  background: var(--border);
  overflow: hidden;
}
.zahlerbalken span { display: block; height: 100%; background: var(--accent); border-radius: 4px; }
.zahlerbetrag {
  flex: 0 0 auto;
  font-size: 14px;
  font-weight: 600;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}

@media (max-width: 780px) {
  .einnahmen-betrag { font-size: 34px; }
  .zahlerzeile { flex-wrap: wrap; }
  .zahlername { flex: 1 1 100%; }
  .zahlerbalken { flex: 1 1 auto; }
}

/* Die Hilfe (N8). Einundzwanzig Antworten will niemand durchscrollen:
   zugeklappt, mit Suche, und aus der Anwendung heraus führen Verweise auf
   genau die Antwort, die dort gerade fehlt. */
.hilfe-suche { margin-bottom: 20px; }
/* Die Feldgestaltung des Hauses gilt nur INNERHALB von .field (siehe oben).
   Ein Suchfeld steht nicht in einem Formularfeld und sah deshalb aus wie
   ein Kasten, den der Browser mitgebracht hat - schmal, kantig, fremd. */
.hilfe-suche input {
  width: 100%;
  max-width: 26rem;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: 8px;
  font-family: var(--font-body);
  font-size: 14px;
  background: var(--surface);
  color: var(--text);
}
.hilfe-suche input:focus { border-color: var(--ink-light); }
.hilfe-gruppe h2 { margin-bottom: 4px; }
.hilfe-liste { list-style: none; margin: 0; padding: 0; }
.hilfe-eintrag { border-bottom: 1px solid var(--border); }
.hilfe-eintrag:last-child { border-bottom: none; }
.hilfe-frage {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 14px;
  width: 100%;
  padding: 13px 0;
  background: none;
  border: none;
  text-align: left;
  font: inherit;
  font-size: 14px;
  font-weight: 600;
  color: var(--text);
  cursor: pointer;
}
/* Auch ein Zeigezustand muss lesbar sein: --accent als Schrift kommt auf
   3,06:1, die Frage steht in 14px. Dieselbe Entscheidung wie bei
   .schritt-tat (Ae2) - der Bildlauf hat sie hier nur nicht gefunden, weil
   er den RUHEZUSTAND misst. */
.hilfe-frage:hover { color: var(--accent-ink); }
.hilfe-pfeil { flex: 0 0 auto; font-size: 17px; color: var(--muted); line-height: 1; }
.hilfe-eintrag.offen .hilfe-pfeil { color: var(--accent-ink); }
.hilfe-antwort { padding: 0 0 16px; max-width: 46rem; }
.hilfe-antwort p { font-size: 14px; line-height: 1.65; color: var(--text); margin: 0 0 10px; }
.hilfe-antwort p:last-child { margin-bottom: 0; }
.hilfe-begriffe {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: 6px 16px;
  margin: 4px 0 12px;
}
.hilfe-begriffe dt { font-weight: 600; font-size: 13px; color: var(--heading); }
.hilfe-begriffe dd { margin: 0; font-size: 13px; line-height: 1.55; color: var(--muted); }

/* Das „?" neben einer Abschnittsüberschrift. Klein, aber anklickbar - es
   führt auf DIE Antwort, nicht auf die Hilfeseite. */
.hilfe-punkt {
  margin-left: 8px;
  width: 20px;
  height: 20px;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: 50%;
  background: none;
  color: var(--muted);
  font: inherit;
  font-size: 12px;
  font-weight: 700;
  line-height: 1;
  cursor: pointer;
  vertical-align: middle;
}
/* Der RAND darf die Flaechenfarbe tragen (3,06:1, fuer einen Rand verlangt
   SC 1.4.11 drei), das Fragezeichen darin nicht: es steht in 12px fett.
   Vom allgemeinen Test gefunden, nicht vom Bildlauf - ein Zeigezustand. */
.hilfe-punkt:hover { border-color: var(--accent); color: var(--accent-ink); }

@media (max-width: 640px) {
  .hilfe-begriffe { grid-template-columns: 1fr; gap: 2px; }
  .hilfe-begriffe dd { margin-bottom: 8px; }
  /* Am Telefon größer: 20px sind mit dem Daumen nicht zu treffen. */
  .hilfe-punkt { width: 28px; height: 28px; font-size: 14px; }
}

/* Die Sprungleiste der Hilfe. Fünf Gruppen und einundzwanzig Fragen sind
   viel zum Scrollen - ein Antippen bringt einen dorthin, wo man vermutet.
   „Frag uns" steht ganz rechts: der letzte Schritt, wenn nichts passt. */
.hilfe-sprungleiste { margin-bottom: 18px; }
/* Wie .schritt-tat: der RAND darf die Flaechenfarbe tragen (3,06:1, und
   fuer einen Rand verlangt SC 1.4.11 nur drei), die SCHRIFT nicht. */
.hilfe-frag-uns { border-color: var(--accent); color: var(--accent-ink); }
.hilfe-frag-uns:hover { background: var(--accent); border-color: var(--accent); color: var(--auf-akzent); }

/* Der Platz fuer das Turnstile-Kaestchen im Kontaktformular (N5).
   Es wird erst beim Hineinfassen gezeichnet; bis dahin ist der Platz leer
   und soll KEINE Luecke reissen - deshalb waechst der Abstand erst, wenn
   wirklich etwas darin steht. */
.turnstile-platz:not(:empty) { margin: 14px 0 4px; }

/* Der Kontaktkasten - am Ende, nicht am Anfang: erst nachlesen, dann
   fragen. Eine Hilfe, die mit einem Formular beginnt, ist ein Postfach mit
   Fußnoten. */
.hilfe-kontakt { border-color: var(--accent); }
.hilfe-kontakt-text { font-size: 14px; color: var(--muted); margin: 0 0 16px; max-width: 46rem; }
.hilfe-kontakt textarea { min-height: 7rem; resize: vertical; }

/* Anfragen aus der Hilfe im Verwaltungsbereich (10.09.2026).
   Eine Liste und keine Tabelle: der längste Teil ist die Frage selbst, und
   ein Fließtext in einer Tabellenzelle wird entweder abgeschnitten oder
   sprengt die Spaltenbreiten. */
.anfragenliste { list-style: none; margin: 12px 0 0; padding: 0; }
.anfrage {
  padding: 14px 0;
  border-bottom: 1px solid var(--border);
}
.anfrage:last-child { border-bottom: none; }
/* Abgehakt heißt nicht weg - nur leiser. Wer den Filter „Alle" wählt, soll
   auf einen Blick sehen, was noch Arbeit macht. */
.anfrage.erledigt { opacity: .6; }
.anfrage-kopf { display: flex; flex-wrap: wrap; align-items: baseline; gap: 10px; }
.anfrage-wer { font-size: 14px; font-weight: 600; color: var(--text); }
.anfrage-thema {
  font-size: 11px;
  padding: 2px 8px;
  border-radius: 999px;
  background: var(--border);
  color: var(--heading);
}
.anfrage-wann { font-size: 12px; color: var(--muted); margin-left: auto; }
.anfrage-text {
  font-size: 14px;
  line-height: 1.6;
  color: var(--text);
  margin: 8px 0 10px;
  max-width: 52rem;
  white-space: pre-wrap;
}
.anfrage-fuss { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }
.anfrage-seite { font-size: 12px; color: var(--muted); margin-right: auto; }
.anfrage-erledigt { font-size: 12px; color: var(--muted); margin: 8px 0 0; }

/* Die Marke am Reiter. Der Reiter ist ein Knopf mit Text - die Marke muss
   daneben passen, ohne die Zeile zu sprengen. */
.admin-tab .nav-zaehler {
  margin-left: 6px;
  min-width: 18px;
  height: 18px;
  line-height: 18px;
  font-size: 11px;
  display: inline-block;
  vertical-align: middle;
}

@media (max-width: 640px) {
  .anfrage-wann { margin-left: 0; flex: 1 1 100%; }
  .anfrage-seite { flex: 1 1 100%; margin-right: 0; }
}

/* Dokumente (N10). Eine Zeile je Vermerk: Art, Datei mit Bezug, Datum, Weg
   dorthin - dieselbe Anordnung wie in der Fahrtenliste, damit man nicht
   zweimal lernen muss, wo was steht. */
.dokumentliste { list-style: none; margin: 0; padding: 0; }
.dokumentzeile {
  display: flex;
  align-items: baseline;
  gap: 14px;
  padding: 11px 0;
  border-bottom: 1px solid var(--border);
}
.dokumentzeile:last-child { border-bottom: none; }
.dokument-art {
  flex: 0 0 11rem;
  font-size: 13px;
  font-weight: 600;
  color: var(--text);
}
.dokument-wohin { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.dokument-name { font-size: 13px; color: var(--text); word-break: break-all; }
.dokument-bezug { font-size: 12px; color: var(--muted); }
.dokument-wann {
  flex: 0 0 auto;
  font-size: 12px;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.dokument-fussnote { margin: 14px 0 0; max-width: 46rem; }

@media (max-width: 780px) {
  .dokumentzeile { flex-wrap: wrap; }
  .dokument-art { flex: 1 1 100%; }
  .dokument-wohin { flex: 1 1 100%; }
}

/* ---------- IK-Vergabebescheid (C13) ---------- */
/*
 * Der Nachweis im Firmenprofil und die Pruefmaske der Verwaltung.
 * Beide benutzen dieselben Zustandsfarben, damit "wartet" und
 * "freigegeben" an beiden Orten gleich aussehen - der Betrieb und der
 * Pruefende sprechen sonst ueber verschiedene Bilder.
 *
 * Alle Farben kommen aus den vorhandenen Variablen; es gibt keinen neuen
 * Ton. Die drei Zustaende bedienen sich bei den Stempeln, die die
 * Rechnungsliste schon kennt.
 */

/* Kein eigener Rahmen: der Nachweis steht seit dem 13.09.2026 in einer
   eigenen Karte ganz oben im Firmenprofil, und die bringt ihren Rahmen
   mit. Ein zweiter waere ein Kasten im Kasten. */

/* Abstand zum Speichern-Knopf darueber. Ohne ihn stiess der Stempel
   ("wird geprueft") an den Knopf "Nummer speichern" - beide sitzen
   rechtsbuendig, und der Stempel ist leicht gedreht, ragt also nach oben
   heraus. Im Bild vom 13.09.2026 ueberlappten sie sichtbar.
   :not(:empty), damit ohne Nachweis kein Loch entsteht. */
#cp-ik-nachweis:not(:empty) { margin-top: 26px; }
.ik-nachweis {
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.ik-nachweis h3 { margin: 0; }

.ik-nachweis-text { margin: 0; color: var(--muted); }
/* Der Hinweis "trag zuerst die Nummer ein" ist KEINE Warnung, sondern der
   naechste Schritt. Er stand zuerst im selben Rot wie eine Ablehnung -
   neben einer echten Fehlermeldung sahen dann zwei rote Kaesten
   untereinander aus, als waere zweimal etwas schiefgegangen. */
.ik-nachweis-schritt {
  margin: 0;
  padding: 8px 12px;
  border-radius: 8px;
  color: var(--accent-ink);
  background: var(--stamp-accent-bg);
}

/* Ein Feld mit einem Knopf darin - die geprueft IK-Nummer und ihr Stift.
   Der Knopf sitzt IM Feld und nicht daneben: daneben waere er ein zweites
   Bedienelement in der Reihe, im Feld gehoert er sichtbar zu genau dieser
   einen Nummer. */
.feld-mit-knopf { position: relative; display: block; }

.feld-mit-knopf > input { width: 100%; padding-right: 44px; }

.feld-knopf {
  position: absolute;
  top: 50%;
  right: 6px;
  transform: translateY(-50%);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* 32px sichtbar, aber die Trefferflaeche reicht ueber den Rand hinaus -
     am Telefon trifft man sonst danebem. */
  width: 32px;
  height: 32px;
  padding: 0;
  border: 0;
  border-radius: 8px;
  background: transparent;
  color: var(--muted);
  cursor: pointer;
}

.feld-knopf svg { width: 17px; height: 17px; }

.feld-knopf:hover { background: var(--stamp-draft-bg); color: var(--text); }

.feld-knopf:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

/* Das gesperrte Feld: ruhiger Grund, aber KEIN ausgegrauter Text - die
   Nummer ist die Hauptinformation der Karte und muss lesbar bleiben.
   Der Grund allein reicht als Aussage nicht (1,15:1 hell / 1,12:1 dunkel
   gegen den Kartengrund) - deshalb das Schloss davor. */
input.gesperrt {
  background: var(--stamp-draft-bg);
  cursor: default;
  padding-left: 38px;
}

.feld-schloss {
  position: absolute;
  top: 50%;
  left: 11px;
  transform: translateY(-50%);
  width: 15px;
  height: 15px;
  color: var(--muted);
  /* Sonst faengt es den Klick ab, der ins Feld gehen soll. */
  pointer-events: none;
}

.ik-aendern-hinweis { margin-top: 6px; color: var(--accent-ink); }

/* Die Entwurfsleiste oben im Formular ist am 23.09.2026 entfallen (Betrieb:
   „den Hinweis, dass es zwischengespeichert wurde, entfernen") - Entwuerfe
   sichern und setzen sich still ein (46-drafts.js). */

/* Der Stand des Nachweises - eine Zeile: Zeichen, Stand, naechster Schritt.
   Bis zum 13.09.2026 war das ein .stamp: Schreibmaschinenschrift,
   Versalien, gestrichelt, um 1,5 Grad gedreht. Das ist ein RECHNUNGS-
   element ("ENTWURF", "BEZAHLT") - ein Bearbeitungsstand ist kein Stempel
   auf einem Dokument, und "NOCH KEIN NACHWEIS HOCHGELADEN" in Versalien
   ist ein Satz, der als Stempel auftritt. */
.ik-stand {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 11px 14px;
  border-radius: 10px;
  border-left: 4px solid currentColor;
  font-size: 14px;
  font-weight: 600;
  line-height: 1.45;
  flex-wrap: wrap;
}
.ik-stand svg { width: 18px; height: 18px; flex: none; }
/* Der erklaerende Teil traegt die Textfarbe: farbig ist der STAND, nicht
   der ganze Satz - sonst schreit die Zeile. */
.ik-stand span { color: var(--text); font-weight: 500; }

/* Und kompakt fuer die Liste der einzelnen Uploads: dort steht der Stand
   neben Dateiname, Datum und "Ansehen" - eine Leiste ueber die ganze
   Breite waere dort ein Block zu viel. */
.ik-pille {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 4px 11px 4px 9px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 600;
  line-height: 1.3;
}
.ik-pille::before {
  content: "";
  width: 6px; height: 6px;
  border-radius: 50%;
  background: currentColor;
  flex: none;
}

/* Die vier Zustaende - dieselben Farben in Leiste und Pille, damit beide
   dieselbe Sprache sprechen. "wartet" borgt sich den Entwurfs-Ton, weil es
   genau das ist: noch nichts entschieden. */
.ik-stand-none      { color: var(--muted);      background: var(--stamp-draft-bg); }
.ik-stand-pending   { color: var(--accent-ink); background: var(--stamp-accent-bg); }
.ik-stand-approved  { color: var(--success);    background: var(--success-bg); }
.ik-stand-rejected  { color: var(--danger);     background: var(--danger-bg); }
/* Fuenfter Zustand, nur beim Rahmenvertrag (77-framework-contract.js): der
   Vertrag liegt uns schon vor, es ist nichts zu tun. Gruen wie "freigegeben"
   - es ist dieselbe Aussage aus Sicht des Betriebs. */
.ik-stand-covered   { color: var(--success);    background: var(--success-bg); }

.ik-nachweis-liste { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
/* Der Weg zur Datei steht rechts und bleibt dort - auch wenn der Name
   umbricht.
   Bis zum 14.09.2026 lief alles in EINER umbrechenden Reihe: Name, Zeiten
   und ein Wort „Ansehen". Am Telefon landete das Wort dadurch allein in
   einer eigenen Zeile, linksbuendig unter dem Datum, und sah aus wie ein
   Teil davon. Der Betrieb: *„Der Ansehen Button gefällt mir irgendwie
   nicht."* Aus vier Entwuerfen wurde D gewaehlt.
   Jetzt zwei Bloecke: links Name und Zeiten untereinander, rechts der
   Knopf. `margin-left: auto` haelt ihn am rechten Rand, `flex: 1 1 180px`
   laesst den Namen umbrechen, bevor der Knopf abrutscht. */
.ik-nachweis-liste li {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  font-size: 13px;
}

.ik-eintrag {
  display: flex;
  flex-direction: column;
  gap: 2px;
  /* Volle Breite: seit der Name selbst der Weg ist, steht rechts daneben
     nichts mehr, dem der Eintrag Platz machen muesste. */
  flex: 1 1 100%;
  min-width: 0;
  overflow-wrap: anywhere;
}

.ik-zeiten { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }

/* Der Dateiname IST der Weg zur Datei - kein zweites Wort daneben.
   Der Betrieb am 14.09.2026 aus vier Entwuerfen: *„Der Ansehen Button
   gefällt mir irgendwie nicht"* -> Entwurf B.
   Vorher stand rechts ein Wort („Ansehen", spaeter „PDF öffnen"), das
   dasselbe meinte wie der Name links daneben. Am Telefon brach es in eine
   eigene Zeile und sah aus wie ein Teil des Datums.
   Die Unterstreichung traegt die Aussage - sie kommt ohne Farbe aus und
   jeder kennt sie. */
.ik-datei-link {
  display: block;
  width: 100%;
  padding: 0;
  border: 0;
  background: none;
  text-align: left;
  font-family: var(--font-mono);
  font-size: 13px;
  line-height: 1.4;
  color: var(--accent-ink);
  cursor: pointer;
  /* Der Abstand haelt die Linie von den Unterlaengen frei (p, g, j). */
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
  /* Ein langer Name ohne Trennstelle sprengt sonst die Karte. */
  overflow-wrap: anywhere;
}

.ik-datei-link:hover { text-decoration-thickness: 2px; }
.ik-datei-link:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.ik-datei { font-family: var(--font-mono); word-break: break-all; }
.ik-zeit { color: var(--muted); }
.ik-nachweis-aktion { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.ik-dateiname { color: var(--muted); font-size: 13px; word-break: break-all; }

/* Regel 10, vom Betrieb am 18.09.2026 entschieden (Vorlage:
   https://claude.ai/artifact/91UdZWLgxoSPqaghpFmj1W).

   Zwei Gruppen, ein Grund: es sind die Aktionen, fuer die es diese Karten
   gibt. „Diesen Tarif verwenden" waehlt den Vertrag, nach dem jede spaetere
   Positionsnummer gerechnet wird - eine Wahl, die einmal im Jahr getroffen
   wird, also ohne Uebung. „Vertrag/Bescheid hochladen" ist die EINZIGE
   Aktion seiner Karte und traegt schon die Akzentfarbe; ein Hauptknopf in
   Akzentfarbe, der 28px hoch ist, widerspricht sich selbst. Beide oeffnen
   den Dateiwaehler des Telefons - danebengetippt passiert nichts, und
   niemand weiss, warum.

   Eng gehalten: .ik-zeiten traegt in den beiden anderen IK-Karten nur
   Pillen und Zeitangaben, dort greift die Regel ins Leere. */
@media (max-width: 640px) {
  .ik-zeiten .btn { min-height: 44px; }
  .ik-nachweis-aktion .btn { min-height: 44px; }
}

/* Die Pruefmaske: Angaben links, Dokument rechts. Ab 720px nebeneinander -
   darunter untereinander, sonst stehen zwei halbe Spalten nebeneinander,
   in denen nichts mehr lesbar ist. */
.ik-pruefkarte { display: flex; flex-direction: column; gap: 14px; }
.ik-pruef-spalten { display: grid; grid-template-columns: 1fr; gap: 16px; }
@media (min-width: 720px) {
  .ik-pruef-spalten { grid-template-columns: 1fr 1fr; }
}
.ik-pruef-angaben h3 { margin: 0 0 6px; }
.ik-pruef-zeile { margin: 0; color: var(--muted); font-size: 14px; }
.ik-pruef-nummer { margin: 8px 0 0; font-family: var(--font-mono); font-weight: 600; }
.ik-pruef-dokument { display: flex; flex-direction: column; align-items: flex-start; gap: 8px; }
/* Die Entscheidung. Das Begruendungsfeld stand zuerst als nacktes
   input-Element neben den Knoepfen - ohne Beschriftung, ohne die Formen
   der uebrigen Felder, in einer Zeile zusammengequetscht. Jetzt traegt es
   Label und Platzhalter wie jedes andere Feld (.field), und die Knoepfe
   stehen darunter statt daneben: eine Begruendung schreibt man, bevor man
   entscheidet. */
.ik-pruef-entscheidung {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding-top: 14px;
  border-top: 1px solid var(--border);
}
.ik-grund-feld { margin: 0; }
.ik-grund-feld textarea { resize: vertical; min-height: 56px; }
.ik-pruef-knoepfe { display: flex; gap: 10px; flex-wrap: wrap; }
@media (min-width: 720px) {
  /* Am Schreibtisch rechtsbuendig - dort, wo der Blick nach dem Lesen
     des Feldes ohnehin ankommt. */
  .ik-pruef-knoepfe { justify-content: flex-end; }
}


/* Was der Transportschein bisher kostet - unter der Positionsliste.
   Bis zum 14.09.2026 sah der Betrieb die Summe erst beim Einreichen; ein
   Zahlendreher fiel damit auf, wenn die Rechnung fertig war. Die Zahlen
   kommen fertig vom Server (api/items.py: betraege) - sie sind dieselben,
   die in die Abrechnungsdatei gehen. */
.beleg-summen {
  margin-top: 14px;
  padding: 12px 14px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--stamp-draft-bg);
  display: grid;
  gap: 4px;
  /* Ziffern untereinander - sonst tanzt die Spalte bei jeder Zeile. */
  font-variant-numeric: tabular-nums;
}

.summen-zeile {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  font-size: 13.5px;
  color: var(--muted);
}

/* Die Summe traegt mehr Gewicht als ihre Teile - sie ist die Zahl, die
   zur Kasse geht. */
.summen-brutto {
  margin-top: 4px;
  padding-top: 8px;
  border-top: 1px solid var(--border);
  font-size: 15px;
  color: var(--text);
}

.summen-brutto strong { font-weight: 600; }

/* --- Die Erfassungsmaske fuer Vertraege (js-admin/20-tariff-editor.js) ---
   Ein Vertrag besteht aus Gruppen, die sich wiederholen: Perioden,
   Bausteine, Beispielrechnungen. Jede Gruppe bekommt einen eigenen Rahmen -
   ohne ihn laufen zwanzig Felder zu einer einzigen Wand zusammen, und
   niemand sieht mehr, welcher Preis zu welchem Baustein gehoert. */
.tarif-block {
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 14px;
  margin-bottom: 12px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

/* Name und Wert nebeneinander, das Kreuz daneben. Unter 520px untereinander:
   drei Felder in einer Zeile sind auf dem Telefon drei Streifen. */
.tarif-paare { display: flex; flex-direction: column; gap: 8px; margin-bottom: 8px; }
.tarif-paar { display: grid; grid-template-columns: 1fr; gap: 8px; align-items: center; }
@media (min-width: 520px) {
  .tarif-paar { grid-template-columns: 1fr 1fr auto; }
  /* Die Bedingung traegt drei Angaben statt zwei: Feld, Vergleich, Wert. */
  .tarif-bedingung { grid-template-columns: 1.4fr auto 1fr auto; }
  /* Die Anlass-Tabelle traegt seit N8 (18.09.2026) eine dritte: den Wortlaut
     des Vertrags neben Kurzname und Auspraegung. Ohne eigene Spalte fiele
     das Kreuz in eine zweite Zeile. */
  .tf-anlaesse .tarif-paar { grid-template-columns: 1fr 1fr 1.6fr auto; }
}

/* Für welche Kassen ein Vertrag benutzt wird, und wie lange er Preise trägt
   (16.09.2026). Die Wahl der Kasse steht als Tafel unter der Vertragszeile -
   dieselbe Bauart wie der Zahlerwechsel an der Fahrt: die Frage erscheint
   dort, wo sie gestellt wird, und nicht in einem Fenster darüber. */
.tarif-kassen { display: flex; flex-wrap: wrap; gap: 6px 12px; margin-top: 4px; }
.tarif-kasse { display: inline-flex; align-items: center; gap: 4px; font-size: 13px; color: var(--muted); }
.tarif-warnung { color: var(--accent-ink); font-weight: 600; }
.tarif-wahl {
  margin-top: 10px;
  padding: 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--stamp-draft-bg);
}
.tarif-wahl .field { margin-bottom: 8px; }

/* ============================================================================
   Auswaehlen und Suchen (A6, 21.09.2026) - app/static/js/14-picker.js
   und 15-calendar.js.

   Vier Muster, EINE Bauart: offene Liste bis 8 Eintraege, Liste mit Filter
   ab 9, Suche ueber wachsende oder fremde Daten, Datum. Die Huelle ist die
   des Hauses (.wahlfeld bzw. .feld-mit-knopf), das Feld ist ein .field input;
   hier steht NUR, was abweicht. Bauvertrag: pruefung/umbau-abrechnungsfall/
   BAUVERTRAG-A6.md.

   Der Zustand steht im ARIA-Attribut (aria-selected, aria-expanded), das
   Stylesheet liest es - keine zweite Wahrheit in einem Klassennamen.
   ========================================================================== */
.af-pick { display: block; position: relative; }
.af-pick > input { padding-right: 34px; }
.af-pick.af-has-btn > input { padding-right: 80px; }
/* Der Fokusring des Hauses nimmt --ink, und das ist im Dunkelmodus die
   Flaeche der Seitenleiste (1,13:1). --accent traegt in beiden Modi. */
.af-pick > input:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.af-pick-icon {
  position: absolute; top: 50%; right: 10px; transform: translateY(-50%);
  display: inline-flex; width: 16px; height: 16px; color: var(--muted); pointer-events: none;
}
.af-pick-icon svg { width: 16px; height: 16px; }
.af-pick.af-has-btn > .af-pick-icon { right: 40px; }
/* Der zweite Knopf (mehrere Tage) sitzt links neben dem ersten. */
.af-pick > .feld-knopf.af-pick-btn2 { right: 40px; }
.af-pick.af-has-btn2 > input { padding-right: 80px; }
.af-pick.af-has-btn2 > .af-pick-icon { display: none; }
.af-pick.af-open > .af-pick-icon { color: var(--text); }
/* .feld-knopf setzt display:inline-flex und schluege das [hidden] des
   Browsers - der Hausknopf muss aber mit der Person kommen und gehen. */
.af-pick > .feld-knopf[hidden] { display: none; }
/* Die Lupe als Knopf (TUER-LUPE-BAUVERTRAG.md, L): ein .feld-knopf wie Haus
   und Kalender, dieselbe Trefferflaeche. Neben dem Hausknopf sitzt sie links
   davon - wie der zweite Kalenderknopf. */
.af-pick.af-has-lupe > input { padding-right: 44px; }
.af-pick.af-has-lupe.af-has-btn > input { padding-right: 80px; }
.af-pick.af-has-btn > .feld-knopf.af-pick-lupe { right: 40px; }
.af-pick.af-open > .feld-knopf.af-pick-lupe { color: var(--text); }

/* Die Ueberlagerung: IN der Huelle, 4 px unter dem Feld; klappt nach oben,
   wenn darunter kein Platz ist (Klasse af-pick-up, kein style-Attribut).
   320 px: acht einzeilige Eintraege (8 x 37,7 px) ohne Bildlauf - genau
   die Grenze, ab der eine Liste einen Filter bekommt (MUSTER.md). */
.af-pick-panel {
  position: absolute; z-index: 80; top: calc(100% + 4px); left: 0;
  min-width: 100%; max-width: 420px;
  background: var(--surface); border: 1px solid var(--rand-bedienelement);
  border-radius: var(--radius-sm); box-shadow: var(--shadow);
}
.af-pick.af-pick-up > .af-pick-panel { top: auto; bottom: calc(100% + 4px); }
/* Seitlich ins Bild geschoben, wenn die Ueberlagerung rechts hinausragte
   (14-picker.js: _pickerFlip setzt die Marke am Element; hier ihr Ruhewert). */
.af-pick-panel {
  --af-shift: 0px;
  transform: translateX(var(--af-shift));
}
.af-pick-list {
  list-style: none; margin: 0; padding: 4px; max-height: 320px; overflow-y: auto;
}
.af-pick-count { margin: 0; padding: 4px 10px; font-size: 12px; color: var(--muted); }
.af-pick-hit {
  display: flex; flex-direction: column; gap: 2px; padding: 8px 10px;
  border-radius: var(--radius-sm); cursor: pointer;
}
.af-pick-hit:hover { background: var(--stamp-draft-bg); }
/* Der Tastaturzeiger: die Toenung allein misst 1,15:1 - der Umriss dazu
   (Muster .fahrgast:focus-visible). */
.af-pick-hit[aria-selected="true"] {
  background: var(--stamp-draft-bg); outline: 2px solid var(--accent); outline-offset: -2px;
}
.af-pick-name { font-size: 14px; font-weight: 600; color: var(--heading); }
.af-pick-meta { font-size: 12px; color: var(--muted); }
.af-pick-list mark { background: var(--treffer-bg); color: inherit; font-weight: 600; padding: 0; }
.af-pick-panel > .empty-state { padding: 12px 10px; }
.af-pick-new { margin: 4px; }
.af-pick-new:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

/* Der Kalender: dieselbe Ueberlagerung, aber ohne Deckel - ein Monat mit
   sechs Zeilen ist 383 px hoch (gemessen), und der Fuss mit "Heute" darf
   nicht unter der Kante liegen. */
.af-cal { width: max-content; max-width: calc(100vw - 32px); max-height: none; padding: 10px; }
.af-cal .serie-kopf { gap: 4px; }
.af-cal-title { font-size: 14px; font-weight: 600; color: var(--heading); flex: 1 1 auto; text-align: center; }
/* Die Wochentagsnamen sind eine eigene Reihe UEBER der Listbox - keine
   Eintraege darin, die eine Vorlesehilfe mitzaehlte. */
.af-cal-weekdays { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 4px; }
.af-cal-weekday { font-size: 11px; font-weight: 600; color: var(--muted); text-align: center; padding: 4px 0; }
/* 7 x 40 px passt nicht auf 320 px (gemessen: 324 mit Rand und Polster) -
   die Zellen duerfen schrumpfen, das Raster bleibt siebenspaltig. */
.af-cal .serie-raster { grid-template-columns: repeat(7, minmax(0, 1fr)); }
.af-cal .serie-tag { width: auto; min-width: 0; }
/* aria-selected heisst hier GEWAEHLT (das sagt es der Vorlesehilfe); der
   Tastaturzeiger ist data-cursor - das Raster traegt den Fokus. */
.af-cal .serie-tag[data-cursor="true"] { outline: 2px solid var(--accent); outline-offset: -2px; }
.af-cal .serie-raster:focus-visible { outline: 0; }
.af-cal .serie-tag.af-cal-today { border-color: var(--accent); }
.af-cal-chips { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 4px; margin: 0 0 8px; }
.af-cal-legend { display: flex; gap: 12px; margin: 8px 0 0; font-size: 12px; color: var(--muted); }
.af-cal-legend i { display: inline-block; width: 10px; height: 10px; border-radius: var(--radius-sm); vertical-align: middle; margin-right: 4px; }
.af-cal-legend i.af-cal-dot { background: var(--muted); }
.af-cal-legend i.af-cal-sel { background: var(--accent); }
.af-cal-foot { display: flex; justify-content: space-between; align-items: center; gap: 8px; padding: 8px 0 0; }
.af-cal-foot .af-cal-stand { font-size: 13px; color: var(--muted); }

@media (max-width: 640px) {
  .af-pick-list > .af-pick-hit { min-height: 44px; }
  .af-cal-chips .serie-wochentag, .af-cal .btn-sm { min-height: 44px; }
  .af-pick-panel { max-width: calc(100vw - 32px); }
}

/* ============================================================================
   Abrechnungsfall (A7, 21.09.2026) - app/static/fragments/view-case.html
   und app/static/js/62-case.js / 63-case-form.js.

   Aufbau "Werkbank" (Festlegung des Betriebs, 21.09.2026): Formular links,
   klebende Begleitspalte rechts. Die Felder stehen in einem Raster aus vier
   Spalten; jedes Feld sagt selbst, wie viele davon es nimmt (af-sp1..4) -
   so steht die Reihenfolge der eingefrorenen Referenz.

   Hier steht NUR, was abweicht. Karte, Feld, Knopf, Tabelle und Abzeichen
   sind die des Hauses (.card, .field, .btn, .data-table, .stamp); das
   Bauteil "Auswaehlen und Suchen" bringt seine eigene Gestaltung mit
   (Abschnitt oben).
   ========================================================================== */
.af-spalte { min-width: 0; }
.af-card { margin-bottom: 20px; }
.af-card h2 { margin: 0 0 4px; }
.af-hinweis { margin: 0 0 16px; font-size: 13px; color: var(--muted); }

/* Vier Spalten am Schreibtisch. Am Telefon steht jedes Feld fuer sich -
   ein Raster, in dem sp1 und sp4 nebeneinander stehen, ergaebe dort
   Felder von 60 px Breite. */
.af-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 0 16px; }
.af-fd { min-width: 0; }
.af-sp1 { grid-column: span 1; }
.af-sp2 { grid-column: span 2; }
.af-sp3 { grid-column: span 3; }
.af-sp4 { grid-column: span 4; }


/* Ein Feld, das nur zeigt: derselbe Kasten, aber ohne Bedienrand - sonst
   sieht es aus wie ein Eingabefeld, das nichts annimmt. */
.af-read input, .af-read .af-wert {
  border-color: var(--border);
  background: var(--paper);
  color: var(--text);
}
.af-wert {
  display: block; width: 100%; padding: 10px 12px;
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  font-size: 14px; min-height: 42px;
}
.af-wert.mono { font-family: var(--font-mono); }

/* Haken - einer oder mehrere nebeneinander in EINEM Feldplatz. */
.af-haken { display: flex; flex-wrap: wrap; gap: 8px 16px; padding: 6px 0 12px; }
.af-haken label { display: flex; align-items: center; gap: 8px; font-size: 14px; color: var(--text); }
.af-haken input { width: 18px; height: 18px; }

/* Die Reiter der zweiten Karte. */
.af-tabs { display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: 16px; border-bottom: 1px solid var(--border); }
.af-tabs button { border-radius: var(--radius-sm) var(--radius-sm) 0 0; }
.af-tabs button[aria-selected="true"] {
  background: var(--stamp-accent-bg); color: var(--accent-ink); font-weight: 600;
}
.af-tafel { min-width: 0; }

/* Zwischenüberschrift im Raster („Abholort", „Zielort"): ohne sie stehen
   acht Adressfelder ununterscheidbar untereinander. */
.af-unter {
  grid-column: 1 / -1;
  margin: 8px 0 8px;
  font-size: 13px;
  font-weight: 600;
  color: var(--muted);
}
/* Der Vertragsblock nimmt die ganze Breite und bringt sein eigenes Raster
   mit - er entsteht erst zur Laufzeit und nur, wenn der Vertrag danach
   fragt (64-case-trip.js). */
#af-tarif-block { grid-column: 1 / -1; }
/* Ein Hinweis, der sagt, warum gerade nichts geht. */
.af-gesperrt { color: var(--accent-ink); }

/* ---- Die Kopfleiste (A9b, Entwurf 7, Betrieb 21.09.2026) ---------------
   Vorbild `.belege-seite > .page-header`: klebend, Ebene 5, Grund der
   Seite, Trennlinie statt Schatten.

   WARUM SIE OBEN STEHT, gemessen (MESSUNG-kopfleiste.md): die Begleitspalte
   nahm dem Formular 280 px - bei 980 px blieben 388 px und 73 px je
   Rasterspalte, in die „TT.MM.JJJJ" nicht hineinpasst. Und unterhalb von
   961 px klappte das Raster einspaltig, die Spalte rutschte UNTER alle
   sechs Karten: „Speichern" stand bei y = 4739 auf einer 4926 px hohen
   Seite.

   24 px Luft nach rechts: der Dunkelmodus-Knopf steht fest bei 16-54 px
   vom rechten Rand (.theme-toggle-btn, Ebene 200) und wird nicht
   verschoben - das ist eine Hausentscheidung. Ueber z-index waere die eine
   oder die andere Seite verdeckt; Abstand ist die ehrliche Loesung.
   Der Inhalt endet bei W-40 (.main), der Knopf beginnt bei W-54: noetig
   sind 14 px, gegeben 24. */
.af-kopf {
  position: sticky;
  top: 0;
  z-index: 5;
  background: var(--paper);
  border-bottom: 1px solid var(--border);
  margin: 0 0 20px;
  padding: 8px 0 0;
}
.af-kopf-z1 { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; min-width: 0; }
.af-kopf h1 {
  margin: 0; font-size: 18px; font-weight: 700; line-height: 1.2;
  color: var(--heading); min-width: 0; flex: 0 1 auto;
}
/* `flex: 1 1 0` und nicht `auto`: beim Zeilenumbruch zaehlt ein Flex-Element
   mit seiner INHALTSBREITE, nicht mit der geschrumpften. Mit `auto` sprangen
   die Aktionen unter den Titel, sobald der Stand gefuellt war - also nach
   dem ersten Speichern, und nur dann (Gegenlesung A9b). */
.af-kopf-stand {
  flex: 1 1 0; min-width: 0; font-size: 11px; color: var(--muted);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.af-kopf-tat { display: flex; gap: 8px; flex: 0 0 auto; margin-left: auto; padding-right: 24px; }
/* Eine Zeile, gedaempft; die Betraege fett in der Akzenttinte.
   SIE BRICHT UM, statt abzuschneiden: das Ende der Zeile ist der Betrag,
   den die Kasse zahlt - und `text-overflow` wirkt in einem Flex-Behaelter
   ohnehin nicht, es haette ihn stumm abgeschnitten (Gegenlesung A9b).
   `min-height` haelt die Hoehe, solange die Zeile leer ist: sonst spraenge
   die Leiste beim ersten Speichern. */
.af-kopf-z2 {
  display: flex; align-items: center; min-height: 34px;
  margin-top: 8px; padding: 6px 0 8px;
  border-top: 1px solid var(--border);
  font-size: 12px; color: var(--muted);
}
.af-kopf-z2 b { font-weight: 600; color: var(--accent-ink); font-variant-numeric: tabular-nums; }

/* Der Platz, den die klebende Leiste verdeckt - EINMAL gesagt, aus ihrer
   GEMESSENEN Hoehe (66-case-list.js schreibt `--af-kopf-hoehe`). Er gilt
   fuer alles, was der Browser ins Bild holt: den Sprung auf Karte 3
   (67-case-edit.js), den Tastaturfokus beim Rueckwaertsgehen mit Umschalt-
   Tabulator und die Fehleranzeige. Drei geratene Konstanten waeren drei
   Gelegenheiten, daneben zu liegen. */
html:has(#view-case:not(.hidden)) { scroll-padding-top: calc(var(--af-kopf-hoehe, 88px) + 20px); }

/* ---- Karte 4 und 5: die Tabellen (A9, 21.09.2026) ----------------------
   Tabelle, Zeile und Zelle sind die des Hauses (.data-table). Hier steht
   nur, was abweicht: die rechtsbuendigen Zahlenspalten, die eingerueckte
   Leistungszeile und der EINE Schalter, der die Positionen zeigt. */
.af-tab-kopf { display: flex; justify-content: space-between; align-items: center; gap: 8px; margin-bottom: 8px; }
.af-tab-stand { font-size: 13px; color: var(--muted); font-variant-numeric: tabular-nums; }
/* Neun Spalten passen am Schreibtisch, dazwischen nicht immer. Dann
   scrollt die TABELLE fuer sich - die Seite darf es nicht (Regel 1 des
   Bildlaufs: querscrollen). */
.af-tab-wrap { overflow-x: auto; }
.af-fahrten-tabelle .af-r, .af-dok-tabelle .af-r { text-align: right; }
.af-fahrten-tabelle .af-sp-nf, .af-dok-tabelle .af-sp-nf { width: 88px; }
.af-fahrt-zeile { cursor: pointer; }
.af-fahrt-zeile:hover td { background: var(--stamp-draft-bg); }
.af-fahrt-nr { display: flex; align-items: center; gap: 4px; }
.af-pos-zeile td { color: var(--muted); }
.af-pos-zeile .af-leistung { padding-left: 16px; }
/* Der Zustand steht im hidden-Attribut, nicht in einem style-Attribut.
   Die Regel MUSS sein: in der Telefonansicht traegt jede Tabellenzeile
   `display: block`, und das schlaegt das [hidden] des Browsers - alle
   Positionen stuenden dort offen. */
.af-fahrten-tabelle .af-pos-zeile[hidden] { display: none; }
.af-neu-zeile td { color: var(--muted); font-size: 13px; }
/* Ein Knopf, der nur im Bearbeitungsmodus dasteht, traegt `hidden` - und
   das allein genuegt nicht: `.btn` setzt `display`, und eine Klasse
   schlaegt das [hidden] des Browsers. Genau diese Falle hat schon der
   Hausknopf im Feld gestellt (.af-pick > .feld-knopf[hidden], A6); hier
   stand „Neu rechnen" dadurch dauerhaft in der Fusszeile der Karte 3,
   auch ohne Vertrag und ohne Fahrt. Gemessen in der A9-Probe ohne
   Rahmenvertrag. */
/* Der Selektor nennt ABSICHTLICH nicht `.karten-fuss .btn`: diese
   Zeichenkette darf ausserhalb des 640er-Blocks nirgends stehen, sonst
   faellt die Wache ueber die Beruehrflaechen (tests/test_gestaltung.py
   sucht sie als Teilzeichenkette). */
.karten-fuss [hidden] { display: none; }
.af-a4-fuss { justify-content: space-between; }
.af-summe { font-size: 14px; color: var(--text); font-variant-numeric: tabular-nums; }

@media (max-width: 640px) {
  .af-grid { grid-template-columns: minmax(0, 1fr); }
  .af-sp1, .af-sp2, .af-sp3, .af-sp4 { grid-column: span 1; }
  .af-tabs button { min-height: 44px; }
  .af-fahrten-tabelle .af-zeile-knopf { min-height: 44px; }
  /* Der Kopfschalter der Karte 4. Er war bis zum 21.09.2026 zufaellig
     hoch genug: „+ Positionen zeigen" brach am Telefon auf zwei Zeilen
     um. Mit dem kuerzeren Hauswort „Posten" steht er einzeilig da und
     misst 30 px - der Bildlauf hat es sofort gemeldet. */
  .af-tab-kopf .btn { min-height: 44px; }
  /* Die drei Aktionen bekommen eine eigene Zeile und die Beruehrflaeche
     des Hauses. Bei 390 px stehen innen 350 px zur Verfuegung; mit 12 px
     Schrift und 8 px Polster brauchen die drei zusammen rund 337 px -
     knapp. `flex-wrap` ist das Netz: lieber eine zweite Zeile als ein
     Knopf, der aus dem Bild ragt. */
  .af-kopf-tat { flex: 1 1 100%; flex-wrap: wrap; gap: 4px; margin-left: 0; }
  .af-kopf-tat .btn { min-height: 44px; flex: 1 1 auto; padding: 8px; font-size: 12px; }
}

/* Ab 780 px baut das Haus jede .data-table in Kaertchen um: thead weg,
   Zeile und Zelle als Block, die Spaltenueberschrift als data-label ueber
   dem Wert. Rechtsbuendig und eingerueckt ergeben dort keinen Sinn - und
   eine LEERE Zelle ist dort ein leerer Block, von dem eine Fahrtzeile drei
   traegt. */
@media (max-width: 780px) {
  .af-fahrten-tabelle .af-r, .af-dok-tabelle .af-r { text-align: left; }
  .af-pos-zeile .af-leistung { padding-left: 0; }
  .af-fahrten-tabelle td:empty, .af-dok-tabelle td:empty { display: none; }
  /* Unter der festen Kopfzeile des Hauses (56 px) - dasselbe Muster wie
     bei `.belege-seite > .page-header`. Ab hier sitzt auch der
     Dunkelmodus-Knopf IN dieser Kopfzeile, die Luft rechts wird
     gegenstandslos. */
  .af-kopf { top: 56px; }
  .af-kopf-tat { padding-right: 0; }
  html:has(#view-case:not(.hidden)) { scroll-padding-top: calc(var(--af-kopf-hoehe, 130px) + 76px); }
}

/* Unter 1061 px passt der Stand nicht mehr neben Titel und Aktionen -
   gemessen (pruefung/a9b-stand.js): er braucht 175 px, frei sind bei
   980 px nur 94. Abgeschnitten stand dort „Entwurf · Beleg…" - ausgerechnet
   das Wort, das im Haus nicht allein vorkommen darf. Also bekommt er eine
   eigene Zeile, statt seinen Text zu verlieren. */
@media (max-width: 1060px) {
  .af-kopf-stand { order: 3; flex: 1 1 100%; white-space: normal; }
}

/* Wenig Hoehe - Querformat, 200 % Schrift, kleine Fenster: dann klebt die
   Leiste nicht mehr, sondern scrollt mit. Bei 360 px Fensterhoehe naehme
   sie sonst die Haelfte des Bildes, und vom Formular bliebe nichts.
   (Nicht vom Betrieb gesehen, im Zweifel umkehrbar: ENTSCHEIDUNGEN.md E17.) */
@media (max-height: 560px) {
  .af-kopf { position: static; }
  html:has(#view-case:not(.hidden)) { scroll-padding-top: 0; }
}
