/* ─────────────────────────────────────────────────────────────────────
   AGA Tax — gemeinsame Oberfläche
   Monochrom, ein einziger Akzent, Milchglas. Keine externen Abhängigkeiten:
   keine Webfonts, keine Icon-Bibliothek, kein Build.
   ───────────────────────────────────────────────────────────────────── */

:root {
  color-scheme: light;
  /* Die zwei Grundstoffe als RGB-Tripel: die Tinte (Raender, Hover,
     Rollbalken — ueberall rgba(var(--tinte-rgb), α)) und das Glasweiss
     (alle halbdurchsichtigen Flaechen). Das dunkle Thema unten tauscht
     NUR diese Tripel und die Volltoene — jede der ~160 Ableitungen folgt
     von selbst, keine muss einzeln gepflegt werden.
     AUSNAHME: die Schiene. Sie ist in BEIDEN Themen dunkel, ihr Weiss ist
     deshalb woertlich (#fff / --schiene-hell) und kein Token, das kippt. */
  --tinte-rgb:    34,37,42;
  --hell-rgb:     255,255,255;
  --schiene-hell: 255,255,255;
  --flaeche:      #fbfbfa;   /* Listen und ruhige Flaechen */
  --flaeche-hoch: #fff;      /* Detail, Blatt, Palette — liegt obenauf */
  --flaeche-matt: #f3f4f5;   /* eingelassene Kaesten, Vorschau */
  --flaeche-leise: #f4f4f5;
  --fussleiste:   rgba(240,243,245,.94);
  /* Das Leuchten hinter der Buehne (body::before). Im Dunkeln gedimmt —
     ein weisser Schein auf schwarzem Grund saehe aus wie eine Lampe. */
  --schein:       rgba(255,255,255,.85);
  --grund:        #b9bbbb;
  --grund-tief:   #a8abab;
  /* Durchsichtiger als zuvor (.42) und deutlich staerker unscharf. Glas,
     das man kaum durchsehen kann, ist kein Glas — es ist helles Grau. */
  --glas:         rgba(var(--hell-rgb),.28);
  --glas-tief:    rgba(var(--hell-rgb),.18);
  /* Deckende Entsprechung zu `--glas` fuer haftende Streifen. Ein
     durchsichtiger Streifen, der ueber einer rollenden Liste stehen bleibt,
     zeigt die Zeilen durch sich hindurch — man liest dann zwei Dinge
     uebereinander. Deckend ist hier kein Stilbruch, sondern die einzige
     lesbare Loesung. */
  --glas-fest:    #eceeef;
  --glas-rand:    rgba(var(--hell-rgb),.42);
  --glas-kante:   rgba(var(--hell-rgb),.85);
  --dunkel:       #1b1c1e;
  --tinte:        #22252a;
  --tinte-matt:   #6c7176;
  --tinte-leise:  #8f9499;
  /* ── Zwei Farben, zwei Aufgaben (17.08.2026) ──────────────────────────
     Bis heute war Smaragd BEIDES: die Bedienfarbe (Knöpfe, Fokus, aktiver
     Reiter) und die Datenfarbe (Einnahmen im Verlauf, positive Differenz).
     Dann sieht ein Balken aus wie ein Knopf, und ein Knopf wie eine Zahl.
     Bakis shadcn-Preset trennt es sauber — Blau für die Oberfläche,
     Smaragd für Diagramme —, und die Trennung ist von ihm freigegeben.

     `--akzent`  bedient: Knöpfe, Fokusring, aktive Kachel, Links
     `--daten`   zeigt:   Einnahmen, positive Differenzen, Diagramme

     Blau ist bewusst kräftig genug für Text auf hellem Grund (Kontrast
     4,6:1 gegen #fbfbfa) — ein zartes Blau wäre auf der Glasfläche nicht
     mehr als Bedienelement erkennbar. */
  --akzent:       #2563eb;
  --akzent-flach: rgba(37,99,235,.13);
  --daten:        #12b981;
  --daten-flach:  rgba(18,185,129,.14);
  --warn:         #d99521;
  --warn-flach:   rgba(217,149,33,.15);
  --alarm:        #d0584c;
  /* Die Form ist ab jetzt binär: RECHTECK oder KREIS, nichts dazwischen.
   *
   * Baki, nachdem die dichten Listen standen: „mach die runden dinge dann
   * auch eckig damit es zusammen passt." Er hat recht, und es ist mehr als
   * Geschmack — eine Liste aus 40-px-Zeilen mit 1-px-Haarlinien lebt von
   * der geraden Kante. Daneben ein 30-px-Radius am Rahmen und eine
   * 999-px-Pille in der Zelle, und das Auge findet keine gemeinsame Kante
   * mehr. Die schwebenden runden Karten WAREN das ursprüngliche Problem.
   *
   * Die drei Token stehen deshalb auf 0. Das ist eine Zeile statt vierzig
   * und hält jede künftige Regel automatisch mit. Kreis bleibt Kreis, wo
   * er eine Bedeutung hat: das Kürzelbild, die Statuspunkte, die
   * Scrollbalkengriffe. */
  --r-gross:      0;
  --r-mittel:     0;
  --r-klein:      0;
  --spur:         .01em;

  /* ── Bewegung ──────────────────────────────────────────────────────
     Dieselbe Kurve stand zehnmal von Hand im Stylesheet. Zehn Stellen,
     die fast gleich sind, werden irgendwann zehn Stellen, die es nicht
     mehr sind. Jetzt steht sie einmal hier.

     Die Wahl der Kurve folgt der Bewegungsart, nicht dem Geschmack:
       auf/zu, hinein/hinaus     → ease-out, startet schnell
       etwas verschiebt sich     → ease-in-out
       Farbe, Überfahren         → ease
     ease-in gibt es nicht: es beginnt langsam und verzögert genau den
     Moment, auf den der Benutzer schaut. */
  --kurve-raus:    cubic-bezier(0.23, 1, 0.32, 1);
  --kurve-beides:  cubic-bezier(0.77, 0, 0.175, 1);
  --kurve-schub:   cubic-bezier(0.32, 0.72, 0, 1);

  /* Dauern. Oberfläche bleibt unter 300 ms; nur Schübe (Leiste, Blatt)
     dürfen darüber, weil sie eine größere Strecke zurücklegen. */
  --zeit-druck:    160ms;
  --zeit-klein:    180ms;
  --zeit-mittel:   240ms;
  --zeit-schub:    380ms;

  /* Zwei Ergaenzungen von 2026-08-17, als das Bewegungssystem
     zusammengefuehrt wurde. Bewusst KEIN zweites Zeitvokabular daneben:
     `--zeit-*` ist an 29 Stellen in Gebrauch, ein paralleles `--takt-*`
     waere genau die Redundanz aus Regel 2 gewesen. Neu ist nur, was es
     wirklich noch nicht gab — eine Strecke und ein Versatz. */
  --weg-klein:     6px;    /* Eintritt von unten. Mehr wippt.          */
  --stufung:       40ms;   /* Versatz je Zeile beim Aufbau einer Liste */
}

/* ── Ein Schalter fuer alle Bewegung ──────────────────────────────────────
   Bis heute stand `prefers-reduced-motion` an sieben Einzelstellen, jede
   fuer ein Feature. Wer eine neue Animation schrieb, musste daran denken —
   und genau das vergisst man. Jetzt werden die Tokens selbst auf null
   gesetzt: alles, was an ihnen haengt, steht damit still, ohne dass es
   irgendwo noch einmal erwaehnt werden muss. Die sieben Altblöcke bleiben,
   sie schalten Dinge ab, die keine Zeitangabe haben (Dauerschleifen).

   `0.01ms` statt `0`: ein `transitionend`, das nie kommt, laesst Code
   haengen, der darauf wartet. Praktisch unsichtbar, technisch vorhanden. */
@media (prefers-reduced-motion: reduce) {
  :root {
    --zeit-druck: 0.01ms; --zeit-klein: 0.01ms;
    --zeit-mittel: 0.01ms; --zeit-schub: 0.01ms;
    --weg-klein: 0px; --stufung: 0ms;
  }
}

* { box-sizing: border-box; margin: 0; padding: 0; }
/* Die Volltonfarbe unter dem Verlauf. Zwei Gruende, nicht einer:
   Safari faerbt seine Leisten auf dem iPhone nach der Hintergrundfarbe der
   Seite an deren Rand — einen Verlauf liest es dabei nicht aus und nimmt
   Weiss. Ergebnis waren zwei weisse Baender, oben und unten. Und wenn der
   Verlauf einmal nicht laedt, steht die Schrift trotzdem auf einer
   definierten Flaeche statt auf Weiss. */
html { background-color: var(--grund-tief); }
/* ── Das dunkle Thema ─────────────────────────────────────────────────────
 *
 * Folgt der Systemeinstellung (prefers-color-scheme), kein eigener
 * Umschalter — das ist der Standard, und ein Schalter waere eine weitere
 * Einstellung, die niemand bestellt hat. Getauscht werden NUR die Toene:
 * die zwei RGB-Tripel (Tinte, Glasweiss), die Volltonflaechen und der
 * Grund. Alle ~160 Ableitungen (Raender, Hover, Glas, Rollbalken) folgen
 * von selbst. Die Schiene bleibt dunkel wie immer — ihr Weiss haengt an
 * --schiene-hell und kippt nicht. */
@media (prefers-color-scheme: dark) {
  /* `:not([data-thema="hell"])` ist der Kern des Schalters: ohne das gilt
     die Systemeinstellung WEITER, auch wenn jemand ausdruecklich „hell"
     gewaehlt hat — dann waehlt er hell und bekommt dunkel. Das Attribut
     hebt den Systemwunsch auf, nicht umgekehrt. */
  :root:not([data-thema="hell"]) {
    color-scheme: dark;
    --tinte-rgb:    230,232,234;
    --hell-rgb:     124,132,142;
    --flaeche:      #1e2124;
    --flaeche-hoch: #26292e;
    --flaeche-matt: #191b1e;
    --flaeche-leise:#1c1f22;
    --fussleiste:   rgba(24,26,29,.94);
    --grund:        #1b1d20;
    --grund-tief:   #141517;
    --glas-fest:    #202327;
    --dunkel:       #101214;
    --tinte:        #e6e8ea;
    --tinte-matt:   #9aa0a7;
    --tinte-leise:  #82888f;
    --schein:       rgba(124,132,142,.12);
    /* Blau muss im Dunkeln HELLER werden. #2563eb auf #1e2124 ergibt
       knapp 3:1 — als Text unlesbar, als Rand kaum sichtbar. #60a5fa
       liegt bei ~6,5:1. Smaragd bleibt, es trägt auf dunklem Grund. */
    --akzent:       #60a5fa;
    --akzent-flach: rgba(96,165,250,.16);
  }
}

/* ── Themenschalter: hell / dunkel / System ──────────────────────────────
   Bis 17.08.2026 folgte das Thema NUR der Systemeinstellung. Wer im hellen
   Buero dunkel arbeiten wollte, konnte es nicht — alle drei untersuchten
   Admin-Vorlagen bieten die Wahl, und sie kostet fast nichts.

   Die Werte sind DIESELBEN wie im prefers-color-scheme-Block darueber. Sie
   stehen zweimal, und das ist hier der geringere Fehler: eine gemeinsame
   Quelle waere nur mit einer dritten Variablenebene zu haben (Token zeigt
   auf Token zeigt auf Wert), und die macht jede Farbsuche im Blatt
   unleserlich. Wer hier etwas aendert, aendert es an BEIDEN Stellen —
   deshalb dieser Hinweis und nicht nur ein Kommentarzeichen.

   `[data-thema="hell"]` braucht keinen eigenen Block: die Grundwerte in
   `:root` SIND das helle Thema. Das Attribut schaltet nur den dunklen
   Block ab, indem es ihn nicht auswaehlt. */
:root[data-thema="dunkel"] {
    color-scheme: dark;
    --tinte-rgb:    230,232,234;
    --hell-rgb:     124,132,142;
    --flaeche:      #1e2124;
    --flaeche-hoch: #26292e;
    --flaeche-matt: #191b1e;
    --flaeche-leise:#1c1f22;
    --fussleiste:   rgba(24,26,29,.94);
    --grund:        #1b1d20;
    --grund-tief:   #141517;
    --glas-fest:    #202327;
    --dunkel:       #101214;
    --tinte:        #e6e8ea;
    --tinte-matt:   #9aa0a7;
    --tinte-leise:  #82888f;
    --schein:       rgba(124,132,142,.12);
    /* Blau muss im Dunkeln HELLER werden. #2563eb auf #1e2124 ergibt
       knapp 3:1 — als Text unlesbar, als Rand kaum sichtbar. #60a5fa
       liegt bei ~6,5:1. Smaragd bleibt, es trägt auf dunklem Grund. */
    --akzent:       #60a5fa;
    --akzent-flach: rgba(96,165,250,.16);
}

html, body { height: 100%; }

body {
  font: 400 15px/1.45 -apple-system, BlinkMacSystemFont, "SF Pro Text",
        "Segoe UI", system-ui, sans-serif;
  color: var(--tinte);
  letter-spacing: var(--spur);
  background: linear-gradient(160deg, var(--grund) 0%, var(--grund-tief) 100%);
  -webkit-font-smoothing: antialiased;
  overflow: hidden;
}

/* Etwas, das durch das Glas scheinen kann. Ohne Hintergrund hinter den
   Flächen wirkt jede Milchglasfläche nur wie ein flaches Grau. */
body::before, body::after {
  content: ""; position: fixed; border-radius: 50%;
  filter: blur(90px); pointer-events: none; z-index: 0;
}
body::before {
  width: 780px; height: 620px; top: -180px; left: 4%;
  background: radial-gradient(circle, var(--schein), transparent 68%);
}
body::after {
  width: 900px; height: 700px; right: -160px; bottom: -220px;
  background: radial-gradient(circle, rgba(18,185,129,.16),
              rgba(120,130,140,.28) 55%, transparent 72%);
}

.buehne {
  position: relative; z-index: 1;
  height: 100vh;
  display: grid;
  grid-template-columns: 104px minmax(280px, 340px) 1fr;
  gap: 22px;
  padding: 22px;
}
/* Ohne Leiste heisst: es gibt gar keine — etwa vor der Anmeldung. Nicht zu
   verwechseln mit `.leiste-zu` weiter unten, wo sie da ist und eingeklappt. */
.buehne.ohne-leiste { grid-template-columns: 104px 1fr; }

/* ── Einklappbare Kontextleiste ──────────────────────────────────────────
   Die Leiste kostet 344 px. Bei fünfzig Mandanten ist das ihr Geld wert; in
   der Aufgabenansicht mit einem Mandanten stand dort „Alle 1 / Rocket Boys 1"
   auf einer Fläche, auf der daneben der Brief nicht mehr hinpasste — das
   Antwortfenster war 500 px schmal und 2790 px hoch.

   Die Breite ist eine registrierte Eigenschaft. Ohne @property ist eine
   Custom Property ein String und springt; registriert ist sie eine Länge und
   läuft. Dieselbe Überlegung wie bei flex-basis gegen flex-direction. */
@property --leiste-breite {
  syntax: "<length>"; inherits: true; initial-value: 320px;
}
@property --leiste-luecke {
  syntax: "<length>"; inherits: true; initial-value: 24px;
}

/* ── Schiene ───────────────────────────────────────────────────────── */

/* `min-height: 0` ist hier kein Feinschliff, sondern der Grund, warum die
   Schiene ueberhaupt in ihre Zeile passt: ein Rasterfeld hat von sich aus
   `min-height: auto` und waechst ueber die Zeile hinaus, statt seinen Inhalt
   rollen zu lassen. Ohne diese Zeile stand das Zahnrad 52 px unter dem
   Fensterrand — unerreichbar, obwohl die Eintraege daneben schon rollten. */
.schiene { display: flex; flex-direction: column; gap: 16px; min-height: 0; }

.schiene-block {
  flex: 1; min-height: 0;
  background: var(--dunkel);
  border-radius: 0;
  padding: 16px 0 22px;
  display: flex; flex-direction: column;
  align-items: center; justify-content: flex-start;
  gap: 10px;
  box-shadow: 0 18px 40px rgba(0,0,0,.22), inset 0 1px 0 rgba(var(--schiene-hell),.07);
}

/* Der Block „AGA TAX · KANZLEI / v0.2" stand hier. Er hat nichts getan,
   nichts erklaert und das Zahnrad nach unten geschoben. Entfernt. */

/* Die Wortmarke ist 3,1 : 1, nicht quadratisch. Eine feste Hoehe von 42 px
   haette sie auf ein Drittel der moeglichen Breite gestaucht. */
.marke {
  width: 100%; display: grid; place-items: center;
  color: #fff; margin-bottom: 8px; padding: 2px 0;
}
.trenner { width: 34px; height: 1px; background: rgba(var(--schiene-hell),.16); margin: 4px 0 10px; }

/* ── Jeder Reiter traegt sein Wort ────────────────────────────────────────
   Baki: „Bei manchen Icons hab ich das Gefuehl, dass man daraus nicht
   schliessen kann, was es ist."

   Er hat recht, und der Tooltip war die falsche Antwort: er kommt nach
   einer Sekunde, er kommt auf einem Telefon gar nicht, und Safari hat ihn
   beim Antippen als schwarzen Kasten ueber zwei Nachbarreiter gelegt.

   Die richtige Antwort ist, dass man nicht raten muss. Die Schienenspalte
   ist 92 px breit (Zeile 112) und das Symbol nutzte davon 46 — der Platz
   fuer das Wort war die ganze Zeit da. Ein Symbol mit Wort ist auch das,
   was macOS in der Seitenleiste und iOS in der Reiterleiste tun. */
.tab {
  width: 88px; min-height: 56px; padding: 8px 3px 7px;
  display: flex; flex-direction: column; align-items: center; gap: 4px;
  border-radius: 0;
  color: rgba(var(--schiene-hell),.5);
  cursor: pointer; text-decoration: none;
  transition: background .18s ease, color .18s ease;
}
.tab-wort {
  display: block; font-size: 10.5px;
  /* 1.35, nicht 1.1. Gemessen: bei 10,5 px braucht die Schrift 11,67 px
     Hoehe, ein Zeilenkasten von 1.1 gibt ihr 11,55 — und `overflow: hidden`
     schneidet die Differenz oben ab. Betroffen ist alles, was ueber die
     Versalhoehe hinausragt: aus „Übersicht" wird „Ubersicht".
     Baki hat es auf dem Telefon fotografiert und gefragt „was ist das bitte".
     Ein Zeilenkasten muss die Schrift aufnehmen, nicht die Schriftgroesse. */
  line-height: 1.35;
  letter-spacing: .01em; text-align: center;
  /* Ein Wort, das umbricht, macht die Reiter ungleich hoch — dann steht die
     Leiste schief. Lieber abschneiden; der volle Name steht im aria-label. */
  max-width: 100%; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap;
}

/* `@media (hover: hover)`: auf einem Touchgeraet bleibt :hover nach einem
   Tipp haengen, bis man woanders hintippt. Der zuletzt angetippte Reiter
   sah dadurch aus wie ein zweiter aktiver. */
@media (hover: hover) {
  .tab:hover { color: rgba(var(--schiene-hell),.85); background: rgba(var(--schiene-hell),.07); }
}
/* ── Die Glaspille ────────────────────────────────────────────────────────
   Baki: „ich finde so eine glas pille für das aktive element nice aber sie
   muss wesentlich schöner sein!!"

   Vorher: `background: rgba(var(--hell-rgb),.13)` mit eckigen Kanten. Ein Ton,
   eine Kante, fertig — deshalb sah es aus wie ein grauer Kasten. Echtes
   Glas hat DREI Dinge, die hier alle gefehlt haben:

     1. einen Verlauf statt einer Fläche (Licht fällt von oben ein),
     2. eine helle Oberkante und eine dunkle Unterkante (Materialstärke),
     3. einen weichen Schatten darunter (es liegt DARAUF, nicht darin).

   Der Reiter selbst hat jetzt gar keinen Hintergrund mehr. Die Markierung
   ist ein eigenes Element, das gleitet — siehe `pilleSetzen` in app.js. */
.tab[aria-current="page"] { color: #fff; }

.schiene .tabs .tabpille {
  position: absolute; top: 0; left: 0; z-index: 0;
  pointer-events: none;
  opacity: 0;
  /* 13 px auf 72x52: gerundet, aber noch rechteckig. Bei 19 px wurde daraus
     ein Blob — die Ecken assen die Flaeche auf. */
  border-radius: 13px;

  /* SEHR wenig Weiss. Der erste Versuch hatte .21 → .085 und machte aus dem
     schwarzen Grund ein mattes Grau: „die pille sieht scheisse aus". Auf
     Schwarz reicht ein Zehntel Weiss fuer eine sichtbare Erhebung; alles
     darueber liest sich als eigene Farbe statt als Licht. */
  background:
    linear-gradient(180deg, rgba(var(--schiene-hell),.105), rgba(var(--schiene-hell),.052));

  /* Die Lichtkante oben ist eine HALBE Zeile und nur schwach — sie soll die
     Kante zeigen, nicht selbst leuchten. */
  box-shadow:
    inset 0 .5px 0 rgba(var(--schiene-hell),.20),
    inset 0 0 0 .5px rgba(var(--schiene-hell),.075),
    inset 0 -.5px 0 rgba(0,0,0,.30),
    0 2px 8px rgba(0,0,0,.30);

  /* Kein `saturate`. Es hat den Grund mitgezogen und das Grau erzeugt. */
  -webkit-backdrop-filter: blur(10px);
          backdrop-filter: blur(10px);

  transition:
    transform .38s cubic-bezier(.22, 1, .36, 1),
    width     .38s cubic-bezier(.22, 1, .36, 1),
    height    .38s cubic-bezier(.22, 1, .36, 1),
    opacity   .20s ease;
}
.schiene .tabs .tabpille.da { opacity: 1; }

/* Ein ganz schmaler Lichtschein an der OBERKANTE — nicht ueber die halbe
   Flaeche. Der erste Versuch legte einen radialen Schein ueber 62 % der
   Hoehe; genau der machte die Pille milchig. */
.schiene .tabs .tabpille::after {
  content: ""; position: absolute; inset: 0; border-radius: inherit;
  background:
    linear-gradient(180deg, rgba(var(--schiene-hell),.07), transparent 34%);
}

/* Symbol und Wort liegen ÜBER der Pille. */
.schiene .tabs .tab { position: relative; z-index: 1; }

@media (prefers-reduced-motion: reduce) {
  .schiene .tabs .tabpille { transition: opacity .22s ease; }
}

/* Die Eintraege rollen, Marke und Zahnrad bleiben stehen.
   Ohne das fielen bei niedrigen Fenstern die letzten Eintraege, der Griff
   und das Zahnrad unten heraus — und die Schiene hat nie gerollt. */
.schiene .tabs {
  position: relative;
  flex: 1 1 auto; min-height: 0; width: 100%;
  display: flex; flex-direction: column; align-items: center; gap: 10px;
  overflow-y: auto; overflow-x: hidden;
  scrollbar-width: none;
  /* Weiche Kante statt harter Linie: man sieht, dass es weitergeht, ohne
     dass ein Strich die Leiste zerteilt. */
  -webkit-mask-image: linear-gradient(180deg, transparent 0, #000 12px,
                                      #000 calc(100% - 12px), transparent 100%);
          mask-image: linear-gradient(180deg, transparent 0, #000 12px,
                                      #000 calc(100% - 12px), transparent 100%);
}
.schiene .tabs::-webkit-scrollbar { display: none; }

/* Der Abstand vor dem Zahnrad. Er darf schrumpfen, aber nicht verschwinden —
   sonst kleben Griff und letzter Eintrag aneinander. */
.schub { flex: 0 0 10px; }

/* Niedrige Fenster: erst enger setzen, dann rollen. Ein Laptop mit
   Menueleiste, Dock und Browserleisten laesst von 900 Punkten keine 620
   fuer die Seite uebrig. Klickflaechen bleiben ueber 34 px. */
@media (max-height: 800px) {
  .buehne { padding: 14px; }
  .schiene-block { padding: 12px 0 14px; gap: 6px; }
  .schiene .tabs { gap: 6px; }
  .marke { margin-bottom: 4px; }
  .marke svg { width: 52px; height: auto; }
  .trenner { margin: 2px 0 6px; }
  /* Niedrige Fenster: enger, aber das Wort bleibt — es ist der Grund,
     warum die Leiste ueberhaupt verstanden wird. */
  .tab { width: 68px; min-height: 48px; padding: 5px 3px; gap: 2px; }
  .tab-wort { font-size: 10px; }
  .zahnrad, .schiene .griff { width: 42px; height: 42px; }
}

/* Das Zahnrad ist ein Reiter wie die anderen und traegt deshalb auch sein
   Wort. Ein einzelnes Symbol ohne Beschriftung zwischen beschrifteten
   Reitern sieht aus, als gehoerte es nicht dazu. */
.zahnrad {
  width: 88px; min-height: 56px; padding: 8px 3px 7px;
  display: flex; flex-direction: column; align-items: center; gap: 4px;
  border-radius: 0;
  color: rgba(var(--schiene-hell),.5); cursor: pointer; text-decoration: none;
  transition: background var(--zeit-klein) ease, color var(--zeit-klein) ease;
  /* MUSS hier stehen, seit aus dem <a> ein <button> wurde (Burger-Umbau
     16.08.): ein Button bringt eigenen Hintergrund, eigenen Rahmen und
     eigene Schrift mit. Ohne diese drei Zeilen stand unten in der dunklen
     Schiene ein WEISSER Kasten — Baki mit Foto: „wenn das Menü inaktiv ist
     sieht es so aus. es soll immer gleich aussehen."
     Der Fehler ist die Klasse „Element getauscht, Grundregeln nicht
     nachgezogen": vorher brauchte es sie nicht, weil ein <a> nichts
     mitbringt. */
  background: none; border: 0; font: inherit;
  -webkit-appearance: none; appearance: none;
}
@media (hover: hover) {
  .zahnrad:hover { color: rgba(var(--schiene-hell),.85); background: rgba(var(--schiene-hell),.07); }
}
/* Das Zahnrad steht AUSSERHALB der Reiterspalte, unten und fest. Die
   gleitende Pille kann ihm nicht folgen, also traegt es dasselbe Glas
   selbst — nur ohne Bewegung, weil es nichts zu bewegen gibt. Die Werte
   sind bewusst dieselben wie bei `.tabpille`: zwei Markierungen, die fast
   gleich aussehen, sind schlimmer als zwei, die verschieden aussehen. */
.zahnrad[aria-current="page"] {
  color: #fff; border-radius: 13px;
  background:
    linear-gradient(180deg, rgba(var(--schiene-hell),.105), rgba(var(--schiene-hell),.052));
  box-shadow:
    inset 0 .5px 0 rgba(var(--schiene-hell),.20),
    inset 0 0 0 .5px rgba(var(--schiene-hell),.075),
    inset 0 -.5px 0 rgba(0,0,0,.30),
    0 2px 8px rgba(0,0,0,.30);
  -webkit-backdrop-filter: blur(10px);
          backdrop-filter: blur(10px);
}

/* ── Glasflächen ───────────────────────────────────────────────────── */

.glasflaeche {
  position: relative;
  background: var(--glas);
  border: 1px solid var(--glas-rand);
  border-radius: 0;
  backdrop-filter: blur(44px) saturate(185%);
  -webkit-backdrop-filter: blur(44px) saturate(185%);
  /* Zwei Schatten mit Absicht: der weiche traegt die Flaeche, die
     Lichtkante oben laesst sie wie eine Scheibe wirken statt wie Farbe. */
  box-shadow:
    0 30px 70px rgba(0,0,0,.16),
    0 2px 8px rgba(0,0,0,.04),
    inset 0 1px 0 var(--glas-kante);
}

/* ── Seitenleiste ──────────────────────────────────────────────────── */

.leiste { padding: 20px 18px; display: flex; flex-direction: column; overflow: hidden; }

/* Die drei macOS-Fensterknoepfe standen hier und taten nichts — sie sahen
   nach Schliessen, Verkleinern, Vergroessern aus und konnten keines davon.
   Dekoration, die eine Funktion vortaeuscht, ist schlimmer als gar keine. */

.konto { display: flex; align-items: center; gap: 12px; margin-bottom: 26px; }
.konto .bild {
  width: 46px; height: 46px; border-radius: 50%;
  background: linear-gradient(150deg, #3a3d41, #17181a);
  color: #fff; display: grid; place-items: center;
  font-size: 15px; font-weight: 500;
  box-shadow: 0 6px 18px rgba(0,0,0,.26), 0 0 0 3px rgba(var(--hell-rgb),.5);
}
.konto .name { font-size: 16px; font-weight: 500; display: flex; align-items: center; gap: 6px; }
.konto .zeile2 { font-size: 12.5px; color: var(--tinte-matt); }

.rubrik {
  font-size: 13px; color: var(--tinte-leise);
  margin: 0 0 10px 14px; letter-spacing: .01em;
}

.gruppe { margin-bottom: 26px; }
.gruppe + .gruppe { border-top: 1px solid rgba(var(--hell-rgb),.4); padding-top: 24px; }

.punkt {
  display: flex; align-items: center; gap: 12px;
  padding: 13px 15px; border-radius: 0;
  color: var(--tinte); cursor: pointer; text-decoration: none;
  transition: background .16s ease, box-shadow .16s ease;
}
/* Nur was anklickbar ist, reagiert auf den Zeiger. Ein Punkt ohne `wahl`
   ist eine Anzeige, kein Knopf — er darf sich nicht wie einer anfuehlen. */
.punkt[data-wahl] { cursor: pointer; }
.punkt[data-wahl]:hover { background: rgba(var(--hell-rgb),.32); }
.punkt[data-wahl]:focus-visible { outline: 2px solid var(--akzent);
                                  outline-offset: 1px; }
.punkt[aria-current="true"] {
  background: rgba(var(--hell-rgb),.62);
  box-shadow: 0 3px 14px rgba(0,0,0,.07), inset 0 1px 0 rgba(var(--hell-rgb),.9);
}
.punkt svg { color: var(--tinte-matt); flex: none; }
/* Eine Zeile, sauber gekuerzt. „Personenbezug — nicht an das Modell gege"
   ueber zwei Zeilen ist kein Umbruch, das ist ein Abbruch. */
.punkt .text { flex: 1; min-width: 0; font-size: 15px;
               display: flex; flex-direction: column; gap: 1px; }
.punkt .text > * { white-space: nowrap; overflow: hidden;
                   text-overflow: ellipsis; display: block; }
.punkt .text small { font-size: 12.5px; color: var(--tinte-leise); }
.punkt .zahl { font-size: 13px; color: var(--tinte-leise); font-variant-numeric: tabular-nums; }
.punkt .zahl.warn { color: var(--akzent); font-weight: 500; }

.suche {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 14px; border-radius: 0;
  background: rgba(var(--hell-rgb),.34);
  border: 1px solid rgba(var(--hell-rgb),.55);
  color: var(--tinte-leise); font-size: 14.5px;
}

.baum {
  margin-top: 12px; flex: 1; min-height: 0; overflow-y: auto;
  scrollbar-width: none;
  -webkit-mask-image: linear-gradient(180deg, #000 88%, transparent 100%);
          mask-image: linear-gradient(180deg, #000 88%, transparent 100%);
}
.baum::-webkit-scrollbar { display: none; }
.baum .punkt { padding: 7px 12px; }
.baum .stufe1 { padding-left: 30px; }
.baum .stufe2 { padding-left: 48px; }

/* ── Hauptfläche ───────────────────────────────────────────────────── */

.haupt { padding: 32px 36px; overflow: hidden; display: flex; flex-direction: column; }

/* Schriftgroessen eine Stufe zurueck. 46 px Ueberschrift und 70 px Zahl
   sahen auf dem Entwurfsbild gut aus, weil dort kaum Inhalt stand. Mit
   echten Tabellen darunter frisst das die halbe Hoehe, und die Zahl ist
   nicht besser lesbar — nur groesser. */
h1 { font-size: 34px; font-weight: 450; letter-spacing: -.022em; line-height: 1.06; }
h2 { font-size: 21px; font-weight: 500; letter-spacing: -.015em; margin-top: 28px; }
h3 { font-size: 18.5px; font-weight: 500; letter-spacing: -.01em; }
.unterzeile { color: var(--tinte-matt); margin-top: 6px; font-size: 14.5px; }

.kopfreihe { display: flex; align-items: flex-start; justify-content: space-between; gap: 24px; }

/* ── Warum die Kachelreihe auf JEDER Breite rollen muss ───────────────────
   Baki am 14.08.2026 zum Kontoauszug: „rechts ist es abgeschnitten oben."

   `#kopfrechts` ist ein Flex-Kind und waechst per Vorgabe auf seinen Inhalt
   (`min-width: auto`). Der Kontoauszug haengt bis zu SECHS Kacheln hinein —
   Alle Buchungen, Mit Beleg, Beleg fehlt, Ohne Belegpflicht, Eingaenge,
   Vorschlag pruefen. Bei 104 px Mindestbreite plus Polster und Abstand sind
   das gut 750 px, die nicht schrumpfen duerfen. Sobald das Fenster schmaler
   ist als Titel plus diese Reihe, laeuft die letzte Kachel aus dem Kopf
   heraus und wird abgeschnitten.

   Die Reparatur stand schon im Stylesheet — aber erst unterhalb von 900 px.
   Das Problem faengt aber nicht bei 900 px an, sondern sobald der Inhalt
   nicht mehr passt: bei geoeffneter Seitenschiene und einem 1280-px-Fenster
   auch dort. Deshalb gilt sie ab hier immer; die Fassung im Telefonblock
   setzt darauf nur noch die Beruehrungsgroessen. */
.kopfreihe > #kopfrechts, #kopfrechts { min-width: 0; max-width: 100%; }

/* `#kopfrechts` hatte keine Anzeigeregel und war damit ein Block. Solange nur
   EIN Ding darin stand, fiel das nicht auf. Sobald zwei darin stehen — die
   Kachelreihe und der Knopf „Belege hochladen" —, faellt der zweite in die
   naechste Zeile und klebt am linken Rand, mitten in der Luft unter der
   ersten Kachel. Baki: „die position vom beleg hochladen button ist eine
   katastrophe."

   Als Flex-Reihe mit `flex-end` steht der Knopf rechts neben den Kacheln;
   wird es eng, rutscht er unter sie und bleibt dabei rechtsbuendig — der
   Umbruch sieht dann nach Absicht aus und nicht nach Unfall. */
#kopfrechts {
  display: flex; align-items: center; justify-content: flex-end;
  flex-wrap: wrap; gap: 10px 14px;
}
.lagechips {
  min-width: 0; max-width: 100%; flex-wrap: nowrap;
  overflow-x: auto; -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}
.lagechips::-webkit-scrollbar { display: none; }
/* Der rechte Rand wird weich, statt hart abzuschneiden — aber NUR, wenn
   wirklich etwas hinausragt. Eine harte Kante sieht aus wie ein Fehler; eine
   weiche Kante ohne Ueberlauf sieht aus wie ein zweiter Fehler. Ob es rollt,
   weiss allein die Messung im Browser: `kopfLage` setzt die Klasse. */
.lagechips.rollt {
  -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 24px), transparent);
          mask-image: linear-gradient(to right, #000 calc(100% - 24px), transparent);
}
.lagechip { flex: none; }

.kacheln {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: 16px; margin: 22px 0 8px;
}

.kachel {
  background: rgba(var(--hell-rgb),.3);
  border: 1px solid rgba(var(--hell-rgb),.45);
  border-radius: 0; padding: 18px 22px 17px;
  box-shadow: inset 0 1px 0 rgba(var(--hell-rgb),.7);
}
.kachel .titel { font-size: 15px; color: var(--tinte-matt); }
.kachel .wert {
  font-size: 46px; font-weight: 280; letter-spacing: -.045em; line-height: 1.02;
  margin-top: 10px; font-variant-numeric: tabular-nums;
  display: flex; align-items: baseline; gap: 14px;
}
.kachel .einheit { font-size: 19px; color: var(--tinte-matt); font-weight: 400; }
.kachel.schmal .wert { font-size: 34px; }
.kachel .titel { letter-spacing: .005em; }

.plakette {
  font-size: 13px; font-weight: 500; line-height: 1.6;
  color: var(--akzent); background: var(--akzent-flach);
  padding: 3px 11px; border-radius: 0; align-self: center;
  white-space: nowrap; letter-spacing: .02em;
}
.plakette.still  { color: var(--tinte-matt); background: rgba(var(--hell-rgb),.5); }
.plakette.warn   { color: var(--warn);  background: var(--warn-flach); }
.plakette.alarm  { color: var(--alarm); background: rgba(208,88,76,.14); }

.knopf {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 12px 20px; border-radius: 0;
  border: 1px solid rgba(var(--tinte-rgb),.16);
  color: var(--tinte); font-size: 15px; cursor: pointer;
  background: none; font-family: inherit; text-decoration: none;
  transition: background .16s ease, border-color .16s ease,
              transform var(--zeit-druck) var(--kurve-raus);
}
/* Rückmeldung im Moment des Drückens.
   Sie fehlte an jedem Knopf der Anwendung — nur der Griff der Seitenleiste
   hatte sie. Ein Knopf, der auf das Drücken selbst nicht reagiert, wirkt
   tot, auch wenn er beim Loslassen das Richtige tut. `scale` nimmt
   Beschriftung und Symbol mit; genau das lässt es körperlich wirken. */
.knopf:active:not(:disabled) { transform: scale(.97); }
/* Überfahren nur mit echtem Zeiger — auf einem Berührungsbildschirm bleibt
   der Hover-Zustand nach dem Tippen kleben. */
@media (hover: hover) and (pointer: fine) {
  .knopf:hover { background: rgba(var(--hell-rgb),.4); border-color: rgba(var(--tinte-rgb),.35); }
}
.knopf.voll {
  border: none; background: var(--dunkel); color: #fff;
  box-shadow: 0 12px 28px rgba(0,0,0,.22), inset 0 1px 0 rgba(var(--hell-rgb),.12);
}
@media (hover: hover) and (pointer: fine) {
  .knopf.voll:hover { background: #2b2d30; }
}
/* Die Varianten „klein" und „leise" wurden im Code benutzt, aber nie
   gestaltet — jeder Zeilenknopf war deshalb so gross wie ein Hauptknopf. */
.knopf.klein { padding: 8px 14px; font-size: 13.5px; border-radius: 0; }
.knopf.leise { border-color: rgba(var(--tinte-rgb),.1); color: var(--tinte-matt); }
@media (hover: hover) and (pointer: fine) {
  .knopf.leise:hover { color: var(--tinte); }
}
.knopf:disabled { opacity: .5; cursor: default; }
.knopf:disabled:hover { background: none; border-color: rgba(var(--tinte-rgb),.16); }

.reiter { display: flex; gap: 26px; margin-top: 16px; border-bottom: 1px solid rgba(var(--hell-rgb),.5); }
.reiter span { padding-bottom: 10px; color: var(--tinte-matt); cursor: pointer; font-size: 15.5px; }
.reiter span[aria-current="true"] { color: var(--tinte); box-shadow: inset 0 -2px 0 var(--tinte); }

/* ── Tabellen ──────────────────────────────────────────────────────── */

.tabelle { margin-top: 16px; overflow: auto; }
/* `separate` statt `collapse` — und das ist kein Geschmack.
   Mit `border-collapse: collapse` gehoert der Zellhintergrund zur
   Tabellenebene, nicht zur Zelle. Eine klebende Kopfzeile bekommt dadurch
   ihren Hintergrund UNTER die wegrollenden Zeilen gemalt, egal welchen
   `z-index` sie hat. Gemessen: Kopfzeile bei y 194–237, deckend, z-index 2 —
   und trotzdem lief eine Zeile von 166 bis 241 sichtbar darueber.
   Mit `separate` und `border-spacing: 0` malt jede Zelle ihren eigenen
   Hintergrund, die Linien stossen wie vorher aneinander, und die Kopfzeile
   deckt. */
table {
  width: 100%; font-size: 14.5px;
  border-collapse: separate; border-spacing: 0;
}
/* Die klebende Kopfzeile muss DECKEN.
   Mit 34 % Weiss schlug die darunter wegrollende Zeile durch: Spaltenname
   und Buchungstext standen uebereinander und beides war unlesbar. Genau der
   Fall „never stack a light translucent surface on another" — nur hier
   besonders schlimm, weil die untere Schicht sich bewegt.
   Das Milchglas allein reicht nicht: eine Vorfahrenflaeche mit `mask-image`
   schneidet `backdrop-filter` von dem ab, was es unscharf zeichnen soll. */
th {
  position: sticky; top: 0; z-index: 2;
  /* DECKEND, nicht fast deckend. Mit 94 % geisterte die wegrollende Zeile
     immer noch durch die Kopfzeile. Sechs Prozent Restdurchsicht fallen bei
     ruhendem Hintergrund nicht auf — unter einer Kopfzeile, unter der sich
     ständig etwas bewegt, sieht das Auge jede Bewegung. Ein `backdrop-filter`
     erübrigt sich damit; er würde nur Rechenzeit kosten. */
  background: var(--flaeche-matt);
  text-align: left; font-weight: 400; color: var(--tinte-matt);
  padding: 12px 14px; font-size: 13px;
  border-bottom: 1px solid rgba(0,0,0,.08); white-space: nowrap;
}
td { padding: 16px 14px; border-bottom: 1px solid rgba(var(--hell-rgb),.3); vertical-align: middle; }
tr:hover td { background: rgba(var(--hell-rgb),.28); }
td.zahl, th.zahl { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.konto-nr { font-variant-numeric: tabular-nums; }

.marke-status { display: inline-flex; align-items: center; gap: 7px; font-size: 13px; color: var(--tinte-matt); white-space: nowrap; }
.marke-status::before { content: ""; width: 7px; height: 7px; border-radius: 50%; background: var(--tinte-leise); }
.marke-status.ok::before    { background: var(--akzent); }
.marke-status.ok            { color: var(--akzent); }
.marke-status.offen::before { background: var(--warn); }
.marke-status.offen         { color: var(--warn); }
.marke-status.rot::before   { background: var(--alarm); }
.marke-status.rot           { color: var(--alarm); }

/* Fortschrittsbalken für den Automatisierungsgrad je Mandant */
.balken { width: 116px; height: 6px; border-radius: 0; background: rgba(var(--tinte-rgb),.12); overflow: hidden; }
.balken i { display: block; height: 100%; border-radius: 0; background: var(--akzent); }
.balken.mittel i { background: var(--warn); }
.balken.schlecht i { background: var(--alarm); }

.hinweisleiste { margin-top: auto; padding-top: 14px; font-size: 12.5px; color: var(--tinte-leise); }

/* ── Aufgabenliste (Mandanten-Dashboard) ───────────────────────────── */

.aufgaben { display: flex; flex-direction: column; gap: 10px; margin-top: 18px; overflow-y: auto; }
.aufgabe {
  display: flex; align-items: center; gap: 16px;
  padding: 15px 18px; border-radius: 0;
  background: rgba(var(--hell-rgb),.46);
  border: 1px solid rgba(var(--hell-rgb),.6);
}
.aufgabe .datum { font-size: 13px; color: var(--tinte-leise); width: 62px; flex: none; font-variant-numeric: tabular-nums; }
.aufgabe .wer { flex: 1; font-size: 15.5px; }
.aufgabe .wer small { display: block; color: var(--tinte-matt); font-size: 13px; margin-top: 2px; }
.aufgabe .summe { font-variant-numeric: tabular-nums; font-size: 16px; white-space: nowrap; }

/* ── Anmeldung ─────────────────────────────────────────────────────── */

.anmelde-buehne {
  position: relative; z-index: 1;
  height: 100vh; display: grid; place-items: center; padding: 24px;
}

.anmelde-karte {
  width: min(460px, 100%);
  padding: 40px 40px 34px;
  border-radius: 0;
}

/* Keine dunkle Plakette mehr um die Marke.
   Dort sass ein 56x56-Quadrat mit weissem Zeichen darin — passend fuer ein
   abstraktes Symbol, unpassend fuer eine Wortmarke im Verhaeltnis 3,1 : 1.
   Das Logo ist von Haus aus dunkel auf hell; auf der hellen Glaskarte steht
   es deshalb frei und in Tintenfarbe, so wie es gedacht ist. */
.anmelde-marke {
  /* Linksbuendig, nicht mittig. Die alte Plakette war ein Quadrat und stand
     links; die breite Wortmarke stand nach dem Wechsel zentriert, waehrend
     „Anmelden" und die Unterzeile darunter links begannen. Zwei Kanten, wo
     eine hingehoert. */
  color: var(--tinte); display: grid; justify-items: start;
  margin-bottom: 22px;
}

.wahl { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; padding: 5px;
        background: rgba(var(--hell-rgb),.36); border: 1px solid rgba(var(--hell-rgb),.55);
        border-radius: 0; margin: 22px 0 24px; }
.wahl button {
  border: none; background: none; font: inherit; cursor: pointer;
  padding: 11px 8px; border-radius: 0; color: var(--tinte-matt);
  transition: background .16s ease, color .16s ease;
}
.wahl button[aria-pressed="true"] {
  background: rgba(var(--hell-rgb),.9); color: var(--tinte); font-weight: 500;
  box-shadow: 0 3px 10px rgba(0,0,0,.08);
}

.feld { margin-bottom: 14px; }
.feld label { display: block; font-size: 13px; color: var(--tinte-matt); margin: 0 0 6px 4px; }
.feld input {
  width: 100%; font: inherit; color: var(--tinte);
  padding: 13px 16px; border-radius: 0;
  background: rgba(var(--hell-rgb),.55);
  border: 1px solid rgba(var(--hell-rgb),.7);
  outline: none;
  transition: border-color .16s ease, background .16s ease;
}
.feld input:focus { border-color: rgba(18,185,129,.55); background: rgba(var(--hell-rgb),.78); }
.feld input::placeholder { color: var(--tinte-leise); }

.anmelde-karte .knopf.voll { width: 100%; justify-content: center; margin-top: 8px; padding: 14px; }

.nebenzeile { margin-top: 18px; font-size: 13.5px; color: var(--tinte-matt); text-align: center; }
.nebenzeile a { color: var(--tinte); text-decoration: none; border-bottom: 1px solid rgba(var(--tinte-rgb),.25); }

.erklaerung {
  margin-top: 26px; padding-top: 18px;
  border-top: 1px solid rgba(var(--hell-rgb),.55);
  font-size: 13px; color: var(--tinte-matt); line-height: 1.55;
}


/* ── Nachbesserungen aus dem ersten Durchsehen ─────────────────────── */

/* Rechte Spalten liefen unten aus dem Bild. Sie bekommen eigenen Lauf
   und blenden aus, statt abzuschneiden. */
.spalte.seitenspalte {
  overflow-y: auto;
  scrollbar-width: none;
  padding-right: 2px;
  -webkit-mask-image: linear-gradient(180deg, #000 92%, transparent 100%);
          mask-image: linear-gradient(180deg, #000 92%, transparent 100%);
}
.spalte.seitenspalte::-webkit-scrollbar { display: none; }

/* Aufgabenliste laeuft, die Ablagezone bleibt darunter stehen.
   Der Verlauf am unteren Rand zeigt, dass es weitergeht — ein harter
   Schnitt sieht aus wie ein Fehler. */
.aufgaben {
  flex: 1; min-height: 0; padding-right: 2px; scrollbar-width: none;
  -webkit-mask-image: linear-gradient(180deg, #000 90%, transparent 100%);
          mask-image: linear-gradient(180deg, #000 90%, transparent 100%);
}
.aufgaben::-webkit-scrollbar { display: none; }

/* Fristen: die Restzeit darf nie umbrechen. */
.frist { gap: 14px; }
.frist > span:first-child { min-width: 0; }
.frist .rest { white-space: nowrap; flex: none; }

/* Tabellen in Spalten brauchen eigenen Lauf. */
.tabelle.laeuft {
  flex: 1 1 0; min-height: 120px; scrollbar-width: none;
  -webkit-mask-image: linear-gradient(180deg, #000 94%, transparent 100%);
          mask-image: linear-gradient(180deg, #000 94%, transparent 100%);
}
.tabelle.laeuft::-webkit-scrollbar { display: none; }

/* ── Dieselbe Dichte für eine Tabelle ────────────────────────────────────
   Die Buchungssätze bleiben eine Tabelle: die Auswahlkästchen, die Werkbank
   darüber und der Agenda-Export hängen daran, und zehn Spalten ergeben
   keine Zeile mit einem Hauptfeld. Verdichtet wird trotzdem nach derselben
   Rechnung wie im Kontoauszug.

   Gemessen vorher: 54 px, bei umbrechendem Buchungstext 75 px — auf einem
   Laptop neun Sätze. `padding: 16px` oben und unten ist mehr Luft als
   Zeile; mit 0 und einer festen Höhe von 40 px steht die Schrift genauso
   mittig und es passen sechzehn.

   Und derselbe zweite Punkt: keine durchscheinenden Flächen übereinander,
   sondern eine deckende Fläche mit 1-px-Linien. Die Maske am unteren Rand
   entfällt dabei — sie verwischt eine Kante, die es jetzt gibt. */
.tabelle.dicht {
  background: var(--flaeche); border: 1px solid rgba(var(--tinte-rgb),.13);
  -webkit-mask-image: none; mask-image: none;
  scrollbar-width: thin;
}
.tabelle.dicht::-webkit-scrollbar { display: block; width: 8px; }
.tabelle.dicht::-webkit-scrollbar-thumb { background: rgba(0,0,0,.18); }
.tabelle.dicht table { font-size: 13.5px; }
.tabelle.dicht th {
  padding: 0 14px; height: 34px; font-size: 12px;
  border-bottom: 1px solid rgba(var(--tinte-rgb),.13);
}
.tabelle.dicht td {
  padding: 0 14px; height: 40px;
  border-bottom: 1px solid rgba(var(--tinte-rgb),.07);
  white-space: nowrap;
}
.tabelle.dicht tr:last-child td { border-bottom: none; }
.tabelle.dicht tr:hover td { background: rgba(var(--tinte-rgb),.045); }
/* Der Buchungstext ist die einzige Spalte, die wachsen will — und die
   einzige, die abgeschnitten werden darf. `max-width` in Pixeln, weil
   `text-overflow` in einer Tabellenzelle sonst nicht greift. */
/* 210 px, und die Grenze steht zweimal da — an der Zelle und am Kasten
   darin.

   Gemessen: ohne Grenze wurde die Tabelle 936 px breit und ragte 31 px aus
   ihren 906 px heraus; dann schiebt man sie seitlich, und die
   Betragsspalte, auf die es ankommt, steht draußen. Nur am Kasten (300 px)
   waren es 59 px zu viel. `max-width` an der Zelle bestimmt die
   Spaltenbreite, `max-width` am Kasten schneidet den Text wirklich ab —
   eins ohne das andere reicht nicht. */
.tabelle.dicht td.text { max-width: 210px; }
.tabelle.dicht td.text > div {
  max-width: 210px; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap;
}

/* Ablageflächen färben sich, wenn eine Datei darüber schwebt. Ohne diese
   Rückmeldung weiß niemand, ob die Fläche überhaupt etwas annimmt. */
.ablage.bereit, .aufgabe.bereit {
  border-color: var(--akzent);
  background: rgba(46,160,110,.12);
}
.aufgabe.bereit { outline: 1.5px dashed var(--akzent); outline-offset: -3px; }

/* Ladezustand.
   Vorher standen feste Demozahlen im HTML — 7 Belege, 38.412 Euro, „Stand
   Juni". Der Browser zeigte die zuerst, dann überschrieb sie das Skript.
   Für einen Sekundenbruchteil standen also erfundene Zahlen im Bild, auf
   einem Dashboard, dessen ganzer Anspruch echte Zahlen sind.
   Jetzt steht dort ein Platzhalter, der ruhig pulsiert, bis die echten
   Werte da sind. */
.platzhalter {
  display: inline-block; min-width: 2.2ch;
  color: rgba(var(--tinte-rgb),.22);
  animation: atmen 1.4s ease-in-out infinite;
}
@keyframes atmen {
  0%, 100% { opacity: .35; }
  50%      { opacity: .75; }
}
/* `pulsieren` weiter unten war bei „weniger Bewegung" abgeschaltet, `atmen`
   nicht — zwei gleichartige Wartezeichen mit zwei Verhaltensweisen. Eine
   Dauerschleife im Blickfeld ist genau das, was diese Einstellung meint. Der
   Platzhalter bleibt sichtbar, er hört nur auf zu atmen. */
@media (prefers-reduced-motion: reduce) {
  .platzhalter { animation: none; opacity: .5; }
}
.tabelle tbody:empty::after,
.aufgaben:empty::after {
  content: "wird geladen …";
  display: block; padding: 30px 12px; text-align: center;
  color: var(--tinte-leise); font-size: 14px;
}

/* Inhalt, der nicht mehr passt, wird gescrollt — nicht abgeschnitten.
   Vorher endete die Aufgabenliste mitten in einer Zeile und die letzte
   Seitenkarte war halb weg. Abgeschnittener Inhalt sieht aus wie ein
   Darstellungsfehler, und genau das ist er auch. */
.aufgaben {
  flex: 1; min-height: 0; overflow-y: auto; padding-right: 4px;
  scrollbar-width: thin; scrollbar-color: rgba(var(--tinte-rgb),.2) transparent;
}
.aufgaben::-webkit-scrollbar { width: 6px; }
.aufgaben::-webkit-scrollbar-thumb {
  background: rgba(var(--tinte-rgb),.18); border-radius: 99px;
}
.mandant-raster > aside,
.aus-raster > aside {
  overflow-y: auto; min-height: 0; padding-right: 4px;
  scrollbar-width: thin; scrollbar-color: rgba(var(--tinte-rgb),.2) transparent;
}
.mandant-raster > aside::-webkit-scrollbar,
.aus-raster > aside::-webkit-scrollbar { width: 6px; }
.mandant-raster > aside::-webkit-scrollbar-thumb,
.aus-raster > aside::-webkit-scrollbar-thumb {
  background: rgba(var(--tinte-rgb),.18); border-radius: 99px;
}
/* Die Ablage bleibt unten stehen, statt mitzuscrollen. */
.ablage { flex: none; }

/* ── Dreispaltig ─────────────────────────────────────────────────────────
   Die Vorlage hat drei Ebenen: schmale dunkle Schiene, eigene
   Navigationsspalte, Inhalt. Meine Fassung hatte nur zwei — und genau das
   war der Grund, warum sie flacher wirkte. Es waren nie die Abstände. */
.buehne {
  grid-template-columns: 104px var(--leiste-breite) 1fr;
  /* Die Lücke gehört der Leiste, nicht dem Raster — sonst bliebe beim
     Einklappen eine 24px breite Leerstelle stehen, wo nichts mehr ist. */
  column-gap: 0; row-gap: 24px;
  transition: --leiste-breite var(--zeit-schub) var(--kurve-schub),
              --leiste-luecke var(--zeit-schub) var(--kurve-schub);
}
.buehne > .schiene { margin-right: 24px; }
.buehne > .leiste  { margin-right: var(--leiste-luecke); }
.buehne.ohne-leiste { column-gap: 24px; }
.buehne.ohne-leiste > .schiene { margin-right: 0; }

.buehne.leiste-zu { --leiste-breite: 0px; --leiste-luecke: 0px; }
/* Der Inhalt verschwindet schneller als die Fläche schmal wird, sonst sieht
   man Text an der Kante zerquetschen. */
/* `visibility` erst NACH der Fahrt, sonst verschwände der Inhalt sofort und
   die Fläche schöbe sich leer zu. Mit 0s Dauer und Verzögerung schaltet sie
   hart um, sobald die Bewegung durch ist — und dann ist die Leiste wirklich
   weg: nicht anklickbar, nicht vorlesbar, nicht mehr Teil der Messung.
   Ohne das galt sie als sichtbar und meldete 20 abgeschnittene Texte. */
.buehne.leiste-zu > .leiste {
  opacity: 0; pointer-events: none; visibility: hidden;
  transition: opacity var(--zeit-klein) ease,
              visibility 0s linear var(--zeit-schub);
}
.buehne > .leiste {
  opacity: 1; visibility: visible;
  transition: opacity var(--zeit-mittel) ease .1s, visibility 0s;
}

/* Hat die Ansicht keinen Kontext, schrumpft die Fläche auf ihren Inhalt.
   Übersicht und Buchungen filtern oben in der Ansicht; ihre mittlere Spalte
   ist leer. Über die volle Höhe gezogen ist das eine graue Wand — als kurze
   Karte mit dem Mandanten darin ist es das, was es ist.

   Die Spaltenbreite bleibt: sie am Inhalt auszurichten hiesse, dass die
   Tabelle rechts bei jedem Reiterwechsel eine andere Breite hätte, und
   springende Spalten sind schlimmer als ruhige Leere. */
.buehne > .leiste:has(> .leiste-inhalt:empty) { align-self: start; }

/* Der Griff sitzt in der Schiene, wo er in jeder Ansicht am selben Platz
   steht. Ein Knopf, der je nach Seite woanders liegt, wird nicht gefunden. */
.schiene .griff {
  width: 46px; height: 46px; margin: 0 auto; border: none; padding: 0;
  background: none; cursor: pointer; border-radius: 0;
  /* NICHT `color: inherit`: die Schiene ist in BEIDEN Themen dunkel, die
     geerbte Seitentinte ist im hellen Thema aber fast schwarz — der Griff
     zeichnete schwarz auf schwarz und war ohne Ueberfahren unsichtbar
     (Bakis Foto vom 16.08.). Er traegt dieselbe Ruhe- und Hover-Farbe wie
     Reiter und Zahnrad — ein Bedienelement der Schiene, keine Ausnahme. */
  color: rgba(var(--schiene-hell),.5);
  display: grid; place-items: center;
  transition: color var(--zeit-druck) ease,
              background var(--zeit-druck) ease,
              transform var(--zeit-druck) var(--kurve-raus);
}
/* Überfahren nur mit echtem Zeiger: auf einem Berührungsbildschirm löst ein
   Tippen ein Hover aus, das danach kleben bleibt. */
@media (hover: hover) and (pointer: fine) {
  .schiene .griff:hover {
    color: rgba(var(--schiene-hell),.85);
    background: rgba(var(--schiene-hell),.07);
  }
}
/* Rückmeldung im Moment des Drückens, nicht erst beim Loslassen. */
.schiene .griff:active { transform: scale(.97); }
.schiene .griff svg { transition: transform var(--zeit-schub) var(--kurve-schub); }
.buehne.leiste-zu .schiene .griff svg { transform: rotate(180deg); }

/* Weniger Bewegung heißt nicht keine Rückmeldung. Die Leiste klappt weiter
   zu — nur ohne die Fahrt über den halben Bildschirm. Das Ein- und
   Ausblenden bleibt, weil es erklärt, was passiert ist. */
@media (prefers-reduced-motion: reduce) {
  .buehne { transition: none; }
  .schiene .griff svg { transition: none; }
}

/* Vorher schob sich die Spalte mit `margin-right: -26px` unter die
   Hauptflaeche. Gedacht war Tiefe; sichtbar war, dass beide Flaechen
   zusammenkleben — zwei Glasplatten ohne Fuge sehen aus wie eine
   missratene. Jetzt stehen sie mit Abstand nebeneinander, und die Tiefe
   kommt aus Schatten und Kantenlicht, wo sie hingehoert. */
.buehne:not(.ohne-leiste) .leiste { z-index: 2; }
.buehne:not(.ohne-leiste) .haupt  { z-index: 1; }

.leiste { padding: 22px 14px 18px; }
.leiste .konto { padding: 0 8px; }
.leiste-inhalt {
  flex: 1; min-height: 0; overflow-y: auto; padding-right: 2px;
  scrollbar-width: none;
  -webkit-mask-image: linear-gradient(180deg, #000 92%, transparent 100%);
          mask-image: linear-gradient(180deg, #000 92%, transparent 100%);
}
.leiste-inhalt::-webkit-scrollbar { display: none; }

/* Zähler rechtsbündig, wie in der Vorlage. */
.punkt .zahl { margin-left: auto; min-width: 2ch; text-align: right; }

/* Eng: die Leiste ist nicht weg, sondern zu — sonst landete die Hauptfläche
   in der leeren zweiten Spalte statt in der dritten. */
/* Eng: die Leiste steht nicht mehr NEBEN dem Inhalt, sondern DARÜBER.
   ────────────────────────────────────────────────────────────────────────
   Hier stand bis zum 07.08. `display: none` — die Leiste war unter 1180 px
   schlicht weg. Das ging, solange sie nur Filter trug: schade, aber
   verschmerzbar.

   Seit der Mandantenwechsel oben in ihr sitzt, ist es ein Fehler. Baki:
   „Ein Fenster, in dem man den Mandanten wechseln kann, muss IMMER
   erreichbar sein." Auf einem Tablet war er es nicht — und der Monatsfilter
   des Kontoauszugs, der ebenfalls dort steht, auch nicht. Weggeblendet ist
   nicht dasselbe wie umgebrochen.

   Jetzt: zwei Spalten statt drei, und die Leiste legt sich als volle Breite
   über den Inhalt. Sie kostet damit Höhe statt Breite — und Höhe hat man,
   weil die Seite ohnehin rollt. */
@media (max-width: 1180px) {
  .buehne {
    grid-template-columns: 96px minmax(0, 1fr);
    --leiste-luecke: 0px;
    align-content: start;
  }
  .buehne > .schiene { grid-column: 1; grid-row: 1 / span 2; }
  .buehne > .leiste {
    grid-column: 2; grid-row: 1;
    width: auto; max-width: none; margin: 0 0 16px;
    align-self: start;
  }
  .buehne > main { grid-column: 2; grid-row: 2; }
  /* Eingeklappt gibt es hier nicht mehr: es gibt keine zweite Spalte, die
     dadurch breiter würde. Der Griff wäre also ein Knopf ohne Wirkung. */
  .buehne.leiste-zu > .leiste {
    opacity: 1; visibility: visible; pointer-events: auto;
  }
  .schiene .griff { display: none; }

  /* Die Kontextpunkte nebeneinander statt untereinander — sechs Monate als
     Spalte schöben den Inhalt nach unten aus dem Bild. */
  .leiste-inhalt {
    /* `align-items: center`, nicht die Vorgabe `stretch`. Ohne das haengt
       jede Gruppe an der Hoehe der hoechsten, und ihre Beschriftung sitzt
       dort, wo ihre eigene Mitte liegt — nicht auf einer gemeinsamen Linie.
       Baki hat es fotografiert: „die zwei angezeigten Punkte, die absolut
       nicht auf selber Hoehe liegen." */
    display: flex; flex-direction: row; flex-wrap: wrap; gap: 8px;
    align-items: center;
  }
  .leiste-inhalt .gruppe {
    /* `nowrap`: eine Gruppe, die intern umbricht, wird zwei Zeilen hoch und
       schiebt die Nachbarn optisch auseinander. Die ganze Reihe rollt
       ohnehin waagerecht.

       FESTE HOEHE, und zwar dieselbe wie die Kacheln. Gemessen am 15.08.:
       die Gruppe „Zugang" war 69 px hoch, obwohl ihr oberstes Kind erst bei
       167 begann — 25 px leerer Raum oben. Die Gruppe wurde gedehnt, nicht
       ihre Kacheln, und damit sassen die Kacheln zweier Gruppen auf
       verschiedenen Hoehen. Baki: „zugang ist auch verschoben."
       Wer die Hoehe festlegt, braucht kein Ausrichten mehr. */
    display: flex; flex-direction: row; flex-wrap: nowrap;
    gap: 8px; align-items: center;
    height: 44px; flex: none; align-self: center;
  }
  .leiste-inhalt .rubrik { margin: 0; padding: 0 4px 0 0; white-space: nowrap; }
  .leiste-inhalt .punkt {
    flex: none; white-space: nowrap;
    border: 1px solid rgba(var(--tinte-rgb),.14);
  }
  .leiste-inhalt:empty { display: none; }
  .leiste .konto { margin-bottom: 10px; }
  .leiste-mandant { padding: 0 0 10px; margin-bottom: 10px; }
  .leiste-mandant .wahlfeld { max-width: 340px; }
}

/* Rasterbereiche duerfen nicht ueber ihren Platz hinauswachsen.
   Ohne min-width:0 nimmt ein 1fr-Bereich die BREITE SEINES INHALTS als
   Untergrenze — eine breite Tabelle schiebt dann die Nachbarspalte aus dem
   Bild. Genau das hat nach dem Einbau der dritten Spalte die Karten rechts
   abgeschnitten. Der Wert ist unscheinbar und der haeufigste Grund fuer
   abgeschnittene Layouts ueberhaupt. */
/* Gilt fuer JEDES Raster, nicht fuer eine Aufzaehlung von dreien. Die erste
   Fassung nannte .mandant-raster und .aus-raster einzeln — und uebersah
   .kanzlei-raster, also ausgerechnet die Seite, auf der der Fehler sichtbar
   war. Wer Regeln aufzaehlt, vergisst eine. */
.buehne > *,
[class$="-raster"] > *,
.spalte { min-width: 0; }

/* Tabellen scrollen in sich, statt ihr Umfeld zu sprengen. */
.tabelle { max-width: 100%; overflow-x: auto; }
.tabelle table { min-width: 620px; }

/* Mandantennamen nicht ueber drei Zeilen brechen. */
.mandant-zeile { display: flex; align-items: center; gap: 10px; min-width: 0; }
.mandantname {
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* Waehrungsbetraege in Kacheln kleiner als blanke Anzahlen.
   „38.412,55 €" bei 47 px sprengt jede Kachel — eine Zahl ohne Einheit
   nicht. Die Groesse richtet sich nach dem Inhalt, nicht nach der Kachel. */
/* Waehrungsbetraege sind laenger als blanke Anzahlen — „-14.813,00 €"
   braucht bei gleicher Kachelbreite eine kleinere Schrift als „34". */
.kacheln.betraege .kachel .wert { font-size: 27px; letter-spacing: -.025em; }
/* Ein Minus muss man sehen, ohne das Zeichen zu suchen. */
.kachel .wert.minus { color: var(--warn); }

/* Gruppierte Ausgaben */
.gruppenzeile td:first-child { font-weight: 500; }
.gruppenzeile .pfeil { display: inline-block; width: 14px;
                       color: var(--tinte-leise); font-size: 11px; }
.gruppenzeile:hover td { background: rgba(var(--hell-rgb),.34); }
.postenzeile td { font-size: 13.5px; color: var(--tinte-matt);
                  padding-top: 9px; padding-bottom: 9px; }
.postenzeile .eingerueckt { padding-left: 34px; }

/* Seitenkarten in den Auswertungen kompakter — sie standen deutlich
   hoeher als die Kacheln daneben. */
.zwei-spalten .seitenkarte { padding: 16px 18px; margin-bottom: 12px; }
.zwei-spalten .seitenkarte h3 { font-size: 16px; margin-bottom: 8px; }
.zwei-spalten .messwert { padding: 6px 0; font-size: 13.5px; }
.zwei-spalten .messwert b { font-size: 14.5px; }

/* ── Einstellungen: Formular und Verbindungseinträge ──────────────────────
   Vorher standen hier drei nackte Eingabefelder nebeneinander, ohne
   Beschriftung, ohne Serverfeld. Das sah nicht nur billig aus — es hat auch
   ein Postfach ohne Server zugelassen, an dem sich nie etwas anmelden
   konnte. Beschriftete Felder in einem Raster, sichtbarer Server, ein
   Hinweis je Anbieter. */

.formular { margin-top: 18px; }

.formular .gitter {
  display: grid; gap: 14px 16px;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
}
.formular .feld { display: flex; flex-direction: column; gap: 7px; min-width: 0; }
.formular .feld.breit { grid-column: span 2; }
@media (max-width: 1180px) { .formular .feld.breit { grid-column: span 1; } }

.formular .feld > span {
  font-size: 12.5px; letter-spacing: .02em; color: var(--tinte-matt);
  padding-left: 2px;
}
.formular input, .formular select {
  width: 100%; font: inherit; font-size: 14.5px; color: var(--tinte);
  padding: 12px 14px; border-radius: 0;
  border: 1px solid rgba(var(--hell-rgb),.62);
  background: rgba(var(--hell-rgb),.52);
  box-shadow: inset 0 1px 2px rgba(var(--tinte-rgb),.05);
  transition: border-color .15s ease, background .15s ease, box-shadow .15s ease;
}
.formular input::placeholder { color: var(--tinte-leise); }
.formular input:focus, .formular select:focus {
  outline: none; border-color: rgba(var(--tinte-rgb),.4);
  background: rgba(var(--hell-rgb),.78);
  box-shadow: 0 0 0 3px rgba(var(--tinte-rgb),.07);
}
/* Ein Feld, das der Anbieter vorgibt, soll nicht wie ein leeres Eingabefeld
   aussehen — sonst tippt jemand dagegen an. */
.formular input:read-only {
  background: rgba(var(--hell-rgb),.28); color: var(--tinte-matt);
  box-shadow: none; cursor: default;
}

.formular .hinweis {
  margin-top: 12px; font-size: 13px; line-height: 1.55;
  color: var(--tinte-matt); max-width: 74ch;
}
.formular .fuss {
  display: flex; align-items: center; justify-content: space-between;
  gap: 18px; flex-wrap: wrap; margin-top: 18px;
}
.formular .fuss small { font-size: 12.5px; color: var(--tinte-leise); }

/* Ein verbundenes Postfach: Adresse, Zustand, Handlungen. */
.eintrag {
  display: grid; grid-template-columns: 1fr auto auto;
  align-items: center; gap: 16px; padding: 14px 0;
}
.eintrag + .eintrag { border-top: 1px solid rgba(var(--hell-rgb),.45); }
.eintrag .wer { min-width: 0; }
.eintrag .kopf { font-size: 15px; overflow: hidden;
                 text-overflow: ellipsis; white-space: nowrap; }
.eintrag .wer small, .eintrag .stand small {
  display: block; font-size: 12.5px; color: var(--tinte-leise);
  margin-top: 3px;
}
.eintrag .stand { text-align: right; max-width: 30ch; }
.eintrag .stand small { white-space: normal; line-height: 1.45; }
.eintrag .knoepfe { display: flex; gap: 7px; flex-wrap: wrap;
                    justify-content: flex-end; }
@media (max-width: 1080px) {
  .eintrag { grid-template-columns: 1fr; }
  .eintrag .stand, .eintrag .knoepfe { text-align: left; justify-content: flex-start; }
  .eintrag .stand { max-width: none; }
}

/* ── Sammelablage ─────────────────────────────────────────────────────────
   Ein Stapel wird nicht mit einer Zahl quittiert, sondern mit einer Liste:
   was war jede Datei, und was ist daraus geworden. Ohne diese Rückmeldung
   ist „50 abgelegt" genauso wenig wert wie das alte „wartet auf Zuordnung" —
   man weiß nicht, ob etwas passiert ist. */

/* Der einzeilige Streifen: dieselbe Fläche, dasselbe Verhalten, 60 px
   weniger Polster. Gemessen sind das anderthalb Belegzeilen mehr in der
   Liste darüber. */
.grossablage.knapp { margin-top: 12px; padding: 11px 18px; }
.grossablage.knapp b { display: inline; margin: 0 8px 0 0; }

.grossablage.laeuft {
  border-style: solid; border-color: var(--akzent);
  background: rgba(46,160,110,.07); cursor: progress;
}
.grossablage.laeuft b::after {
  content: " …"; animation: pulsieren 1.1s ease-in-out infinite;
}
@keyframes pulsieren { 50% { opacity: .35; } }

.stapelbericht {
  margin-top: 12px; max-height: 260px; overflow-y: auto;
  border-radius: 0; border: 1px solid rgba(var(--hell-rgb),.5);
  background: rgba(var(--hell-rgb),.34); padding: 6px 4px;
  scrollbar-width: thin;
}
.stapelzeile {
  padding: 7px 14px; font-size: 13px; line-height: 1.5;
  color: var(--tinte-matt); font-variant-numeric: tabular-nums;
}
.stapelzeile + .stapelzeile { border-top: 1px solid rgba(var(--hell-rgb),.4); }
.stapelzeile.gut      { color: var(--akzent); }
.stapelzeile.schlecht { color: var(--alarm); }
.stapelzeile.still    { color: var(--tinte-leise); }
@media (prefers-reduced-motion: reduce) {
  .grossablage.laeuft b::after { animation: none; }
}

/* ── Betrieb: Zusammenfassung, Auffälligkeiten, Vorschläge ────────────────
   Getrennte Karten statt eines langen Berichts. Nur so lässt sich ein
   einzelner Punkt abhaken; ein Fließtext, den man jeden Monat neu liest,
   wird nach dem zweiten Mal überblättert. */

.befundliste { display: flex; flex-direction: column; gap: 14px;
               margin-top: 20px; overflow-y: auto; padding-bottom: 20px;
               flex: 1; min-height: 0; scrollbar-width: thin; }

.befund {
  background: rgba(var(--hell-rgb),.32);
  border: 1px solid rgba(var(--hell-rgb),.5);
  border-left: 3px solid var(--tinte-leise);
  border-radius: 0; padding: 20px 24px;
  box-shadow: inset 0 1px 0 rgba(var(--hell-rgb),.7);
}
/* Die Farbe am linken Rand sagt, worum es geht — ohne dass man liest. */
.befund.auffaelligkeit { border-left-color: var(--warn); }
.befund.optimierung    { border-left-color: var(--akzent); }
.befund.zusammenfassung {
  border-left-color: var(--tinte);
  background: rgba(var(--hell-rgb),.44);
}
.befund.hoch.auffaelligkeit { border-left-color: var(--alarm); }
.befund.erledigt { opacity: .5; }
.befund.erledigt h3 { text-decoration: line-through; }

.befundkopf { display: flex; align-items: baseline; gap: 12px;
              flex-wrap: wrap; margin-bottom: 8px; }
.befundkopf h3 { font-size: 16.5px; font-weight: 500; }
.marke-art {
  font-size: 11.5px; letter-spacing: .04em; text-transform: uppercase;
  color: var(--tinte-leise); white-space: nowrap;
}
.befund p { font-size: 14.5px; line-height: 1.62; color: var(--tinte-matt);
            max-width: 84ch; }

.befundzahlen {
  display: flex; flex-wrap: wrap; gap: 10px 28px; margin-top: 14px;
  padding-top: 13px; border-top: 1px solid rgba(var(--hell-rgb),.5);
}
.befundzahlen small { display: block; font-size: 12px;
                      color: var(--tinte-leise); }
.befundzahlen b { font-size: 15px; font-weight: 500;
                  font-variant-numeric: tabular-nums; }
.befund .knopf { margin-top: 14px; }

/* Passwort nachtragen, ohne die Ansicht zu verlassen. Ein Systemdialog
   mitten in der Oberfläche sieht hingeworfen aus und kann nicht sagen,
   wofür das Passwort eigentlich ist. */
.passwortzeile {
  grid-column: 1 / -1; display: flex; gap: 10px; align-items: center;
  margin-top: 12px; padding-top: 12px;
  border-top: 1px solid rgba(var(--hell-rgb),.5);
}
.passwortzeile input {
  flex: 1; min-width: 0; font: inherit; font-size: 14px;
  padding: 10px 14px; border-radius: 0;
  border: 1px solid rgba(var(--hell-rgb),.7);
  background: rgba(var(--hell-rgb),.6); color: var(--tinte);
}
.passwortzeile input:focus {
  outline: none; border-color: rgba(var(--tinte-rgb),.4);
  box-shadow: 0 0 0 3px rgba(var(--tinte-rgb),.07);
}

/* Kontieren direkt in der Zeile. Wer 523 Fälle abarbeiten soll, darf für
   jeden einzelnen kein Fenster öffnen müssen. */
.kontieren { display: flex; gap: 8px; align-items: center; }
.kontieren input {
  width: 150px; font: inherit; font-size: 13.5px;
  padding: 7px 11px; border-radius: 0;
  border: 1px solid rgba(var(--hell-rgb),.7);
  background: rgba(var(--hell-rgb),.55); color: var(--tinte);
  font-variant-numeric: tabular-nums;
}
.kontieren input:focus {
  outline: none; border-color: rgba(var(--tinte-rgb),.4);
  background: rgba(var(--hell-rgb),.85);
  box-shadow: 0 0 0 3px rgba(var(--tinte-rgb),.07);
}

/* Höchstens zwei Zeilen. Ein Empfängername wie „Finanzamt Muenchen Finanzamt
   Muenchen STEUERN" macht die Tabellenzeile sonst doppelt so hoch wie ihre
   Nachbarn, und die Liste wird unruhig. Der volle Text steht im Titel. */
.zweizeilig {
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden; line-height: 1.35;
}

/* ── Kommandozentrale (Kanzlei-Übersicht) ──────────────────────────── */

/* Eine Karte je Mandant statt einer Tabellenzeile. Eine Zeile kann vier
   Rubriken nicht tragen: „letzter Finanzamtbrief" und „letzte Mail" sind
   Sätze, keine Zahlen, und nebeneinander in Spalten werden sie unlesbar
   schmal. */
/* Die Kartenliste MUSS rollen.
   Mit einem Mandanten war sie 236 px hoch und passte. Mit 230 sind es 9.440,
   und `.haupt` hat `overflow: hidden` — alles ab der vierten Karte war
   unerreichbar, auch der Knopf „Weitere 190 anzeigen" ganz unten. Gefunden
   von `tools/sichtprobe.mjs`, nicht mit dem Auge: von oben sieht die Liste
   vollkommen richtig aus. */
.lage-karten {
  display: flex; flex-direction: column; gap: 14px;
  flex: 1 1 0; min-height: 0; overflow-y: auto;
  padding-right: 4px; scrollbar-width: thin;
}
.lage-karten::-webkit-scrollbar { width: 6px; }
.lage-karten::-webkit-scrollbar-thumb {
  background: rgba(0,0,0,.16); border-radius: 3px;
}
/* Die Karten dürfen nicht schrumpfen, wenn viele davon in einem
   Flex-Behälter liegen — sonst quetscht der Behälter sie zusammen. */
.lage-karten > .lage-karte { flex: none; }

.lage-karte {
  background: rgba(var(--hell-rgb),.46);
  border: 1px solid rgba(var(--hell-rgb),.6);
  border-radius: 0;
  padding: 18px 20px;
}
/* Ein überfälliger Mandant muss ohne Lesen auffallen. */
.lage-karte.dringend { border-left: 4px solid var(--warn); }
.lage-karte.still    { opacity: .72; }

.lage-kopf {
  display: flex; align-items: baseline; gap: 12px;
  margin-bottom: 14px; cursor: pointer;
}
.lage-kopf .name  { font-size: 17px; font-weight: 500; }
.lage-kopf .nr    { font-size: 13px; color: var(--tinte-leise); }
.lage-kopf .lauf  { margin-left: auto; font-size: 13px; color: var(--tinte-matt); }

.lage-rubriken {
  display: grid; gap: 16px;
  grid-template-columns: repeat(auto-fit, minmax(215px, 1fr));
}
.lage-rubrik h4 {
  margin: 0 0 7px; font-size: 12px; font-weight: 500;
  color: var(--tinte-leise); letter-spacing: .04em; text-transform: uppercase;
}
.lage-rubrik .gross { font-size: 21px; font-variant-numeric: tabular-nums; }
.lage-rubrik .gross.warnen { color: var(--warn); }
.lage-rubrik .satz {
  font-size: 13.5px; color: var(--tinte-matt); line-height: 1.45;
  /* Betreffzeilen sind lang. Zwei Zeilen, dann Schluss — sonst schiebt eine
     einzige Mail die Karte auf die doppelte Höhe. */
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
}
.lage-rubrik .leise { font-size: 13px; color: var(--tinte-leise); }

/* ── Aufgabenbearbeitung ────────────────────────────────────────────── */

/* Liste links, Arbeitsfenster rechts. Nicht untereinander: wer eine Aufgabe
   bearbeitet, will die Liste im Blick behalten und ohne Zurückspringen zur
   nächsten wechseln. */
.arbeitsflaeche {
  display: grid; grid-template-columns: minmax(260px, 340px) 1fr;
  gap: 18px; flex: 1; min-height: 0; margin-top: 16px;
}
@media (max-width: 1180px) { .arbeitsflaeche { grid-template-columns: 1fr; } }

.aufgabenliste { overflow-y: auto; display: flex; flex-direction: column; gap: 8px; }
.aufgabenliste::-webkit-scrollbar { width: 6px; }
.aufgabenliste::-webkit-scrollbar-thumb {
  background: rgba(0,0,0,.16); border-radius: 3px;
}

.aufgabenzeile {
  padding: 13px 15px; border-radius: 0; cursor: pointer;
  background: rgba(var(--hell-rgb),.4);
  border: 1px solid rgba(var(--hell-rgb),.55);
  transition: background .14s ease, box-shadow .14s ease;
}
.aufgabenzeile:hover { background: rgba(var(--hell-rgb),.62); }
.aufgabenzeile.gewaehlt {
  background: rgba(var(--hell-rgb),.8);
  box-shadow: 0 0 0 1.5px var(--akzent) inset;
}
.aufgabenzeile.ueberfaellig { border-left: 3px solid var(--warn); }
.aufgabenzeile .titel { font-size: 14.5px; line-height: 1.35; }
.aufgabenzeile .unter {
  font-size: 12.5px; color: var(--tinte-leise); margin-top: 4px;
  display: flex; gap: 8px; flex-wrap: wrap;
}
.aufgabenzeile .unter .warnen { color: var(--warn); }

/* Schmal: Vorgang und Antwort untereinander, das Ganze scrollt.
   Breit: nebeneinander — „eine vorgefertigte Antwort in einem Chatfenster
   NEBEN der Aufgabe". Untereinander war das Antwortfenster 2790 px unter dem
   Sichtfeld; man musste bis ans Ende scrollen, um den Senden-Knopf zu finden.
   Die Klasse setzt ein ResizeObserver, nicht eine Bildschirmbreite: ob Platz
   ist, hängt davon ab, ob die Kontextleiste offen ist. */
.arbeitsfenster {
  overflow-y: auto; padding-right: 4px;
  display: flex; flex-direction: column; gap: 14px;
}
.arbeitsfenster::-webkit-scrollbar { width: 6px; }
.arbeitsfenster::-webkit-scrollbar-thumb {
  background: rgba(0,0,0,.16); border-radius: 3px;
}
.vorgangspalte, .antwortspalte {
  display: flex; flex-direction: column; gap: 14px; min-width: 0;
}

.arbeitsfenster.nebeneinander {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.06fr);
  gap: 16px; overflow: hidden; padding-right: 0;
}
.arbeitsfenster.nebeneinander .vorgangspalte {
  overflow-y: auto; padding-right: 6px; min-height: 0;
}
.arbeitsfenster.nebeneinander .vorgangspalte::-webkit-scrollbar { width: 6px; }
.arbeitsfenster.nebeneinander .vorgangspalte::-webkit-scrollbar-thumb {
  background: rgba(0,0,0,.16); border-radius: 3px;
}
/* Die Antwortspalte scrollt NICHT. Der Brief füllt die Höhe, die Fußleiste
   mit „Erledigen und antworten" bleibt sichtbar. */
.arbeitsfenster.nebeneinander .antwortspalte { overflow: hidden; min-height: 0; }
.arbeitsfenster.nebeneinander .antwortspalte > .antwortkarte {
  flex: 1; min-height: 0;
}
.arbeitsfenster.nebeneinander .verfassen { flex: 1; min-height: 0; }

.werkkarte {
  background: rgba(var(--hell-rgb),.5);
  border: 1px solid rgba(var(--hell-rgb),.62);
  border-radius: 0; padding: 18px 20px;
}
.werkkarte h3 {
  margin: 0 0 10px; font-size: 12px; font-weight: 500;
  color: var(--tinte-leise); letter-spacing: .04em; text-transform: uppercase;
}
/* Vorformatierter Text: der Lösungsweg kommt als nummerierte Schritte, und
   die sollen Schritte bleiben. */
.werkkarte .fliess {
  white-space: pre-wrap; font-size: 14.5px; line-height: 1.6;
}
.werkkarte .fein { font-size: 13px; color: var(--tinte-matt); line-height: 1.55; }
/* ── Verfassen: eine Fläche, keine schwebenden Kästen ──────────────────
   Vorher standen „An" und „Betreff" links neben ihren Feldern. Weil die
   beiden Wörter verschieden lang sind, begannen die Felder an verschiedenen
   Stellen, liefen über den Kartenrand hinaus, und das Textfeld hatte eine
   dritte Breite samt nativem Anfasser in der Ecke. Funktional richtig,
   handwerklich schlecht.

   Jetzt: EIN Block mit fester Beschriftungsspalte und Haarlinien dazwischen
   — wie ein Mailfenster. Alle Felder beginnen an derselben Kante, keins hat
   einen eigenen Rahmen, die Fläche hat einen Radius. */
/* Die Antwortspalte ist keine Karte in einer Karte, sondern die
   Arbeitsfläche selbst: Überschrift, darunter der Brief. */
.antwortkarte { display: flex; flex-direction: column; min-width: 0; }

.verfassen {
  border: 1px solid rgba(var(--hell-rgb),.72);
  border-radius: 0; overflow: hidden;
  /* Fast deckend, nicht durchscheinend: hier wird gelesen und geschrieben.
     Ein Brieftext auf zwei Lagen Milchglas verliert genau den Kontrast, den
     er zum Lesen braucht. */
  background: rgba(var(--hell-rgb),.88);
  box-shadow: 0 1px 3px rgba(0,0,0,.05), 0 8px 24px rgba(0,0,0,.06);
  /* Kopfzeilen fest, Brieftext dehnbar, Fußleiste unten. */
  display: flex; flex-direction: column;
}
.verfassen .reihe, .verfassen .fussleiste { flex: none; }
.verfassen .reihe {
  display: grid; grid-template-columns: 74px 1fr; align-items: center;
  border-bottom: 1px solid rgba(0,0,0,.07);
}
.verfassen .reihe label {
  padding-left: 16px; font-size: 13px; color: var(--tinte-leise);
  user-select: none;
}
.verfassen input,
.verfassen textarea {
  width: 100%; border: none; background: none; color: var(--tinte);
  font: inherit; font-size: 14.5px;
  /* Der native Anfasser unten rechts gehoert keinem Entwurf, den jemand
     gestaltet hat. Die Hoehe kommt aus dem Platz, nicht aus dem Ziehen. */
  resize: none;
}
.verfassen input { padding: 13px 16px 13px 0; }
.verfassen input:focus, .verfassen textarea:focus { outline: none; }
.verfassen input::placeholder, .verfassen textarea::placeholder {
  color: var(--tinte-leise);
}
/* Die ganze Reihe faerbt sich, nicht nur das Feld — sonst leuchtet ein
   Rechteck in einer Flaeche, die keine Rechtecke hat. */
.verfassen .reihe:focus-within { background: var(--flaeche-hoch); }

.verfassen .koerper {
  padding: 15px 16px 16px; min-height: 260px;
  line-height: 1.62; display: block;
}
/* Nebeneinander bekommt der Brief die Resthöhe und scrollt in sich. Vorher
   wuchs das Feld auf die Texthöhe — bei diesem Entwurf 829 px — und schob
   die Fußleiste aus dem Fenster. */
.arbeitsfenster.nebeneinander .verfassen .koerper {
  flex: 1; min-height: 0; height: auto !important; overflow-y: auto;
}
.arbeitsfenster.nebeneinander .verfassen .koerper::-webkit-scrollbar { width: 6px; }
.arbeitsfenster.nebeneinander .verfassen .koerper::-webkit-scrollbar-thumb {
  background: rgba(0,0,0,.16); border-radius: 3px;
}
.verfassen .fussleiste {
  display: flex; gap: 10px; align-items: center;
  padding: 12px 14px; border-top: 1px solid rgba(0,0,0,.07);
  /* Heller als die Fläche, nicht dunkler — die Fußleiste liegt darüber.
     Mit dem alten Wert (.4 auf einer .62-Fläche) war sie ein grauer Streifen,
     seit die Fläche fast deckend ist, wäre sie ein Loch. */
  background: rgba(var(--hell-rgb),.55);
}
.verfassen .fussleiste .hinweis {
  margin-left: auto; font-size: 12.5px; color: var(--tinte-leise);
}

.werkzeile { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.werkzeile .knopf { margin: 0; }

/* Ein Entwurf, den das Modell selbst für nicht versandfertig hält, darf
   nicht aussehen wie einer, der es ist. */
.pruefen {
  background: var(--warn-flach); border: 1px solid var(--warn);
  border-radius: 0; padding: 10px 13px; font-size: 13.5px;
  line-height: 1.5;
}

/* ── Kontoauszug Zeile für Zeile ────────────────────────────────────── */

/* Eine Zeile des Auszugs, darunter die Belege daran. Keine Tabelle: der
   Verwendungszweck ist bis zu 280 Zeichen lang und ein Beleg braucht eine
   eigene, anklickbare Zeile. In Spalten gepresst wird beides unlesbar. */
/* `margin-top` statt gar nichts: die Liste begann unmittelbar unter der
   Kopfreihe, die erste Zahl stand fast an den Kacheln. */
/* ── Kontoauszug: Liste links, Detail rechts ─────────────────────────────
   Baki: „unser Interface ist wirklich nicht gut und wirklich nicht
   übersichtlich."

   Gemessen war er im Recht: eine Buchungszeile war 118 bis 203 px hoch, weil
   Belegknöpfe, Kostenart, Konto und Klärfall alle IN der Zeile standen. Auf
   einen Laptop passten vier bis fünf Buchungen; bei 122 im Monat bedeutet das
   25-mal scrollen. Midday zeigt 18 Zeilen, weil dort eine Zeile 45 px hoch ist
   und alles Bedienbare rechts im Detail steht.

   Zwei Änderungen, eine Wirkung:
     1. Die Zeile trägt nur noch, was man beim Überfliegen braucht.
     2. Kein Milchglas mehr in der Liste. Durchscheinende Flächen auf
        durchscheinenden Flächen sehen auf einem Foto gut aus und sind zum
        Zahlenlesen falsch — nichts hat eine klare Kante. Jetzt: deckende
        Fläche, 1-px-Linien, keine Radien, keine Schatten. */
/* Dieselbe Aufteilung trägt inzwischen zwei Ansichten — Kontoauszug und
   Belege. Deshalb heißen Fläche, Liste, Zeile und Detailspalte nicht mehr
   nach dem Auszug, sondern nach dem, was sie sind.

   Die Klassen `.auszug` und `.buchung` bleiben ZUSÄTZLICH an ihren
   Elementen: `tools/zuordnenprobe.mjs` und `tools/scrollprobe.mjs` messen
   darauf. Eine Umbenennung, die die Proben blind macht, kostet mehr als ein
   zweiter Klassenname. */
.dichteflaeche {
  display: grid; grid-template-columns: minmax(0, 1fr);
  gap: 0; flex: 1 1 0; min-height: 0; margin-top: 16px;
}
.dichteflaeche:has(.detailspalte.offen) {
  grid-template-columns: minmax(0, 1fr) 380px;
}
/* Steht ein Suchfeld darüber, bringt es seinen eigenen Abstand mit (16 px
   unten). Zwei Abstände hintereinander wären 32 px — fast eine ganze Zeile,
   die niemand bestellt hat. */
.mandatensuche + .dichteflaeche { margin-top: 0; }

.dichteliste {
  display: flex; flex-direction: column;
  overflow-y: auto; min-height: 0;
  background: var(--flaeche);
  border: 1px solid rgba(var(--tinte-rgb),.13);
}
.dichteliste::-webkit-scrollbar { width: 8px; }
.dichteliste::-webkit-scrollbar-thumb { background: rgba(0,0,0,.18); }

/* 40 px hoch. Das ist die ganze Rechnung.
   Die Spaltenteilung steht bei der jeweiligen Ansicht — sie ist das
   einzige, worin sich die beiden Listen unterscheiden. */
.dichtezeile {
  display: grid;
  gap: 12px; align-items: center;
  padding: 0 14px; min-height: 40px;
  border-bottom: 1px solid rgba(var(--tinte-rgb),.07);
  cursor: pointer; background: transparent;
  border-left: 3px solid transparent;
}
.dichtezeile:last-child { border-bottom: none; }
@media (hover: hover) and (pointer: fine) {
  .dichtezeile:hover { background: rgba(var(--tinte-rgb),.045); }
}
.dichtezeile:focus-visible {
  outline: none; background: rgba(var(--tinte-rgb),.045);
  box-shadow: inset 0 0 0 2px var(--akzent);
}
.dichtezeile.gewaehlt { background: rgba(18,185,129,.09); }

/* Kontoauszug: Datum · wer · Konto · Belegzustand · Beleg dazu · Betrag
   Die Kontospalte ist von 58 auf 96 px gewachsen: dort stand vorher ein
   blosses „?", jetzt steht dort „Konto fehlt" oder „4980 prüfen". Ein
   Fragezeichen sagt, DASS etwas unklar ist, nicht WAS. */
.buchung { grid-template-columns: 62px minmax(0, 1fr) 96px 132px 76px 106px; }

/* Der Buchungssatz — dieselbe Zeile, eine Spalte mehr: das Auswahlkästchen.
   Es steht vorn, weil man beim Freigeben von oben nach unten hakt und die
   Augen dabei an der linken Kante bleiben. */
.buchungssatz { grid-template-columns: 40px 62px minmax(0, 1fr) 110px 132px 106px; }
.buchungssatz .kontospalte { text-align: left; }
/* Ein <input> hat ~170 px EIGENbreite und quillt sonst aus seiner
   110-px-Rasterspalte unter den Zustandstext — im dunklen Thema lief der
   Kastenrand mitten durch „freigegeben". Von Baki fotografiert. Ein
   Rasterkind schrumpft erst mit min-width: 0 unter seine Eigenbreite. */
.buchungssatz .kontofeld { width: 100%; min-width: 0; }

/* „Alle sichtbaren auswählen" stand vorher als namenloses Kästchen im
   Tabellenkopf. Ein Kästchen ohne Wort ist eine Frage ohne Text — jetzt
   steht sie da. */
.alleauswahl {
  display: flex; align-items: center; gap: 8px;
  padding: 6px 10px 8px; font-size: 12.5px; color: var(--tinte-leise);
}

/* Das Einzige in der Zeile, das jemand noch beschaffen muss. */
.dichtezeile .wer .zweck .warnwort { color: var(--warn); font-weight: 500; }

/* `stand-…` statt der rohen Statusnamen: `.klaerung` und `.vorschlag` sind
   im Stilblatt seit Langem vergeben (Klaerzeile, Kontovorschlag). Zwei Orte,
   ein Name — genau der Fehler, der schon `.marke` und `.konto` getroffen
   hat. Der Zustand traegt hier deshalb ein eigenes Vorwort. */
.dichtezeile .zustand.stand-vorschlag .ampel   { background: var(--warn); }
.dichtezeile .zustand.stand-klaerung .ampel    { background: var(--warn); }
.dichtezeile .zustand.stand-klaerung           { color: var(--warn); }
.dichtezeile .zustand.stand-freigegeben .ampel { background: var(--akzent); }
.dichtezeile .zustand.stand-exportiert .ampel  { background: rgba(var(--tinte-rgb),.22); }
.dichtezeile .zustand.stand-exportiert         { color: var(--tinte-leise); }
.buchung.fehlt    { border-left-color: var(--warn); }
.buchung.eingang .summe { color: #0d7a56; }

/* Belege: Eingang · Lieferant und Rechnungsnummer · Belegdatum ·
   Zustand · Bruttobetrag. Lieferant, Rechnungsnummer, Brutto und
   Belegdatum liefert `beleg_liste` seit jeher — angezeigt wurden sie nie,
   und ohne sie ist die Liste 59-mal derselbe Satz. */
.belegzeile { grid-template-columns: 62px minmax(0, 1fr) 62px 150px 106px; }
/* Was noch nicht ausgelesen ist, ist die eigentliche Arbeit. */
.belegzeile.neu { border-left-color: var(--warn); }
/* Verworfenes bleibt lesbar, aber zurückgenommen — es zählt nicht mehr. */
.belegzeile.verworfen { opacity: .5; }

.dichtezeile .tag {
  font-size: 12.5px; color: var(--tinte-matt);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
/* Empfänger und Zweck auf EINER Zeile — der Zweck leiser dahinter.
   Zweizeilig kostete allein 25 % der sichtbaren Zeilen. */
.dichtezeile .wer {
  min-width: 0; display: flex; align-items: baseline; gap: 8px;
  white-space: nowrap; overflow: hidden;
}
.dichtezeile .wer .name {
  font-size: 13.5px; color: var(--tinte); flex: none;
  max-width: 60%; overflow: hidden; text-overflow: ellipsis;
}
.dichtezeile .wer .zweck {
  font-size: 12.5px; color: var(--tinte-leise);
  overflow: hidden; text-overflow: ellipsis; min-width: 0;
}
/* `kontospalte`, nicht `konto`: die Klasse `.konto` gehört dem Benutzerblock
   in der Seitenleiste (Zeile 264) und bringt dort `display: flex` und
   `margin-bottom: 26px` mit. In einer Zeilenzelle heisst das: rechtsbündig
   wirkt nicht, und der Text sitzt 13 px zu hoch. Gemessen, nicht vermutet. */
.buchung .kontospalte {
  font-size: 12.5px; color: var(--tinte-matt);
  font-variant-numeric: tabular-nums; text-align: right;
}
/* Das Belegdatum steht rechtsbündig neben dem Eingangsdatum links: beide
   sind Daten, und untereinander stehende Zahlenspalten liest man an der
   Kante. */
.belegzeile .bdatum {
  font-size: 12.5px; color: var(--tinte-matt);
  font-variant-numeric: tabular-nums; text-align: right;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.dichtezeile .zustand {
  display: flex; align-items: center; gap: 6px;
  font-size: 12px; color: var(--tinte-matt);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.dichtezeile .zustand span:not(.ampel) {
  overflow: hidden; text-overflow: ellipsis;
}
.dichtezeile .zustand .ampel {
  width: 6px; height: 6px; border-radius: 50%; flex: none;
  background: var(--tinte-leise);
}
.dichtezeile .zustand.zugeordnet .ampel { background: var(--akzent); }
.dichtezeile .zustand.fehlt .ampel      { background: var(--warn); }
.dichtezeile .zustand.fehlt             { color: var(--warn); }
.dichtezeile .zustand.belegfrei .ampel  { background: rgba(var(--tinte-rgb),.22); }
.dichtezeile .zustand.eingang .ampel    { background: rgba(18,185,129,.45); }
/* Die Zustände der Belegliste. „neu" warnt, weil dort Arbeit liegt;
   „gebucht" ist der Endzustand und darf so grün sein wie „zugeordnet". */
.dichtezeile .zustand.neu .ampel        { background: var(--warn); }
.dichtezeile .zustand.neu               { color: var(--warn); }
.dichtezeile .zustand.extrahiert .ampel { background: rgba(18,185,129,.45); }
.dichtezeile .zustand.gebucht .ampel    { background: var(--akzent); }
.dichtezeile .zustand.verworfen .ampel  { background: rgba(var(--tinte-rgb),.22); }

.dichtezeile .summe {
  text-align: right; font-variant-numeric: tabular-nums;
  font-size: 13.5px; white-space: nowrap; color: var(--tinte);
}
/* Ein Beleg ohne ausgelesenen Betrag darf keine Lücke reißen — der
   Gedankenstrich hält die Spalte. */
.dichtezeile .summe.ohne { color: var(--tinte-leise); }

/* ── Die Detailspalte ──────────────────────────────────────────────────── */
.detailspalte { display: none; }
.detailspalte.offen {
  display: flex; flex-direction: column; gap: 0;
  overflow-y: auto; min-height: 0;
  background: var(--flaeche-hoch);
  border: 1px solid rgba(var(--tinte-rgb),.13); border-left: none;
  padding: 18px 20px 24px;
}
.detailspalte .dkopf {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: 10px;
}
.detailspalte .dtag {
  font-size: 12.5px; color: var(--tinte-matt);
  font-variant-numeric: tabular-nums;
}
.detailspalte .dschliessen {
  width: 34px; height: 34px; border: none; background: none;
  color: var(--tinte-leise); font-size: 21px; line-height: 1;
  cursor: pointer; margin-right: -8px;
  transition: color var(--zeit-druck) ease,
              transform var(--zeit-druck) var(--kurve-raus);
}
.detailspalte .dschliessen:hover  { color: var(--tinte); }
.detailspalte .dschliessen:active { transform: scale(.97); }

/* Die Dokumentvorschau im Detail liefert `.belegvorschau` (weiter unten) —
   die parallel entstandene `.dvorschau`-Fassung ist beim Zusammenführen
   der Fassung vom Mac mini gewichen. */

.detailspalte .dwer {
  font-size: 15px; line-height: 1.35; color: var(--tinte);
}
.detailspalte .dsumme {
  font-size: 30px; line-height: 1.2; margin: 6px 0 2px;
  font-variant-numeric: tabular-nums; color: var(--tinte);
}
.detailspalte .dzweck {
  font-size: 12.5px; line-height: 1.5; color: var(--tinte-leise);
  margin-top: 8px; word-break: break-word;
}
.detailspalte .dfeld {
  margin-top: 20px; padding-top: 16px;
  border-top: 1px solid rgba(var(--tinte-rgb),.1);
  display: flex; flex-wrap: wrap; gap: 8px;
}
.detailspalte .dfeld h4 {
  flex-basis: 100%; margin: 0 0 2px; font-size: 11px; font-weight: 500;
  color: var(--tinte-leise); letter-spacing: .05em; text-transform: uppercase;
}
.detailspalte .dwert {
  flex-basis: 100%; font-size: 14px; color: var(--tinte);
  font-variant-numeric: tabular-nums;
}
.detailspalte .fein { flex-basis: 100%; }
.detailspalte .knopf { margin: 0; }
.detailspalte .klaerung { flex-basis: 100%; margin-top: 4px; }
/* Was beim Auslesen schiefging, gehört nicht in eine Fußnote. Es ist der
   Grund, warum bei diesem Beleg kein Betrag steht. */
.detailspalte .dfehler {
  flex-basis: 100%; font-size: 12.5px; line-height: 1.45;
  color: var(--alarm); word-break: break-word;
}

/* Tastenkürzel als sichtbare Kappen, unten in der Spalte.
   Wer 122 Zeilen prüft, soll mit den Pfeiltasten durchgehen können — aber
   niemand lernt ein Kürzel auswendig, das nirgends steht. 10 px, damit es
   die Auskunft darüber nicht überstimmt; `margin-top: auto` drückt die
   Reihe an den Fuß, egal wie kurz das Detail ist. */
.detailspalte .dtasten {
  margin-top: auto; padding-top: 20px;
  display: flex; flex-wrap: wrap; gap: 6px 14px;
  font-size: 10px; color: var(--tinte-leise); line-height: 1.6;
}
.detailspalte .dtasten span { display: inline-flex; align-items: center; gap: 4px; }
.detailspalte kbd {
  display: inline-block; min-width: 15px; padding: 1px 4px;
  border: 1px solid rgba(var(--tinte-rgb),.22); border-radius: 0;
  background: var(--flaeche-hoch); color: var(--tinte-matt);
  font: inherit; font-size: 10px; line-height: 1.4; text-align: center;
}

/* Eng: das Detail legt sich über die Liste statt daneben. */
@media (max-width: 1180px) {
  .dichteflaeche:has(.detailspalte.offen) { grid-template-columns: minmax(0,1fr); }
  .dichteflaeche:has(.detailspalte.offen) .dichteliste { display: none; }
  .detailspalte.offen { border-left: 1px solid rgba(var(--tinte-rgb),.13); }
}

.belegknopf {
  display: inline-flex; align-items: center; gap: 7px;
  /* Mindestens 34 px hoch. Der Prüflauf misst Klickflächen und hatte hier
     29 px gemeldet — auf einem Laptop-Trackpad trifft man das schlecht,
     und es ist der wichtigste Knopf der Ansicht. */
  padding: 8px 12px; min-height: 34px; border-radius: 0; cursor: pointer;
  background: var(--akzent-flach); border: 1px solid rgba(18,185,129,.4);
  color: var(--tinte); font: inherit; font-size: 13px; line-height: 1.3;
  text-align: left;
}
.belegknopf:hover { background: rgba(18,185,129,.22); }
.belegknopf .quelle { color: var(--tinte-leise); font-size: 11.5px; }
.belegknopf[disabled] { opacity: .6; cursor: wait; }

.fehltknopf {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 11px; border-radius: 0;
  background: var(--warn-flach); border: 1px solid rgba(0,0,0,.06);
  font-size: 12.5px; color: var(--tinte-matt);
}

/* „Mietvertrag", „Lohnjournal": kein Mangel, sondern die Auskunft, WARUM
   hier kein Einzelbeleg liegt. Deshalb ruhig und nicht warnfarben. */
.grundknopf, .artknopf {
  display: inline-flex; align-items: center;
  padding: 5px 11px; border-radius: 0; font-size: 12.5px;
  background: rgba(var(--hell-rgb),.5); border: 1px solid rgba(var(--hell-rgb),.7);
  color: var(--tinte-matt);
}
.artknopf { color: var(--tinte-leise); font-size: 12px; }

/* ── Lagezahlen im Kopf, die beim Scrollen zusammenschrumpfen ────────── */

/* Die drei Zahlen standen unter der Überschrift und nahmen 110 px Höhe weg —
   bei einem Arbeitsfenster, in dem man einen Brief schreibt, ist das die
   Hälfte des Textfeldes. Jetzt stehen sie RECHTS neben der Überschrift und
   schrumpfen beim Scrollen zu Pillen zusammen.

   Der Kniff für eine Animation, die wirklich läuft: Beschriftung und Zahl
   liegen in einem umbrechenden Flex-Kasten, die Beschriftung steht zuerst.
   Gross hat sie `flex-basis: 100%` und drängt die Zahl in die zweite Zeile;
   klein geht die Basis auf 0 und beide stehen nebeneinander. `flex-basis`
   ist animierbar — `flex-direction` wäre es nicht und würde springen. */
.lagechips {
  display: flex; gap: 10px; align-items: stretch;
  transition: gap var(--zeit-mittel) var(--kurve-schub);
}
.lagechip {
  display: flex; flex-wrap: wrap; align-items: baseline;
  gap: 0 7px; padding: 9px 16px; min-width: 104px;
  border-radius: 0;
  background: rgba(var(--hell-rgb),.42);
  border: 1px solid rgba(var(--hell-rgb),.6);
  /* Der Radius stand hier mit im Übergang. Er ist jetzt in beiden
     Zuständen 0 — ein Übergang auf einen Wert, der sich nie ändert, ist
     tote Rechenzeit. */
  transition: padding var(--zeit-mittel) var(--kurve-schub),
              min-width var(--zeit-mittel) var(--kurve-schub),
              background var(--zeit-klein) ease;
}
.lagechip .text {
  flex-basis: 100%; font-size: 12px; color: var(--tinte-leise);
  letter-spacing: .01em; white-space: nowrap;
  transition: flex-basis var(--zeit-mittel) var(--kurve-schub),
              font-size var(--zeit-mittel) var(--kurve-schub);
}
.lagechip .wert {
  font-size: 27px; font-variant-numeric: tabular-nums; line-height: 1.1;
  transition: font-size var(--zeit-mittel) var(--kurve-schub);
}
.lagechip.warnen .wert { color: var(--warn); }

/* Anklickbare Zahlen filtern die Liste darunter. Eine Zahl, die aussieht wie
   ein Knopf, muss auch einer sein — und eine, die man drücken kann, muss
   zeigen, dass sie gedrückt ist. */
.lagechip.waehlbar { cursor: pointer; }
.lagechip.waehlbar:hover { background: rgba(var(--hell-rgb),.62); }
.lagechip.aktiv {
  background: rgba(var(--hell-rgb),.88);
  box-shadow: 0 0 0 1.5px var(--akzent) inset;
  border-color: transparent;
}
.lagechips.klein .lagechip.aktiv { background: rgba(var(--hell-rgb),.8); }

.lagechips.klein { gap: 7px; }
.lagechips.klein .lagechip {
  padding: 5px 12px; min-width: 0; border-radius: 0;
  background: rgba(var(--hell-rgb),.34);
}
.lagechips.klein .text { flex-basis: 0%; font-size: 12px; }
.lagechips.klein .wert { font-size: 15px; }

@media (prefers-reduced-motion: reduce) {
  .lagechips, .lagechip, .lagechip .text, .lagechip .wert { transition: none; }
}

/* Kante ausblenden, damit gescrollter Inhalt nicht abgeschnitten aussieht.
   Die Maske gehört an den Bereich, der WIRKLICH scrollt. Nebeneinander ist
   das nicht mehr das Arbeitsfenster, sondern nur die linke Spalte — dort
   fraß die Maske sonst die Fußleiste des Briefs an, den unteren Rand sah man
   verwaschen auslaufen, obwohl da gar nichts weiterging. */
.arbeitsfenster:not(.nebeneinander),
.arbeitsfenster.nebeneinander .vorgangspalte {
  -webkit-mask-image: linear-gradient(180deg, transparent 0, #000 14px,
                                      #000 97%, transparent 100%);
          mask-image: linear-gradient(180deg, transparent 0, #000 14px,
                                      #000 97%, transparent 100%);
}

/* ── Beleg von Hand zuordnen ────────────────────────────────────────── */

/* Das Auswahlfeld sitzt seit dem Umbau in der Detailspalte, in einem
   `.dfeld` mit `flex-wrap`. Ohne volle Basis schrumpft es dort auf die
   Breite seines längsten Wortes. */
.detailspalte .zuordnen { flex-basis: 100%; }
.zuordnen {
  grid-column: 2 / 4; margin-top: 8px;
  background: rgba(var(--hell-rgb),.62);
  border: 1px solid rgba(var(--hell-rgb),.8);
  border-radius: 0; padding: 12px 14px;
}
.zuordnen .suche {
  width: 100%; padding: 8px 12px; border-radius: 0; font: inherit;
  font-size: 13.5px; border: 1px solid rgba(var(--hell-rgb),.8);
  background: rgba(var(--hell-rgb),.8); color: var(--tinte); margin-bottom: 8px;
}
.zuordnen .suche:focus { outline: none; border-color: rgba(18,185,129,.55); }
/* Höchstens fünf Vorschläge sichtbar, der Rest rollt. Ein Auswahlfeld, das
   die halbe Seite aufschiebt, verdeckt genau die Zeile, um die es geht. */
.zuordnen .treffer { max-height: 176px; overflow-y: auto; }
.zuordnen .treffer::-webkit-scrollbar { width: 5px; }
.zuordnen .treffer::-webkit-scrollbar-thumb {
  background: rgba(0,0,0,.16); border-radius: 3px;
}
.zuordnen .kandidat {
  display: flex; align-items: baseline; gap: 10px; width: 100%;
  padding: 8px 10px; border-radius: 0; cursor: pointer;
  background: none; border: none; font: inherit; font-size: 13.5px;
  color: var(--tinte); text-align: left;
}
.zuordnen .kandidat:hover { background: rgba(18,185,129,.14); }
.zuordnen .kandidat .passt { color: var(--akzent); font-size: 12px; }
.zuordnen .kandidat .datum {
  margin-left: auto; color: var(--tinte-leise); font-size: 12px;
  white-space: nowrap;
}
.zuordnen .fuss {
  display: flex; gap: 8px; align-items: center; margin-top: 8px;
  padding-top: 8px; border-top: 1px solid rgba(0,0,0,.06);
}

/* Das × am zugeordneten Beleg: klein, aber nicht versteckt. Eine falsche
   Zuordnung muss man wegnehmen können, ohne die Ansicht zu wechseln. */
.belegknopf .loesen {
  margin-left: 2px; padding: 0 3px; border-radius: 0;
  color: var(--tinte-leise); font-size: 14px; line-height: 1;
}
.belegknopf .loesen:hover { background: rgba(0,0,0,.1); color: var(--tinte); }

/* ── Werkbank über einer Tabelle ─────────────────────────────────────────
   Was mit der Auswahl geschehen kann, steht ÜBER der Liste — nicht unter
   ihr. Bei 122 Zeilen wäre ein Knopf am Fuß nach dem Scrollen unauffindbar,
   und die Auswahl trifft man oben. */
.werkbank {
  display: flex; align-items: center; gap: 10px;
  margin: 14px 0 10px; min-height: 34px;
}
.werkbank .schub { flex: 1; }
.werkbank .stand {
  font-size: 13px; color: var(--tinte-leise); margin-right: 4px;
}
.werkbank .knopf { margin: 0; }
/* Die Werkbank bringt ihren Abstand nach unten schon mit — der eigene
   Abstand der Tabelle käme obendrauf. */
.werkbank + .tabelle { margin-top: 0; }

/* Die Auswahlspalte bleibt schmal und die Kästchen mittig — sonst wandert
   die erste Datenspalte je nach Zeileninhalt hin und her. */
th.wahlspalte, td.wahlspalte {
  width: 34px; padding-left: 14px; padding-right: 0; text-align: left;
}
.wahlspalte input[type="checkbox"] {
  width: 15px; height: 15px; margin: 0; cursor: pointer;
  accent-color: var(--akzent); vertical-align: middle;
}

/* Das Gegenkonto einer Bankzahlung ist immer dasselbe (1200). Es gehört in
   die Tabelle, weil es den Buchungssatz vollständig macht — aber leiser als
   das Konto, das den Vorgang benennt. */
td.konto-nr.gegen { color: var(--tinte-leise); }

/* ── Suche über die Mandate ──────────────────────────────────────────────
   Mit einem Mandanten war die Kartenliste die Übersicht. Mit 230 ist sie
   ohne Suche unbenutzbar — 229 Karten sagen dasselbe („keine Bankdaten"). */
.mandatensuche {
  display: flex; align-items: center; gap: 10px;
  margin: 14px 0 16px; flex-wrap: wrap;
}
.mandatensuche .suchfeld {
  flex: 1 1 260px; min-width: 200px;
  padding: 10px 14px; border-radius: 0;
  border: 1px solid rgba(var(--hell-rgb),.62);
  background: rgba(var(--hell-rgb),.5);
  font: inherit; font-size: 14.5px; color: var(--tinte);
  transition: background var(--zeit-druck) ease,
              border-color var(--zeit-druck) ease;
}
.mandatensuche .suchfeld::placeholder { color: var(--tinte-leise); }
.mandatensuche .suchfeld:focus {
  outline: none; background: var(--flaeche-hoch);
  border-color: rgba(var(--tinte-rgb),.22);
}
/* Das native Kreuz in `type="search"` gehört keinem Entwurf, den jemand
   gestaltet hat — und es sieht in jedem Browser anders aus. */
.mandatensuche .suchfeld::-webkit-search-cancel-button { appearance: none; }

.filterchips { display: flex; gap: 7px; }
.filterchip {
  padding: 9px 15px; border-radius: 0; min-height: 34px;
  border: 1px solid rgba(var(--tinte-rgb),.14);
  background: rgba(var(--hell-rgb),.4);
  color: var(--tinte-matt); font: inherit; font-size: 13.5px;
  cursor: pointer;
  transition: background var(--zeit-druck) ease,
              color var(--zeit-druck) ease,
              border-color var(--zeit-druck) ease,
              transform var(--zeit-druck) var(--kurve-raus);
}
@media (hover: hover) and (pointer: fine) {
  .filterchip:hover { background: rgba(var(--hell-rgb),.66); color: var(--tinte); }
}
.filterchip:active { transform: scale(.97); }
.filterchip.aktiv {
  background: var(--dunkel); color: #fff; border-color: transparent;
}
/* „Alle" ist der Ruhezustand und muss sich nicht als Filter aufspielen. */
.filterchip[data-wert="alle"].aktiv {
  background: rgba(var(--hell-rgb),.8); color: var(--tinte);
  border-color: rgba(var(--tinte-rgb),.2);
}

.trefferzahl {
  margin-left: auto; font-size: 13px; color: var(--tinte-leise);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
/* Leer heisst weg, nicht leer aber da. Ein leeres Element mit Zeilenhoehe
   haelt seinen Platz und schiebt die Liste nach unten — auf dem Telefon um
   eine ganze Zeile. */
.trefferzahl:empty { display: none; }

/* ── Die Filterzeile über einer Tabelle ──────────────────────────────────
   Mandant, Monat, Status, Suche — in der Reihenfolge, in der man einengt.
   Sie steht in einer Zeile, weil jeder Teil für sich schmal ist; erst
   zusammen ergeben sie die Frage „welche Buchungen sehe ich gerade?". */
.filterzeile {
  display: flex; align-items: flex-end; gap: 12px;
  margin: 14px 0 12px; flex-wrap: wrap;
}
/* Die Suchleiste bringt ihre eigenen Ränder mit — in der Filterzeile
   stören sie, dort setzt der Abstand der Zeile den Takt.

   Und sie bringt ihr eigenes Aussehen mit: halbdurchsichtig, fast randlos.
   Für sich genommen richtig, in dieser Zeile falsch — daneben stehen drei
   weiße Felder mit grauem Rand, und das vierte sah aus wie ein Loch. Vier
   Felder nebeneinander sind vier gleiche Felder. */
.filterzeile .mandatensuche {
  margin: 0; flex: 1 1 220px; min-width: 180px;
  flex-direction: column; align-items: stretch; gap: 5px;
}
.filterzeile .mandatensuche .suchfeld {
  flex: none; width: 100%; min-width: 0;
  padding: 9px 12px; min-height: 36px;
  border: 1px solid rgba(var(--tinte-rgb),.18); background: var(--flaeche-hoch);
  font-size: 13.5px;
}
.filterzeile .mandatensuche .suchfeld:focus {
  border-color: var(--akzent); box-shadow: 0 0 0 3px var(--akzent-flach);
}
/* Die Trefferzahl darf die Zeile nicht auseinanderziehen — sie steht unter
   dem Feld, wo ohnehin Platz ist, und nur dann, wenn gesucht wurde. */
.filterzeile .trefferzahl {
  margin: 0; order: 3; font-size: 12px;
}
.filterzeile .trefferzahl:empty { display: none; }
.filterzeile + .werkbank { margin-top: 0; }

/* Der feste Platz des Mandantenwechsels: unter dem Kanzleinamen, über allem,
   was die Ansicht darunter zeigt. Klein — er ist ein Umschalter, kein Thema
   der Seite. Die trennende Linie sagt, dass darunter etwas anderes anfängt. */
.leiste-mandant {
  padding: 0 14px 14px;
  border-bottom: 1px solid rgba(var(--tinte-rgb),.1);
  margin-bottom: 12px;
}
.leiste-mandant .mandantwahl { gap: 4px; }
.leiste-mandant .wahlfeld { width: 100%; min-width: 0; font-size: 13px; }
.leiste-mandant .mandantwahl .wahlfeld[type="text"] { min-width: 0; }

.mandantwahl { display: flex; flex-direction: column; gap: 5px; }
.wahlmarke {
  font-size: 11px; letter-spacing: .06em; text-transform: uppercase;
  color: var(--tinte-leise);
}
.wahlfeld {
  padding: 9px 12px; border-radius: 0; min-height: 36px;
  border: 1px solid rgba(var(--tinte-rgb),.18);
  background: var(--flaeche-hoch); font: inherit; font-size: 13.5px; color: var(--tinte);
  transition: border-color var(--zeit-druck) ease;
}
.wahlfeld:focus {
  outline: none; border-color: var(--akzent);
  box-shadow: 0 0 0 3px var(--akzent-flach);
}
.mandantwahl .wahlfeld[type="text"] { min-width: 230px; }
/* Der native Aufklapppfeil ist der einzige Anfasser, den wir stehen lassen:
   ohne ihn sieht ein `select` aus wie ein Textfeld, und man weiß nicht, dass
   etwas dahinter liegt. */
select.wahlfeld { cursor: pointer; }

/* Das Konto in der Buchungszeile: ruhig, bis man hinzeigt.
   Ein umrandetes Eingabefeld in jeder der 25 Zeilen wäre eine Wand aus
   Kästen; hier liest man meistens nur. Beim Überfahren zeigt sich der
   Rahmen — dann ist erkennbar, dass die Zahl änderbar ist. */
.tabelle td .kontofeld {
  width: 88px; padding: 4px 7px;
  border-color: transparent; background: transparent;
  transition: border-color var(--zeit-druck) ease,
              background var(--zeit-druck) ease;
}
@media (hover: hover) and (pointer: fine) {
  .tabelle tr:hover .kontofeld { border-color: rgba(var(--tinte-rgb),.18); background: var(--flaeche-hoch); }
}
.tabelle td .kontofeld:focus { border-color: var(--akzent); background: var(--flaeche-hoch); }
.tabelle td .kontofeld:disabled { opacity: .5; }
/* Kurze Bestätigung, dass geschrieben wurde. Ohne sie fragt man sich, ob der
   Klick angekommen ist — und tippt die Zahl ein zweites Mal. */
.tabelle td .kontofeld.gesetzt {
  border-color: var(--akzent);
  background: var(--akzent-flach);
}
.lage-karten > .knopf { align-self: center; margin-top: 4px; }

/* ── Klärfall an der Kontoauszugszeile ───────────────────────────────────
   Stand bis heute auf einem eigenen Bildschirm. Wer den Auszug durchging,
   sah dort nicht, dass bei dieser Zeile das Konto offen ist — und wer die
   Klärung durchging, sah den Beleg nicht. Zwei Bildschirme für eine Zeile. */
.klaerung {
  grid-column: 2 / 4; display: flex; align-items: center;
  gap: 8px; flex-wrap: wrap; margin-top: 8px;
  padding: 9px 12px; border-radius: 0;
  background: rgba(18,185,129,.07);
  border: 1px solid rgba(18,185,129,.22);
}
.klaerung .warum {
  font-size: 12.5px; color: var(--tinte-matt); line-height: 1.4;
}
.klaerung .vorschlag {
  font-size: 12.5px; font-variant-numeric: tabular-nums;
  padding: 4px 10px; border-radius: 0;
  background: rgba(18,185,129,.14); color: #0d7a56; white-space: nowrap;
}
.klaerung .entscheidung {
  margin-left: auto; display: flex; gap: 8px; flex: none;
}
.klaerung .entscheidung .knopf { margin: 0; white-space: nowrap; }
/* Der Grund darf schrumpfen, die Knöpfe nicht. */
.klaerung .warum { flex: 1 1 240px; min-width: 0; }

/* Das Kontofeld. Schmal — es nimmt vier Ziffern auf, nicht einen Satz. */
.kontofeld {
  padding: 7px 11px; border-radius: 0;
  border: 1px solid rgba(var(--tinte-rgb),.18);
  background: var(--flaeche-hoch); font: inherit; font-size: 13.5px;
  font-variant-numeric: tabular-nums; color: var(--tinte);
}
.kontofeld:focus {
  outline: none; border-color: var(--akzent);
  box-shadow: 0 0 0 3px var(--akzent-flach);
}
.kontofeld::placeholder { color: var(--tinte-leise); }
.klaerung .kontofeld { width: 108px; }

/* Statuszelle mit Nebenhandlung. Der Knopf steht rechts und bleibt leise —
   er ist der Ausweg, nicht der Hauptweg. */
td.statuszelle {
  display: flex; align-items: center; gap: 10px; justify-content: space-between;
}
td.statuszelle .knopf { margin: 0; flex: none; }

/* ═══════════════════════════════════════════════════════════════════════
   TELEFON UND TABLET
   ═══════════════════════════════════════════════════════════════════════

   Baki, mit dem Telefon in der Hand: „Das, was du da baust, ist auf jeden
   Fall nicht mobile first, es ist nicht mal mobiltauglich."

   Er hatte recht, und die Ursache ist eine Zeile: das Raster steht fest auf
   `96px  340px  1fr`. Schiene und Leiste belegen zusammen 436 px, bevor der
   Inhalt anfängt. Auf einem iPhone mit 390 px Fensterbreite blieb für die
   Inhaltsspalte nichts übrig — sie war rechnerisch negativ breit, und was
   man sah, war die Leiste, die über den Bildschirmrand hinausragte.

   Warum es niemandem auffiel: die schmalste Breite im Prüflauf war 1180 px,
   die schmalste Regel in dieser Datei griff bei 1080. Unterhalb davon gab es
   schlicht kein Layout. `tools/audit.mjs` prüft jetzt zuerst 390 und 360 px.

   Der Umbau in einem Satz: aus drei Spalten nebeneinander werden drei Lagen
   übereinander — Inhalt in der Mitte, Navigation unten am Daumen, Mandant
   und Filter oben.
   ─────────────────────────────────────────────────────────────────────── */

@media (max-width: 860px) {

  /* ── Glas aus ─────────────────────────────────────────────────────────
     `backdrop-filter` macht ein Element zum ENTHALTENDEN BLOCK fuer alle
     `position: fixed`-Nachfahren. `.glasflaeche` traegt `blur(44px)`, also
     bezog sich `inset: 0` der Detailspalte nicht auf das Fenster, sondern
     auf die Karte darunter: gemessene 364×261 px statt 390×844, mit 274 px
     verborgenem Inhalt — Kontofeld und „buchen"-Knopf eines Klaerfalls lagen
     ausserhalb. Darunter lagen gleichzeitig 288 px leerer Bildschirm.

     Auf dem Telefon ist das Glas ohnehin ein teurer Effekt, den ein Sechstel
     der Flaeche traegt. Aus, und die Flaeche wird deckend — dann stimmt auch
     wieder, was ueber einer rollenden Liste steht. */
  .glasflaeche {
    backdrop-filter: none; -webkit-backdrop-filter: none;
    background: var(--glas-fest);
  }

  /* ── Die Seite muss rollen dürfen ─────────────────────────────────────
     `body { overflow: hidden }` und `html, body { height: 100% }` stammen
     aus dem Schreibtischlayout: dort ist das Fenster fest und die einzelnen
     Flächen rollen innen. Auf dem Telefon heisst dieselbe Zeile: die Seite
     lässt sich überhaupt nicht bewegen. Baki: „Scrollen geht auch nicht,
     also kein Plan was du redest, aber da geht gar nichts."

     Er hatte recht, und mein Prüfstand hatte es NICHT gefunden — schlimmer
     noch, er hatte es grün gemeldet: er rief `window.scrollTo(0, 600)` und
     stellte danach fest, dass die haftende Suchleiste bei 0 stand. Sie stand
     dort, weil sich nichts bewegt hatte. Eine Prüfung, die einen
     Nicht-Effekt für den erwarteten Effekt hält, ist schlimmer als keine.

     KEIN `overflow-x: hidden` mehr, und das ist der Kern:

     Die Kombination `overflow-y: visible` + `overflow-x: hidden` gibt es in
     CSS nicht. Sobald eine Achse `hidden` ist, rechnet der Browser die
     andere von `visible` auf `auto` um. Damit wurde `body` selbst zum
     Rollbehälter — und der endet wegen `min-height: 100%` an der KLEINEN
     Bildschirmhöhe, also oberhalb von Safaris Werkzeugleiste. Der Inhalt
     rollte innerhalb dieses Kastens; hinter der Leiste konnte deshalb
     niemals etwas liegen, dort blieb nur der Seitenhintergrund stehen.

     Nachgewiesen, nicht vermutet: Hintergrund kurz auf Rot gesetzt und
     fotografiert — 136 von 140 Messpunkten hinter Safaris Werkzeugen waren
     rot. Also unser Hintergrund, kein fremdes Element und kein Material von
     Safari. Baki hatte von Anfang an recht: „eigentlich müsste man links und
     rechts und über und unter der domain bar den inhalt der seite sehen."

     Gegen seitliches Verschieben braucht es die Zeile nicht: Abnahmepunkt 3
     misst bei 320, 390, 768, 1024, 1440 und 1920 px, ob `scrollWidth` über
     `clientWidth` liegt, und ist grün. Wo nichts übersteht, muss auch nichts
     abgeschnitten werden. */
  html, body {
    height: auto; min-height: 100%;
    overflow: visible;
  }

  /* ── Woher Safari die Farbe seiner Leisten wirklich nimmt ─────────────
     NICHT aus `theme-color`. Safari 26 liest das <meta> zwar noch, benutzt
     den Wert aber nicht mehr. Es sucht stattdessen FEST oder HAFTEND
     stehende Elemente am Bildschirmrand und nimmt deren
     `background-color`; ist dort nichts Deckendes, faellt es auf die
     `background-color` von body zurueck und danach auf die von html.

     Nachgemessen bei 390 px (berechnete Werte, Chrome — die Kaskade ist
     dieselbe, es geht um die Werte, nicht ums Zeichnen):

       .schiene  (position: fixed, bottom: 0)   rgba(0,0,0,0)
       body                                     rgba(0,0,0,0)
       html                                     rgb(168,171,171)  = #a8abab

     Der fest stehende Kasten am unteren Rand ist die Schiene, und die ist
     absichtlich durchsichtig — die sichtbare Kapsel ist ihr KIND, das
     zaehlt fuer Safari nicht. body ist ebenfalls durchsichtig, weil die
     Kurzschreibweise `background: linear-gradient(…)` die Farbe auf ihren
     Anfangswert zuruecksetzt. Also landet Safari bei html: #a8abab, dem
     Untergrundton. Die Karten sind #eceeef. Genau diese Differenz ist der
     graue Balken, den Baki unten sieht — und er ist messbar dunkler, nicht
     Safaris eigenes Grau.

     Beide Zeilen sind noetig, nicht nur die zweite: Safari fragt body vor
     html, und ein durchsichtiger body soll die Frage nicht weiterreichen.

     Sichtbar aendert sich dadurch nichts. Der Verlauf liegt als
     background-image DARUEBER und deckt die Farbe vollstaendig; sie wird
     nur dort wirksam, wo gar nichts gezeichnet wird — im Ueberrollbereich
     und eben in Safaris Leisten.

     `theme-color` bleibt im <head> stehen: Chrome auf Android und iOS vor
     26 lesen es weiterhin, und es steht bereits auf demselben Ton. */
  /* Der Verlauf muss WEG, nicht nur untermalt werden.
     Safari 26 faerbt seine Leisten nach dem, was am Bildschirmrand
     GEZEICHNET wird — nicht nach `theme-color` und nicht nach einer
     `background-color`, die unter einem Bild liegt. `body` traegt
     `background: linear-gradient(…)`; das ist ein Bild und deckt die Farbe
     ab. Gesetzt war sie also, gesehen hat Safari sie nie: der Balken blieb
     #a8abab, das untere Ende des Verlaufs.

     Auf dem Telefon ist der Verlauf ohnehin nur in dem schmalen Streifen
     hinter der Fussleiste zu sehen — die Karten gehen bis an die Kante.
     Ein Verlauf, den man nicht sieht, der aber die Leistenfarbe bestimmt,
     ist genau die falsche Reihenfolge. */
  /* Der KARTENTON als Grundfarbe — nach zwei gemessenen Irrwegen:

     `transparent` war falsch: zeichnet die Seite dort nichts, malt Safari
     sein eigenes Standardgrau unter das Material. Dunkler als alles auf
     der Seite, der Balken wurde SICHTBARER.

     Woher das Grau am Listenende kommt: Safaris Leiste zeigt das, was die
     Seite HINTER ihr zeichnet. Mitten in der Liste sind das die Zeilen —
     nachgewiesen, „AMAZON EU S.à.R.L." lief hinter der Leiste durch. Ganz
     unten, nach der letzten Zeile, gibt es keinen Inhalt mehr; dort zeigt
     die Leiste zwangslaeufig den Seitengrund. Das kann keine Seite der Welt
     vermeiden — auch Bakis Beispiel zeigt dort seinen eigenen Grund, der
     ist nur dunkel und faellt deshalb nicht als Balken auf.

     Mit dem Kartenton ist der Grund von den Karten nicht zu unterscheiden:
     kein Absatz, kein Balken — die Flaeche gehoert sichtbar zur Seite. */
  html, body {
    background-image: none;
    background-color: var(--glas-fest);
  }

  /* ── Das Grundgerüst ──────────────────────────────────────────────────
     Eine Spalte, und die Seite rollt wieder normal. `height: 100vh` mit
     innen rollenden Flächen ist ein Desktop-Muster; auf dem Telefon kämpft
     es gegen die ein- und ausfahrende Adressleiste. */
  .buehne {
    display: block;
    height: auto; min-height: 100svh;
    /* KEIN Rand links, rechts und oben.
       Der Untergrund der Anwendung ist --grund (#b9bbbb). Am Schirm ist das
       die Flaeche, auf der die Glaskarten liegen — dort hat sie Platz und
       einen Sinn. Auf einem Telefon von 402 px blieb davon ein 12 px
       breiter grauer Streifen ringsum, und genau so sah es auch aus: ein
       Rahmen um die Seite. Baki: „so einen fetten haesslichen Rand".
       Die Karten gehen jetzt bis an die Kante; der Untergrund erscheint nur
       noch als schmale Fuge ZWISCHEN den Karten, wo er die Trennung macht.

       Unten bleiben 78 px: die Kapsel ist 57 hoch (5 + 46 + 6), darunter
       8 px Luft und darunter die Safe-Area. Bleiben 13 px Abstand zwischen
       Inhalt und Leiste. */
    /* Oben die Safe-Area, seit `viewport-fit=cover` gesetzt ist.
       Im Browser ist der Wert 0 — dort hält Safari den Bereich selbst frei.
       Auf dem Home-Bildschirm gibt es keine Browserleiste mehr, und ohne
       diese Zeile läge die Mandantenkarte unter der Dynamic Island. */
    /* Kein Innenabstand unten. Auf Ansage: „DANN MACH DEINEN SCHEISS INNEN
       ABSTAND WEG". Der Abstand hielt die letzte Zeile über der schwebenden
       Kapsel frei — dafür reserviert er aber eine Fläche, hinter der nie
       Inhalt liegen kann, und genau die war unten zu sehen.
       Preis, ausgesprochen: ganz nach unten gescrollt liegt die letzte Zeile
       hinter der Kapsel. Dafür zieht der Inhalt jetzt bis an die Kante. */
    padding: env(safe-area-inset-top) 0 0;
    gap: 0;
  }
  .buehne.ohne-leiste { display: block; }

  /* ── Die zwei Zierkreise gehen auf dem Telefon aus ─────────────────────
     `body::before` und `body::after` sind fest positionierte Kreise von
     780×620 und 900×700 px mit `filter: blur(90px)`. Am Schirm geben sie
     dem Milchglas etwas zum Durchscheinen.

     Auf dem Telefon leisten sie NICHTS: dort ist backdrop-filter überall
     abgeschaltet, es gibt also kein Milchglas, durch das etwas scheinen
     könnte. Sie kosten nur zwei bildschirmfüllende Weichzeichner-Ebenen.

     Sie waren einmal als Verursacher des schwarzen Klotzes verdächtigt.
     Das war falsch — der Klotz kam aus der Sprechblase in app.html, siehe
     dort. Die Kreise bleiben trotzdem aus, aus dem Grund darüber. */
  body::before, body::after { display: none; }

  /* ── Die Schiene wird zur Leiste unten ────────────────────────────────
     Unten, weil dort der Daumen ist. Fest stehend, weil Navigation nicht
     weggescrollt werden darf. */
  .buehne > .schiene {
    /* NICHT an der Bildschirmkante. Das ist der im Vergleich gefundene
       Unterschied zu Seiten, bei denen der Inhalt durch Safaris Leiste
       scheint: dieselbe Referenzseite im selben Simulator, selber
       Ruhezustand — dort läuft der Inhalt hinter der Leiste durch, bei uns
       stand ein grauer Balken. Die Referenz hat KEIN fest positioniertes
       Element, das die untere Kante berührt; bei uns lag dort die Schiene
       über die volle Breite. Safari nimmt das kantenberührende fixe Element
       als Farbquelle für seine Leiste — war es durchsichtig, malte Safari
       sein Standardgrau, war es gefärbt, einen Balken.

       Jetzt endet die Schiene 8 px über der Safe-Area und beginnt 10 px vom
       Rand: kein fixes Element berührt die Kante, Safari zeigt den
       Seiteninhalt. Die Luft ringsum ist damit Positionierung, nicht mehr
       Innenabstand. */
    position: fixed; z-index: 40;
    left: 10px; right: 10px;
    bottom: calc(8px + env(safe-area-inset-bottom));
    margin: 0; height: auto;
    /* `min-width: 0` ist hier nicht kosmetisch: ohne die Zeile nimmt der
       Flex-Kasten die Breite SEINES INHALTS als Untergrenze. Gemessen waren
       das 473 px bei 390 px Bildschirm — die ganze Seite liess sich dadurch
       seitlich schieben, obwohl kein einzelnes Element sichtbar hinausragte.
       Der Verursacher war die Fussleiste selbst. */
    min-width: 0; max-width: 100vw;
    flex-direction: row;
    padding: 0;
    /* KEINE eigene Flaeche. Die Kapsel schwebt, und um sie herum muss der
       Inhalt durchziehen — links, rechts, ueber und unter ihr.

       Hier stand eine Hintergrundfarbe, weil Safari seine untere Leiste
       auch nach dem fest stehenden Element am Bildschirmrand faerbt: mit
       Farbe kam sie auf 233 statt 190 von 238. Ich habe dazugeschrieben,
       die Flaeche sei „unsichtbar". Sie war es nicht. Baki: „unter der home
       bar ist doch dieser durchgehende balken noch … eigentlich muesste man
       links und rechts und ueber und unter der domain bar den inhalt der
       seite sehen."

       Er hat recht. Die Flaeche verdeckte genau den Inhalt, den das Glas
       zeigen sollte — ich hatte einen sichtbaren Balken gegen eine hellere
       Browserleiste getauscht und den Tausch nicht als Tausch benannt.

       Der Grund faellt ohnehin weg: ueber den Home-Bildschirm gestartet hat
       die App keine Safari-Leiste mehr, die einzufaerben waere. Bleibt in
       Safari die Leiste etwas dunkler — dafuer schwebt die Kapsel wirklich. */
    /* Der Zeiger geht durch den Rand hindurch zum Inhalt darunter; nur die
       Kapsel selbst faengt ihn wieder ein (.schiene-block). */
    pointer-events: none;
  }
  /* 94 px hoch war sie: 48 Symbol + 12 Polster + 34 Safe-Area. Baki: „Die
     Bar unten ist fett ohne Ende." Stimmt — das ist ein Neuntel des
     Bildschirms für sechs Symbole. Jetzt 44 + 8 + Safe-Area = 86 px, davon
     34 unvermeidlich (dort sitzt der Home-Balken des Geräts). */
  /* ── Die Fussleiste als schwebendes Glas ────────────────────────────
     Vorher: ein schwarzer Balken ueber die volle Breite, fuenf graue
     Symbole ohne Beschriftung, der aktive Eintrag ein grauer Klotz. Auf
     dem Geraet fotografiert und von Baki so benannt: haesslich.

     Jetzt eine freistehende Kapsel mit Milchglas darunter. Das ist Apples
     eigene Loesung fuer genau diese Stelle, und sie loest hier zwei Dinge
     auf einmal: der Inhalt scheint durch, also sieht man beim Rollen, dass
     unter der Leiste weitergeht — und die Leiste gehoert sichtbar zur
     Oberflaeche und nicht zum Geraet.

     ZU DEN RUNDEN ECKEN: die ganze Anwendung hat --r-gross/-mittel/-klein
     auf 0, also rechte Winkel. Diese eine Flaeche bricht das bewusst. Sie
     ist das einzige Element, das ueber dem Inhalt SCHWEBT; eine
     rechtwinklige schwebende Platte sieht aus wie ein Fehler im Layout,
     eine Kapsel sieht aus wie ein Bedienelement. Zweitens ist es die eine
     Stelle, an der das Geraet selbst rundet — der Bildschirm hat dort
     seine eigene Ecke.

     Der Zeiger geht durch die aussere Schiene hindurch (pointer-events),
     damit die 10 px Luft links und rechts nicht ein Streifen sind, in dem
     Tipper verschwinden. */
  /* Wortmarke, Trenner, Abstandhalter und Griff gehoeren nicht in eine
     Fussleiste — sie stehen oben im Kopf der Seite. Diese Zeile ist beim
     Umbau der Leiste einmal verlorengegangen; danach stand das AGA-Zeichen
     mitten zwischen den Reitern und hat einen davon hinausgedrueckt. */
  .schiene .marke, .schiene .trenner, .schiene .schub,
  .schiene .griff { display: none; }

  .schiene-block {
    pointer-events: auto;
    flex: 1 1 auto; min-width: 0;
    flex-direction: row; justify-content: space-between;
    align-items: center; gap: 4px;
    padding: 5px;
    /* Kapselform: der Radius ist die halbe Hoehe, nicht ein fester Wert —
       so bleibt es eine Kapsel, egal wie hoch die Leiste einmal wird. */
    border-radius: 999px;
    /* Echte Transparenz. 45 % statt 72 %: bei 72 % war es eine weisse
       Platte mit einem Hauch Durchblick, und genau das hat gefehlt. Der
       Inhalt soll darunter erkennbar durchziehen, wenn man rollt.
       saturate(200%) ist nicht Zierde: Blur allein wäscht die Farben aus,
       die Saettigung holt sie zurueck — das ist der Unterschied zwischen
       Milchglas und grauem Schleier. */
    /* 28 % Weiss, nicht 45 %.
       Baki: „null komma null transparent." Er hat recht gehabt, und die
       Ursache lag nicht an der Zahl allein: hinter der Leiste liegt eine
       fast weisse Karte (#f7f7f8). 45 % Weiss mit Blur ueber Weiss ergibt
       Weiss — es war nichts durchzusehen. Bei der Vorlage aus Instagram
       liegt dort ein Foto.
       Bei 28 % zeichnen sich die Zeilentrenner und die Betraege dahinter
       als weiche Schemen ab, und man sieht beim Rollen, dass es weitergeht.
       Weiter herunter geht nicht: die Symbole stehen dann auf wechselndem
       Grund, und der Kontrast haengt davon ab, welche Zeile gerade
       durchlaeuft.
       Der Blur bleibt bei 30 — er ist es, der aus Text Schemen macht statt
       aus Text lesbaren Text unter dem Symbol. */
    /* Ein kuehler Ton, nicht reines Weiss.
       Nachgemessen: hinter der Leiste liegt die Karte des Kontoauszugs mit
       #f7f7f8 (Helligkeit 247). Weisses Glas darauf ergibt 247 — die
       Scheibe war rechnerisch durchsichtig und optisch nicht vorhanden.
       Auf einer hellen Seite entsteht der Glaseindruck nicht durch
       Durchsicht, sondern durch den Unterschied zum Untergrund: eine Scheibe
       ist etwas kuehler und etwas dunkler als das, worauf sie liegt, und
       hat einen hellen Rand. Genau das macht diese Zeile.
       Wo doch etwas dahinterlaeuft — beim Rollen ziehen die Zeilen darunter
       durch — bleibt es echtes Glas: 62 % lassen 38 % des verwaschenen
       Untergrunds durch. */
    /* KEIN backdrop-filter.
       Hier stand, der Filter sei die Ursache des schwarzen Klotzes. Das war
       die dritte falsche Vermutung. Der Klotz kam aus der Sprechblase
       (`.tab::after`) in app.html — nachgestellt, gemessen, behoben; die
       Erklaerung steht dort.

       Der Filter bleibt trotzdem erst einmal draussen: er ist zusammen mit
       vier weiteren Aenderungen ausgeliefert worden, und wer ihn
       zurueckholt, soll das in einem eigenen Schritt tun und einzeln
       nachsehen. Was heute steht, ist eine leicht durchscheinende Scheibe
       mit hellem Rand — das Auge erkennt Glas ohnehin am Rand und am
       Tonunterschied und nicht an der Unschaerfe. */
    background: var(--fussleiste);
    /* Die Kante traegt das Glas, wenn die Flaeche selbst kaum noch etwas
       traegt: aussen ein heller Rand, innen oben ein Lichtstrich. */
    border: 1px solid rgba(var(--hell-rgb),.7);
    /* EIN weicher Schatten statt zwei.
       Vorher lagen hier `0 10px 30px` UND ein enger `0 2px 8px` plus eine
       zweite innere Lichtkante unten. Der enge Schatten zeichnete direkt
       unter der Kapselkante eine schmale dunkle Zone — auf dem Geraet las
       sich das als durchgezogene Linie, nicht als Schweben. Baki hat es
       richtig vermutet: „ich denke du musst den schatten der home bar
       ueberarbeiten."
       Jetzt: nur die grosse, weiche Komponente, weiter gestreut (40 statt
       30) und leiser (.12 statt .18), mit 12 px Abstand, damit die
       dunkelste Stelle nicht an der Kante klebt. Die untere Lichtkante
       faellt weg — sie hat die Linie mitgezeichnet. */
    /* GAR KEIN Wurfschatten mehr. Die weiche Fassung (.12, 40 px) war
       immer noch als grauer Hof rund um die Kapsel zu sehen — Baki:
       „schatten ist noch da!!!!". Die Kapsel trennt sich jetzt allein
       über Rand und Lichtkante vom Inhalt; auf einer durchscheinenden
       Flaeche reicht das, und ein Hof gehoert da ohnehin nicht hin. */
    box-shadow: inset 0 1px 0 rgba(var(--hell-rgb),.85);
  }

  /* ── Eintraege: nur Symbole ────────────────────────────────────────────
     Nach der Vorlage, die Baki geschickt hat. Beschriftet ist nur der
     AKTIVE Eintrag, und zwar in der Pille neben seinem Symbol.

     Warum nicht ganz ohne Wort, wie in der Vorlage: dort sind es Haus,
     Film, Papierflieger, Lupe und ein Profilbild — Zeichen, die jeder
     kennt. Hier stehen ein Regal fuer den Kontoauszug und ein Wuerfel fuer
     die Buchungen. Das errät niemand. Das Wort am aktiven Eintrag kostet
     keine Flaeche (die Pille waechst ohnehin) und sagt beim Ankommen, wo
     man ist. */
  .schiene .tabs {
    flex-direction: row; justify-content: space-between;
    overflow: visible; gap: 2px; flex: 4 1 auto; min-width: 0;
    -webkit-mask-image: none; mask-image: none;
  }
  /* ── 15.08.2026: jeder Reiter traegt sein Wort ─────────────────────────
     Der Kommentar darueber sagte es schon selbst — „ein Regal fuer den
     Kontoauszug und ein Wuerfel fuer die Buchungen, das erraet niemand" —
     und die damalige Antwort war, nur den AKTIVEN Eintrag zu beschriften.
     Baki: „Bei manchen Icons hab ich das Gefuehl, dass man daraus nicht
     schliessen kann, was es ist."
     Er hat recht, und zwar genau hier: zu wissen, wo man IST, sagt nichts
     darueber, wohin die anderen fuehren. Und zwei der Symbole sind
     einander so aehnlich (Rechnungen und Belege sind beide ein Blatt),
     dass auch ein geuebtes Auge sie verwechselt.
     Jetzt Symbol und Wort untereinander — die Reiterleiste, die jedes
     Telefon hat. */
  .schiene .tab, .schiene .zahnrad {
    /* `flex: 1 1 0` statt `1 1 46px`: sonst bekommt der aktive Eintrag mehr
       Platz als die anderen und „Rechnungen" bzw. „Einstellungen" werden
       abgeschnitten. Gemessen: 72 px fuer den aktiven, 58 fuer die uebrigen,
       zwei Woerter beschnitten. Gleiche Breite fuer alle loest beides. */
    width: auto; height: 46px; flex: 1 1 0; min-width: 0;
    display: flex; flex-direction: column;
    align-items: center; justify-content: center; gap: 2px;
    padding: 0 2px;
    border-radius: 999px;
    color: var(--tinte);
    background: transparent; box-shadow: none;
    /* KEIN transition. Begruendet war das mit dem schwarzen Klotz; der kam
       in Wahrheit aus der Sprechblase in app.html und hat mit Animationen
       nichts zu tun. Ohne Uebergang bleibt es trotzdem: eine Pille, die
       ihre Breite animiert, rechnet bei jedem Bild das Layout der ganzen
       Leiste neu, und die vier Nachbarn zucken dabei mit. Der harte Wechsel
       ist hier der ruhigere. */
  }

  /* Die Sprechblase aus app.html gehoert nicht in die Fussleiste.
     Sie zeigt nach RECHTS — in der senkrechten Schiene ist dort Platz, in
     der waagerechten Leiste steht dort der naechste Eintrag. Auf dem
     Telefon greift sie ohnehin nicht (sie haengt an
     `hover: hover and pointer: fine`), wohl aber an einem iPad mit Maus in
     einem schmalen Fenster. Und noetig ist sie hier nicht: der Name des
     aktiven Eintrags steht sichtbar in der Pille. */
  .schiene .tab::after, .schiene .zahnrad::after { content: none; }

  .schiene .tab svg, .schiene .zahnrad svg { width: 22px; height: 22px; flex: none; }

  /* Das Wort steht nur am aktiven Eintrag. */
  /* ── Die Einstellungen verlassen die Fussleiste ───────────────────────
     Baki: „dadurch dass es 6 icons in der bar auf mobile sind sieht das ein
     bisschen kacke aus. leg die einstellungen wo anders hin auf mobile.
     immer rechts oben oder so."

     Er hat recht, und es loest zwei Dinge auf einmal. Sechs Ziele in einer
     Reiterleiste sind eines mehr, als ein Telefon traegt — und „Einstellungen"
     war das einzige Wort, das nicht passte. Ich hatte das mit einem
     Kurzwort („Profil") ueberklebt; das war eine Behandlung des Symptoms.

     Jetzt steht das Zahnrad oben rechts, wo es in jeder App steht, und die
     Leiste unten traegt genau die vier Orte, zwischen denen man waehrend
     der Arbeit wechselt — plus das Plus. */
  .schiene .zahnrad {
    position: fixed; top: max(10px, env(safe-area-inset-top)); right: 12px;
    z-index: 60;
    /* DUNKLES Symbol. `.zahnrad` erbt `color: rgba(255,255,255,.5)` — das ist
       fuer die dunkle Schiene am Schirm gedacht. Am Telefon steht es als
       WEISSER Kreis auf hellem Grund, und ein halbdurchsichtiges Weiss darauf
       ist unsichtbar. Baki, mit gelbem Kreis im Foto: „der button rechts oben
       funktioniert nicht settings. und man sieht ihn nicht." Er funktionierte
       — man sah ihn nur nicht. */
    color: var(--tinte);
    /* `min-height` aus der Schirmfassung wuerde daraus ein Oval machen:
       gemessen 40 x 56. Ein Kreis muss beide Masse gesetzt bekommen. */
    width: 40px; height: 40px; min-width: 40px; min-height: 40px;
    padding: 0; flex: none; gap: 0;
    border-radius: 999px;
    background: rgba(var(--hell-rgb),.82);
    border: 1px solid rgba(var(--tinte-rgb),.10);
    box-shadow: 0 2px 10px rgba(0,0,0,.10);
    backdrop-filter: saturate(140%) blur(12px);
    -webkit-backdrop-filter: saturate(140%) blur(12px);
  }
  .schiene .zahnrad[aria-current="page"] {
    background: var(--tinte); color: #fff;
  }
  .schiene .zahnrad[aria-current="page"] svg { stroke: #fff; }
  /* Es steht allein und traegt deshalb kein Wort — ein Zahnrad ist das eine
     Zeichen, das jeder kennt, und daneben steht nichts, mit dem man es
     verwechseln koennte. */
  .schiene .zahnrad .tab-wort { display: none; }
  .schiene .tab-wort {
    display: block; margin: 0;
    /* Siehe `.tab-wort` oben: bei 9 px braucht die Schrift 10 px, 1.05 gibt
       ihr 9,44. Der Umlaut wurde dadurch abgeschnitten. */
    font-size: 9px; line-height: 1.35; letter-spacing: -.02em;
    max-width: 100%; overflow: hidden; text-overflow: ellipsis;
    white-space: nowrap; text-align: center;
  }
  /* Der aktive Eintrag traegt sein Wort fetter — die Pille ist damit immer
     noch erkennbar, ohne dass die anderen stumm bleiben. */
  .schiene .tab[aria-current="page"] .tab-wort,
  .schiene .zahnrad[aria-current="page"] .tab-wort {
    font-weight: 600;
  }
  /* Die Pille. Heller als die Leiste, nicht farbiger — so wie in der
     Vorlage. Die Akzentfarbe traegt das Symbol, nicht die Flaeche. */
  .schiene .tab[aria-current="page"],
  .schiene .zahnrad[aria-current="page"] {
    flex: 0 0 auto; padding: 0 14px 0 12px;
    color: var(--akzent);
    /* Die Pille bleibt deckender als die Leiste — sonst verschwimmt der
       aktive Eintrag mit dem, was gerade dahinter durchlaeuft. Der
       Unterschied zwischen 28 % und 78 % IST die Markierung. */
    background: rgba(var(--hell-rgb),.78);
    /* Kein Schatten mehr — siehe die Begruendung oben. Die Pille traegt
       sich ueber die Flaeche: 78 % gegen 28 % der Leiste. Das reicht. */
    box-shadow: none;
  }
  /* ── Rückmeldung beim Antippen: KEIN transform ────────────────────────
     Hier stand `transform: scale(.93)`, und hier stand auch die zweite
     falsche Erklärung des schwarzen Klotzes. Der Klotz kam aus der
     Sprechblase in app.html.

     Die Rückmeldung bleibt trotzdem so, wie sie jetzt ist: die Fläche wird
     kurz kräftiger, statt zu schrumpfen. Eine schrumpfende Pille zieht die
     vier Nachbarn mit, weil alle im selben Flex-Kasten liegen.
     `-webkit-tap-highlight-color` muss dabei bleiben, sonst legt iOS
     zusätzlich sein eigenes graues Rechteck darüber. */
  .schiene .tab, .schiene .zahnrad { -webkit-tap-highlight-color: transparent; }
  .schiene .tab:active, .schiene .zahnrad:active {
    background: rgba(var(--hell-rgb),.85);
  }
  .schiene .tab[aria-current="page"]:active,
  .schiene .zahnrad[aria-current="page"]:active {
    background: rgba(var(--hell-rgb),.95);
  }

  /* ── Die Kontextleiste wird zum Kopf ──────────────────────────────────
     Voll breit über dem Inhalt statt daneben. Der Mandantenwechsel bleibt
     damit da, wo Baki ihn verlangt hat: immer erreichbar, oben. */
  .buehne > .leiste {
    display: block;              /* gegen ein früheres `display: none` */
    position: static; width: auto; max-width: none;
    /* Die Fuge zwischen Kopf und Inhalt bleibt — sie trennt zwei Karten.
       Der Rand ringsum faellt weg, siehe .buehne. */
    margin: 0 0 8px; padding: 12px;
    max-height: none; overflow: visible;
    opacity: 1; visibility: visible;
  }
  /* Eingeklappt gibt es auf dem Telefon nicht — es gibt keine zweite Spalte,
     die dadurch breiter würde. Der Griff ist oben schon ausgeblendet. */
  .buehne.leiste-zu > .leiste {
    opacity: 1; visibility: visible; pointer-events: auto;
  }
  .buehne.leiste-zu { --leiste-breite: auto; --leiste-luecke: 0px; }

  /* ── Der Kopf kostet Platz, den die Liste braucht ─────────────────────
     Gemessen im Kontoauszug bei 390×844: bis zur ersten Buchungszeile gingen
     über 500 der 844 Punkte drauf — sichtbar blieben drei Zeilen. Auf einem
     Schreibtisch ist derselbe Kopf richtig; dort ist er ein Zwanzigstel der
     Höhe, hier zwei Drittel.

     Also alles im Kopf eine Stufe kleiner: Kürzel 46 → 34 px, Polster der
     Kontextpunkte 13 → 8 px, und die zweite Zeile eines Punktes („7
     Buchungen · 1 mit Beleg") faellt weg — sie steht in der Zahl daneben
     schon. Das bringt gemessene ~150 px zurück, also vier Zeilen mehr. */
  .leiste .konto { margin-bottom: 10px; gap: 10px; }
  .leiste .konto .bild { width: 34px; height: 34px; font-size: 13px; }
  .leiste .konto .name { font-size: 14.5px; }
  .leiste .konto .zeile2 { font-size: 11.5px; }
  .leiste-mandant { padding: 0 0 10px; margin-bottom: 10px; }

  .leiste-inhalt .punkt { padding: 8px 11px; gap: 8px; }
  .leiste-inhalt .punkt small,
  .leiste-inhalt .punkt .unter { display: none; }
  .leiste-inhalt .rubrik { font-size: 11px; }

  /* Die Kacheln über der Liste: 80 px sind zwei Buchungszeilen. */
  .lagechip { padding: 7px 12px; min-width: 88px; }
  .lagechip .wert { font-size: 22px; }
  .lagechip .text { font-size: 12px; }

  /* Kontextpunkte nebeneinander statt untereinander: sechs Monate als Liste
     schöben den Inhalt vom Bildschirm. Als rollende Reihe kosten sie eine
     Zeile. */
  /* `nowrap` ausdruecklich, sonst gewinnt das `wrap` aus der 1180er-Regel:
     dann bricht die Reihe um, und ein EINZELNER langer Eintrag — etwa
     „Sakmani Lamaso Kiosk/ kons.4187" in der Belegansicht — schiebt die
     Seite trotzdem auf 473 px. Genau das hat die Probe gemeldet. Deshalb
     zusaetzlich eine Obergrenze je Eintrag: was laenger ist, wird gekuerzt,
     statt den Bildschirm zu sprengen. */
  .leiste-inhalt {
    /* Siehe oben: eine gemeinsame Mittellinie fuer alle Gruppen. */
    display: flex; flex-direction: row; flex-wrap: nowrap; gap: 8px;
    align-items: center;
    min-width: 0; max-width: 100%;
    overflow-x: auto; overflow-y: hidden;
    padding-bottom: 4px;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  .leiste-inhalt .punkt { max-width: 74vw; }
  .leiste-inhalt .punkt .text {
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .leiste-inhalt::-webkit-scrollbar { display: none; }
  .leiste-inhalt .gruppe {
    /* Siehe oben: feste Hoehe statt Dehnung. */
    display: flex; flex-direction: row; flex-wrap: nowrap; gap: 8px;
    align-items: center; flex: none;
    height: 44px; align-self: center;
  }
  .leiste-inhalt .rubrik {
    margin: 0; padding: 0 4px 0 0; white-space: nowrap; flex: none;
  }
  .leiste-inhalt .punkt {
    /* FESTE Hoehe, nicht `min-height`. Gemessen am 15.08.: die Gruppe
       „Zugang" war 69 px hoch, „Abschnitt" 44 — eine Kachel darin lief auf
       zwei Zeilen. Beide Gruppen werden mittig gesetzt, also sitzen ihre
       44-px-Kacheln danach auf verschiedenen Hoehen. Baki, mit gelbem Kreis
       im Foto: „zugang ist auch verschoben."
       Mit fester Hoehe ist jede Gruppe genau so hoch wie ihre Kacheln, und
       eine gemeinsame Linie ergibt sich von selbst. Was nicht hineinpasst,
       wird gekuerzt — dafuer steht `text-overflow: ellipsis` am `.text`. */
    flex: none; white-space: nowrap;
    height: 44px; min-height: 44px;
    display: flex; align-items: center; align-self: center;
    overflow: hidden;
    border: 1px solid rgba(var(--tinte-rgb),.14);
  }
  .leiste-inhalt:empty { display: none; }

  /* ── Der Inhalt ───────────────────────────────────────────────────────
     `.haupt` hat 36 px Innenabstand je Seite. Auf dem Schreibtisch ist das
     der Rahmen, der die Flaeche atmen laesst; auf 390 px sind es 72 von 366
     verfuegbaren Punkten — ein Fuenftel des Bildschirms fuer nichts. Die
     Probe hat es als „Inhalt 292 px breit" gemeldet.

     `overflow: hidden` muss hier ebenfalls weg: es stammt aus dem
     Schreibtischlayout, wo innen einzelne Flaechen rollen. Auf dem Telefon
     rollt die Seite, und was ueber die Hoehe hinausgeht, waere sonst
     abgeschnitten statt erreichbar. */
  .buehne > main, .haupt {
    width: auto; min-width: 0;
    padding: 16px 14px;
    overflow: visible;
  }
  h1, .titelzeile h1 { font-size: 26px; }
  h2 { font-size: 19px; margin-top: 20px; }
  .kopfreihe { flex-wrap: wrap; gap: 10px; }

  /* ── Felderreihen stapeln ─────────────────────────────────────────────
     Vier Felder nebeneinander sind auf 390 px vier Felder von 80 px. */
  .filterzeile { flex-direction: column; align-items: stretch; gap: 10px; }
  .filterzeile .mandantwahl,
  .filterzeile .mandatensuche { width: 100%; flex: none; }
  .mandantwahl .wahlfeld[type="text"] { min-width: 0; width: 100%; }
  .wahlfeld { width: 100%; }
  /* 16 px verhindert, dass iOS beim Antippen hineinzoomt.
     44 px Hoehe, weil 36 px Grundhoehe plus Polster auf 39 kamen — einen
     Punkt unter der Tippschwelle. Gemessen, nicht geschaetzt. */
  .wahlfeld, .suchfeld, .kontofeld, input, select, textarea { font-size: 16px; }
  .wahlfeld, .suchfeld, .filterzeile .mandatensuche .suchfeld,
  .leiste-mandant .wahlfeld { min-height: 44px; }

  /* `.mandatensuche .suchfeld` traegt `flex: 1 1 260px`. In einer Reihe ist
     das eine Mindestbreite; sobald ich den Kasten auf `column` gestellt
     habe, wurde daraus eine Mindest-HOEHE — das Suchfeld im Kontoauszug war
     gemessene 336×260 px, ein leerer Block ueber der halben Seite.
     Deshalb hier ausdruecklich zuruecknehmen. */
  /* Die Suchleiste bleibt oben stehen.
     Gemessen im Kontoauszug: die Seite ist 11.046 px hoch, und ab 600 px
     Rollen waren Suchfeld, Kachelband und Monatsleiste alle aus dem Bild.
     Wer bei Zeile 40 etwas sucht, musste 600 px zurück und danach dieselbe
     Strecke wieder vor. Ein Filter, den man nur am Anfang erreicht, ist auf
     einer langen Liste kein Filter.

     Nur die Suchleiste, nicht auch das Kachelband: zwei haftende Streifen
     übereinander nähmen ein Viertel des Bildschirms. Die Suche erreicht
     jede Zeile, die Kacheln sind vier Wischer entfernt. */
  .mandatensuche {
    position: sticky; top: 0; z-index: 20;
    background: var(--glas-fest, #eef0f0);
    padding: 8px 0; margin-top: 0;
    box-shadow: 0 6px 12px -8px rgba(0,0,0,.28);
  }
  .mandatensuche { flex-direction: column; align-items: stretch; }
  .mandatensuche .suchfeld {
    flex: none; width: 100%; min-width: 0; height: 44px;
  }
  .mandatensuche .trefferzahl { margin: 0; }
  .filterchips { overflow-x: auto; padding-bottom: 4px; scrollbar-width: none; }
  .filterchips::-webkit-scrollbar { display: none; }
  .filterchip { flex: none; min-height: 40px; }

  /* ── Tabellen ─────────────────────────────────────────────────────────
     Zehn Spalten passen nicht auf ein Telefon und sollen es auch nicht. Sie
     rollen seitwärts, in ihrem eigenen Kasten — die SEITE darf dabei nicht
     mitwandern, sonst verrutscht alles. */
  /* ── Innen rollen wird zu: die Seite rollt ────────────────────────────
     Auf dem Schreibtisch hat jede Liste ihren eigenen Rollbereich, damit
     Kopfzeile und Werkbank stehen bleiben. Dafuer braucht es eine feste
     Fensterhoehe, die sich nach unten durchreicht (`flex: 1; min-height: 0`).

     Auf dem Telefon gibt es diese Hoehe nicht — die Kette endete bei fast
     null, und die Buchungstabelle zeigte drei Zeilen, darunter grauer Rest.
     Zwei Rollbereiche ineinander sind dort ohnehin falsch: man weiss beim
     Wischen nie, welcher sich bewegt.

     Also: die inneren Bereiche wachsen mit ihrem Inhalt, und gerollt wird
     die Seite. Seitwaerts rollt weiterhin nur die Tabelle selbst. */
  /* `.tabelle.laeuft` traegt `flex: 1 1 0; min-height: 120px` (Spezifitaet
     0,2,0) und schlug meine Regel mit 0,1,0. Gemessen: Kasten 118 px hoch
     bei 1058 px Inhalt — zwei von 25 Buchungen sichtbar, obwohl darunter
     leerer Bildschirm lag. Deshalb hier BEIDE Waehler. */
  .tabelle, .tabelle.laeuft, .tabelle.dicht {
    overflow-x: auto; overflow-y: visible;
    -webkit-overflow-scrolling: touch;
    flex: none; height: auto; min-height: 0; max-height: none;
  }
  .tabelle table { min-width: 720px; }

  .dichteflaeche, .auszugflaeche { flex: none; min-height: 0; }

  /* Fuenf Spalten sind auf 336 px keine fuenf Spalten.
     Datum 62 + Name + Konto 58 + Zustand 132 + Betrag 106 plus vier Luecken
     ergeben 445 px feste Breite — gemessen, und genau so lief die Liste aus
     ihrem Kasten heraus.

     Auf dem Telefon wird daraus, was eine Telefonzeile ist: oben der Name,
     darunter die Nebensachen in einer Reihe, der Betrag rechts. Dieselben
     Angaben, andere Anordnung — nichts wird weggelassen. */
  .dichtezeile {
    display: flex; flex-wrap: wrap; align-items: baseline;
    column-gap: 10px; row-gap: 2px;
    padding: 9px 12px; min-height: 58px;
  }
  /* Erst eine Vorgabe fuer ALLE Zellen, dann die Ausnahmen.
     Die erste Fassung zaehlte die Zellen des Kontoauszugs auf (.tag, .konto,
     .zustand, .summe). Die Belegliste hat aber `.bdatum` statt `.konto` —
     ohne Reihenfolge landete sie auf 0, also VOR dem Namen, und aus der
     zweizeiligen Zeile wurde eine dreizeilige. Mit einer Vorgabe kann eine
     neue Zelle die Zeile nicht mehr aufbrechen. */
  /* Namenskollision, und eine teure.
     `.konto` ist in der Seitenleiste der Profilblock (Bild, Name, Zeile 2)
     und traegt dort `margin-bottom: 26px`. In der Buchungszeile heisst die
     Kontozelle GENAUSO. Am Schreibtisch fiel es nicht auf, weil die Zeile
     ein Raster ist und der Aussenabstand dort verpufft; auf dem Telefon ist
     sie umbrechendes Flex — und aus 26 px Abstand wird echte Zeilenhoehe.
     Gemessen: 86 px statt 60 px je Zeile, 3.102 px Rollstrecke ueber 122
     Zeilen, allein durch diese eine Zeile.
     (Der saubere Weg waere, die Zellklasse umzubenennen. Das beruehrt
     `zuordnenprobe.mjs` und `scrollprobe.mjs`, die darauf messen — deshalb
     hier erst der Riegel, die Umbenennung als eigener Schritt.) */
  .dichtezeile > .konto   { margin: 0; display: inline; }

  .dichtezeile > *        { order: 5; }
  .dichtezeile > .wer     { flex: 1 1 100%; order: 1; min-width: 0; }
  .dichtezeile > .tag     { order: 2; }
  .dichtezeile > .zustand { order: 8; }
  .dichtezeile > .summe   { order: 9; margin-left: auto; }
  .dichtezeile > .wer {
    display: flex; align-items: baseline; gap: 8px;
  }
  .dichtezeile > .wer .name {
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  /* Der Verwendungszweck faellt auf dem Telefon weg.
     Neben dem Namen blieben von ihm zwei abgeschnittene Wörter („ändung vom
     25.0…") — das ist keine Auskunft, das ist Rauschen. Vollständig steht er
     im Detail, das ein Antippen entfernt ist. */
  .dichtezeile > .wer .zweck { display: none; }

  /* In der Belegzeile stehen ZWEI Daten: Eingang und Belegdatum. Am
     Schreibtisch trennen sie zwei Spalten; auf dem Telefon stehen sie
     nebeneinander („06.08. 31.07.") und man weiss nicht, welches welches
     ist. Zwei Zahlen, von denen eine unklar ist, sind schlechter als eine
     klare — also bleibt das Belegdatum, und der Eingang steht im Detail,
     wo er ohnehin schon als „Eingang 06.08." beschriftet ist.
     Im KONTOAUSZUG bleibt `.tag` stehen: dort ist es der Buchungstag und
     das einzige Datum der Zeile. */
  .belegzeile > .tag { display: none; }
  .dichteliste, .auszug, .aufgaben, .befundliste, .lage-karten {
    overflow-y: visible; max-height: none; flex: none;
  }
  #buehnenteil, .ansicht { flex: none; min-height: 0; }
  main.haupt { min-height: 0; }

  /* ── Kontoauszug und Belege: Liste und Detail übereinander ────────────*/
  .auszugflaeche,
  .auszugflaeche:has(.auszugdetail.offen),
  .dichteflaeche,
  .dichteflaeche:has(.detailspalte.offen) {
    grid-template-columns: minmax(0, 1fr);
  }
  /* Ist ein Detail offen, gehört ihm der Bildschirm. Nebeneinander wären es
     zwei Spalten von 190 px. */
  .auszugdetail.offen, .detailspalte.offen {
    position: fixed; inset: 0; z-index: 50;
    margin: 0; border: none;
    padding-bottom: calc(78px + env(safe-area-inset-bottom));
    overflow-y: auto;
  }

  /* ── Die Mandantenkarte ───────────────────────────────────────────────
     Gemessen 270 px hoch — bei 230 Mandanten sieht man eineinhalb Karten
     und scrollt danach. Die Ursache war meine eigene erste Regel:
     `grid-template-columns: 1fr` stapelte die beiden Rubriken
     untereinander, jede mit Überschrift, grosser Zahl und Erläuterung.

     Auf dem Telefon gehört in eine Karte, wonach man sie sucht: der Name,
     die Nummer, und die zwei Zahlen, die die Arbeit beschreiben. Nebeneinander
     in einer Reihe, Überschrift klein davor. Aus 270 px werden ~110. */
  .kacheln { grid-template-columns: 1fr; }
  .lage-karte { padding: 11px 13px; }
  .lage-kopf { flex-wrap: wrap; gap: 4px 10px; }
  .lage-rubriken {
    display: flex; flex-direction: row; flex-wrap: wrap;
    gap: 6px 18px; margin-top: 6px;
  }
  .lage-rubrik { display: flex; align-items: baseline; gap: 7px; }
  .lage-rubrik h4 { margin: 0; font-size: 11px; }
  .lage-rubrik .gross { font-size: 17px; }
  /* Die Erläuterung („Zahlungen ohne Beleg") wiederholt die Überschrift
     („BELEGE") mit anderen Worten. Am Schreibtisch ist das Sorgfalt, auf
     dem Telefon sind es zwei Zeilen je Karte. */
  .lage-rubrik .leise { display: none; }
  .lage-karten { gap: 8px; }
  /* Die ganze Karte ist jetzt der Schalter — sie muss sich auch so
     anfühlen und beim Antippen antworten. */
  .lage-karte { cursor: pointer; }
  .lage-karte:active { background: rgba(var(--hell-rgb),.72); }
  .lage-karte:focus-visible {
    outline: 2px solid var(--akzent); outline-offset: 2px;
  }
  .lage-kopf { cursor: inherit; }
  /* Gleich hohe Karten: Name und Bankstand jeweils einzeilig. Vorher
     sprangen die Höhen um bis zu 49 px, je nachdem ob ein Name umbrach —
     eine Liste, die ausfranst, liest sich schlechter, obwohl in jeder Karte
     dasselbe steht. */
  .lage-kopf .name {
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    min-width: 0;
  }
  .lage-kopf .lauf { white-space: nowrap; }

  /* „Mandate" stand dreimal: als Unterzeile der Ansicht („… · 230
     Mandate"), als eigene Überschrift und als Hinweis darunter. 88 px, die
     nichts Neues sagen. Am Schreibtisch ist die Zwischenüberschrift eine
     Gliederung; auf dem Telefon, wo unter dem Titel ohnehin nichts anderes
     steht, ist sie Wiederholung. */
  main.haupt > h2:first-of-type,
  main.haupt > h2:first-of-type + .unterzeile { display: none; }

  /* Die Fläche reicht bis zur Fussleiste. Bei leerem Suchergebnis riss sie
     sonst mitten im Bild ab und darunter stand grauer Hintergrund. */
  main.haupt { min-height: calc(100svh - 92px - env(safe-area-inset-bottom)); }
  .arbeitsflaeche, .mandant-raster, .aus-raster { grid-template-columns: 1fr; }
  /* Die Werkbank darf nicht mit der Auswahl wachsen.
     Mit `flex: 1 1 auto` streckte sich jeder Knopf auf die volle Breite und
     bekam eine eigene Zeile: 54 px ohne Auswahl, 108 px mit einer, 162 px
     mit allen 25 — das Datenfenster schrumpfte dabei von 85 auf 78 px. Ein
     Bedienstreifen, der umso mehr Platz nimmt, je mehr man ausgewaehlt hat,
     arbeitet gegen den Benutzer. */
  .werkbank { flex-wrap: wrap; gap: 8px; }
  .werkbank .schub { display: none; }
  .werkbank .knopf { flex: 0 1 auto; min-height: 44px; }
  .werkbank .stand { flex: 1 1 100%; }

  /* Knöpfe sind Tippziele, nicht Klickziele. */
  .knopf, .belegknopf, .grundknopf, .fehltknopf, .artknopf { min-height: 44px; }

  /* Der Schliessknopf des Details ist auf dem Telefon der EINZIGE Ausweg:
     bei offenem Detail steht die Liste dahinter auf `display: none`, es gibt
     also nichts anderes anzutippen. 34 px waren dafür zu klein. */
  .detailspalte .dschliessen {
    width: 44px; height: 44px; margin-right: -8px;
  }

  /* Die Kachelreihe über dem Kontoauszug rollt seitwärts.
     Sie war der Grund, warum die Auszugsseite 783 px breit wurde: fünf
     Kacheln nebeneinander, jede so breit wie ihr Text, in einem Raster ohne
     Umbruch. Gemessen mit `mobilprobe.mjs`, nicht geschätzt. */
  /* `overflow-x: auto` allein genuegt hier NICHT.
     Die Reihe steht in `#kopfrechts` innerhalb der Flex-Kopfzeile, und ein
     Flex-Kind waechst per Vorgabe auf seinen Inhalt (`min-width: auto`) —
     der Kasten wurde also so breit wie seine fuenf Kacheln und rollte nie,
     sondern schob die Seite auf 779 px. Erst `min-width: 0` laesst ihn
     kleiner werden als sein Inhalt, und dann greift das Rollen. */
  .kopfreihe > #kopfrechts, #kopfrechts { min-width: 0; max-width: 100%; }
  .lagechips, .kopflage, .lage-kacheln {
    display: flex; flex-wrap: nowrap;
    min-width: 0; max-width: 100%;
    overflow-x: auto; -webkit-overflow-scrolling: touch;
    padding-bottom: 4px; scrollbar-width: none;
  }
  .lagechips::-webkit-scrollbar, .kopflage::-webkit-scrollbar,
  .lage-kacheln::-webkit-scrollbar { display: none; }
  .lagechip { flex: none; min-height: 44px; }

  /* Ankreuzfelder: 15 px trifft man mit der Maus, nicht mit dem Daumen.
     Die Zelle bleibt schmal, das Feld selbst wird groß. */
  /* 24 px, nicht 22: das ist die Untergrenze aus WCAG 2.5.8, und mit 22
     war sie um zwei Punkte verfehlt. Gemessen, nicht geschätzt. */
  .tabelle input[type="checkbox"] {
    width: 24px; height: 24px;
  }
  .wahlspalte { padding: 0 4px; }
  /* Das Kontofeld in der Zeile: 33 px hoch war unter der Tippschwelle. */
  .tabelle td .kontofeld { min-height: 40px; width: 96px; }
}

/* Sehr schmal: 360 px lässt keinen Rand von 12 px mehr übrig, ohne dass
   Beträge umbrechen. */
@media (max-width: 380px) {
  .buehne { padding-left: 8px; padding-right: 8px; }
  .buehne > .leiste { padding: 10px; }
  h1, .titelzeile h1 { font-size: 23px; }
}

/* ── Beleg hinzufügen: Plus in der Fussleiste ─────────────────────────────
   Nur auf dem Telefon. Am Schirm gibt es den Upload an den Stellen, an
   denen er hingehoert — im Posteingang und an der Bankzeile. Ein Plus in
   der Seitenschiene waere dort ein zweiter Weg zum selben Ziel. */
/* Das Plus stand bis zum 15.08.2026 IN der Fussleiste, in der Mitte zwischen
   den Reitern. Baki: „Haben wir doch gesagt, dass in der Homebar unten nur
   fuenf Punkte sein sollen, dass symmetrisch sein soll. Das sieht absolut
   unsymmetrisch und haesslich aus."

   Fuenf Reiter lassen sich durch ein Element in der Mitte nicht symmetrisch
   teilen — zwei und drei geht nie auf. Es war ausserdem das einzige Element
   der Reihe, das keine Ansicht oeffnet. Es schwebt jetzt rechts darueber. */
.tab-plus { display: none; }
#belegPlusFelder { display: none; }

.belegblatt { position: fixed; inset: 0; z-index: 900; }
.belegblatt-schirm { position: absolute; inset: 0; background: rgba(0,0,0,.35); }
.belegblatt-karte {
  position: absolute; left: 12px; right: 12px; bottom: 12px;
  background: var(--flaeche-hoch); border-radius: 0; overflow: hidden;
  padding: 8px; display: flex; flex-direction: column; gap: 6px;
  box-shadow: 0 18px 50px rgba(0,0,0,.28);
  padding-bottom: calc(8px + env(safe-area-inset-bottom));
}
.belegblatt-wahl {
  display: flex; align-items: center; gap: 14px; width: 100%;
  /* 60 px, nicht 44: hier wird mit dem Daumen im Vorbeigehen getippt, oft
     einhaendig und in Bewegung. Das Mindestmass ist die Untergrenze fuer
     Erreichbarkeit, nicht das Ziel. */
  min-height: 60px; padding: 12px 16px;
  border: none; background: var(--flaeche-leise, #f4f4f5);
  border-radius: 0; font: inherit; color: inherit; text-align: left;
  cursor: pointer;
}
.belegblatt-wahl:active { background: rgba(var(--tinte-rgb),.09); }
.belegblatt-wahl span { display: flex; flex-direction: column; gap: 2px; }
.belegblatt-wahl strong { font-size: 16px; font-weight: 600; }
.belegblatt-wahl small { font-size: 13px; color: var(--tinte-leise, #6b6b6b); }
.belegblatt-abbruch {
  min-height: 52px; border: none; background: none; font: inherit;
  font-size: 16px; color: var(--tinte-leise, #6b6b6b); cursor: pointer;
}

@media (max-width: 900px) {
  /* Das Plus steht in der Mitte und ist die einzige gefuellte Flaeche der
     Leiste — genau ein hervorgehobenes Element, sonst hebt sich nichts ab. */
}

/* ── Das Blatt: Formular über der Arbeit ──────────────────────────────────
   Dieselbe Bewegung wie das Beleg-Plus: am Telefon von unten, am Schirm in
   der Mitte. Und dieselbe Form wie alles andere — rechteckig. Ein
   abgerundetes Formular über einer Liste aus geraden Kanten sieht aus wie
   von woanders. */
.blatt { position: fixed; inset: 0; z-index: 950; }

/* ── Das Burger-Menü: die Themenliste der Einstellungen ──────────────────
   Öffnet am Burger unten in der Schiene und listet, was sich einstellen
   lässt — gruppiert wie die Ansicht selbst, dazu Abmelden. Am Telefon
   fährt es wie das Blatt von unten hoch: dieselbe Geste, nicht zwei. */
.menue-schleier { position: fixed; inset: 0; z-index: 960;
  background: rgba(15,17,20,.35); }
.menue-karte {
  position: absolute; left: 78px; bottom: 14px;
  min-width: 264px; max-width: 340px; max-height: min(82vh, 680px);
  overflow: auto; padding: 8px 0;
  background: var(--glas-fest, #eceeef);
  border: 1px solid var(--glas-rand, rgba(var(--hell-rgb),.42));
  box-shadow: 0 24px 70px rgba(0,0,0,.30);
}
.menue-rubrik {
  padding: 12px 18px 5px; font-size: 12px; font-weight: 600;
  letter-spacing: .05em; text-transform: uppercase;
  color: var(--tinte-leise);
}
.menue-punkt {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; width: 100%; min-height: 44px; padding: 10px 18px;
  border: 0; background: none; font: inherit; font-size: 15px;
  color: var(--tinte); text-align: left; cursor: pointer;
}
.menue-punkt svg { color: var(--tinte-leise); flex: none; }
.menue-punkt:hover, .menue-punkt:focus-visible {
  background: rgba(var(--tinte-rgb),.06); outline: none;
}
.menue-punkt.gehen { color: var(--alarm); }
.menue-trenner { height: 1px; margin: 8px 0;
  background: rgba(var(--tinte-rgb),.12); }
@media (max-width: 860px) {
  .menue-karte {
    left: 0; right: 0; bottom: 0; max-width: none;
    max-height: 76vh; padding-bottom: max(8px, env(safe-area-inset-bottom));
  }
}

/* ── Der Verlauf: Einnahmen und Ausgaben je Monat ────────────────────────
   Spiegel-Balken: oben Einnahmen, unten Ausgaben — die Richtung trägt die
   Bedeutung, die Farbe verstärkt nur. Beide Hälften teilen sich EINE Skala.
   Dünne Balken mit Lücke, die Nulllinie ist die einzige Linie im Bild. */
.verlauf {
  display: flex; gap: 10px; align-items: stretch;
  margin: 6px 0 4px; padding: 0 2px;
}
.vmonat {
  flex: 1 1 0; min-width: 0;
  display: flex; flex-direction: column;
}
/* Feste Halbhoehen statt Gesamthoehe am Verlauf: seit die Zahlen in den
   Spalten stehen, wuerde eine Gesamthoehe die Balkenflaeche je nach
   Textumbruch verschieben — die Nulllinie laege dann nicht mehr in jeder
   Spalte auf derselben Hoehe. */
.vhalb { height: 64px; display: flex; justify-content: center; }
.vhalb.oben  { align-items: flex-end;
  border-bottom: 1px solid var(--tinte-matt); }
.vhalb.unten { align-items: flex-start; }
.vbalken { width: min(26px, 70%); min-height: 0; }
.vbalken.ein { background: var(--daten); }
.vbalken.aus { background: var(--tinte-matt); }
/* Die Zahlen an den Balkenenden: oben die Einnahme, unten die Ausgabe.
   Tabellenziffern, damit acht Spalten als Spalten lesbar sind; kein
   Umbruch — eine umgebrochene Zahl saehe aus wie zwei. */
.vzahl {
  text-align: center; font-size: 11px; color: var(--tinte-leise);
  font-variant-numeric: tabular-nums; white-space: nowrap;
  padding: 0 1px 4px;
}
.vzahl.aus { padding: 4px 1px 0; }
.vname {
  text-align: center; font-size: 11.5px; color: var(--tinte-leise);
  padding-top: 6px;
}
.vdiff {
  text-align: center; font-size: 11px; font-weight: 600;
  font-variant-numeric: tabular-nums; white-space: nowrap;
  padding-top: 2px;
}
.vdiff.plus  { color: var(--daten); }
.vdiff.minus { color: var(--alarm); }
.vlegende {
  font-size: 13px; color: var(--tinte-leise); margin-bottom: 18px;
  font-variant-numeric: tabular-nums;
}

/* ── Die Befehlssuche (⌘K) ──────────────────────────────────────────────
   Über allem außer den Meldungen; das Blatt wird beim Öffnen entfernt,
   zwei Überlagerungen gibt es nie gleichzeitig. */
#palette { position: fixed; inset: 0; z-index: 960; }
#palette .palette-schirm {
  position: absolute; inset: 0; background: rgba(20,22,25,.32);
}
#palette .palette-karte {
  position: relative; margin: 14vh auto 0;
  width: min(560px, 92vw);
  background: var(--flaeche-hoch); border-radius: 12px;
  box-shadow: 0 24px 70px rgba(0,0,0,.35);
  overflow: hidden;
}
#palette input {
  width: 100%; border: none; outline: none; background: none;
  padding: 16px 18px; font-size: 16px;
  border-bottom: 1px solid rgba(var(--tinte-rgb),.12);
}
#palette .palette-liste { max-height: 46vh; overflow-y: auto; padding: 6px; }
#palette .palette-zeile {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 12px; padding: 10px 12px; border-radius: 8px; cursor: pointer;
  font-size: 14.5px;
}
#palette .palette-zeile small { color: var(--tinte-leise); font-size: 12.5px; }
#palette .palette-zeile:hover,
#palette .palette-zeile.dran { background: rgba(var(--tinte-rgb),.07); }
#palette .palette-leer {
  padding: 16px 12px; color: var(--tinte-leise); font-size: 14px;
}
.blatt-schirm {
  position: absolute; inset: 0; background: rgba(0,0,0,.38);
  backdrop-filter: blur(2px);
}
.blatt-karte {
  position: absolute; left: 50%; top: 50%;
  transform: translate(-50%, -50%);
  width: min(640px, calc(100vw - 32px));
  max-height: min(86vh, 860px); overflow: auto;
  background: var(--glas-fest, #eceeef);
  border: 1px solid var(--glas-rand, rgba(var(--hell-rgb),.42));
  box-shadow: 0 24px 70px rgba(0,0,0,.30);
  padding: 22px 22px 0; border-radius: 0;   /* unten polstert der Fuss */
  display: flex; flex-direction: column; gap: 16px;
}
.blatt-karte header h3 { margin: 0; font-size: 19px; letter-spacing: var(--spur); }
.blatt-karte header p {
  margin: 5px 0 0; font-size: 13.5px; color: var(--tinte-matt);
  line-height: 1.45;
}

/* Zwei Spalten am Schirm, eine am Telefon. Ein Feld mit `breit` nimmt beide
   — Strasse und Firmenname brauchen die Zeile, PLZ nicht. */
.blatt-felder {
  display: grid; grid-template-columns: 1fr 1fr; gap: 12px 14px;
}
.blatt-feld { display: flex; flex-direction: column; gap: 5px; min-width: 0; }
.blatt-feld.breit, .blatt-schalter { grid-column: 1 / -1; }
.blatt-feld > span {
  font-size: 12.5px; font-weight: 600; color: var(--tinte-matt);
  letter-spacing: .02em;
}
.blatt-feld > span em {
  font-style: normal; font-weight: 400; color: var(--tinte-leise);
}
.blatt-feld input, .blatt-feld select, .blatt-feld textarea {
  /* 44 px ist die Untergrenze fuer einen Treffer mit dem Finger. Die Felder
     stehen alle gleich hoch, damit die Zeilen eine gemeinsame Grundlinie
     haben — ungleich hohe Felder nebeneinander sind das Erste, was an einer
     Oberflaeche billig aussieht. */
  min-height: 44px; padding: 10px 12px; border-radius: 0;
  border: 1px solid rgba(var(--tinte-rgb),.18);
  background: rgba(var(--hell-rgb),.62);
  font: inherit; font-size: 15px; color: var(--tinte); width: 100%;
  /* Ohne das ragt ein <select> unter iOS aus seinem Kasten heraus. */
  appearance: none; -webkit-appearance: none;
}
/* Das mehrzeilige Feld (Anschreiben): nur senkrecht ziehbar — waagerecht
   wuerde es aus der Blattkarte herauswachsen. */
.blatt-feld textarea { resize: vertical; line-height: 1.5; }
.blatt-feld select {
  background-image:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5 6 6.5l5-5' fill='none' stroke='%236c7176' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 12px center;
  padding-right: 34px;
}
.blatt-feld input:focus, .blatt-feld select:focus,
.blatt-feld textarea:focus {
  outline: none; border-color: var(--akzent);
  box-shadow: 0 0 0 3px var(--akzent-flach);
}
.blatt-feld small {
  font-size: 12px; color: var(--tinte-leise); line-height: 1.4;
}

.blatt-schalter {
  display: flex; align-items: flex-start; gap: 11px; cursor: pointer;
  padding: 11px 12px; background: rgba(var(--hell-rgb),.42);
  border: 1px solid rgba(var(--tinte-rgb),.12);
}
.blatt-schalter input { width: 19px; height: 19px; margin-top: 1px; flex: 0 0 19px; }
.blatt-schalter span { display: flex; flex-direction: column; gap: 2px; }
.blatt-schalter strong { font-size: 14.5px; font-weight: 600; }
.blatt-schalter small { font-size: 12.5px; color: var(--tinte-leise); line-height: 1.4; }

.blatt-hinweis {
  margin: 0; font-size: 12.5px; color: var(--tinte-matt); line-height: 1.5;
  border-left: 2px solid var(--akzent); padding-left: 11px;
}
.blatt-fehler {
  margin: 0; font-size: 13.5px; color: var(--alarm); font-weight: 500;
  background: rgba(208,88,76,.10); padding: 10px 12px;
}
/* Die Knoepfe bleiben stehen, auch wenn das Formular laenger ist als das
   Fenster. Gemessen bei 1280x900: die Karte wird 774 px hoch und rollt in
   sich — der Absendeknopf lag beim Oeffnen unterhalb des Sichtfelds. Ein
   Formular, dessen Abschluss man erst suchen muss, ist ein halbes Formular. */
.blatt-karte footer {
  display: flex; justify-content: flex-end; gap: 10px;
  border-top: 1px solid rgba(var(--tinte-rgb),.10);
  /* Der Fuss bringt sein Polster SELBST mit, und die Karte hat unten keines.
     Vorher stand hier `bottom: -16px; margin-bottom: -16px` — der Fuss ragte
     damit absichtlich ueber den Inhaltsrand, und genau diese 16 px hat das
     `overflow: auto` der Karte abgeschnitten. Ein haftendes Element darf nie
     ueber den Rand seines Rollbereichs hinausstehen. */
  padding: 14px 0 calc(18px + env(safe-area-inset-bottom, 0px));
  position: sticky; bottom: 0; margin-top: auto;
  background: var(--glas-fest, #eceeef);
}
.blatt-karte footer .knopf[type="submit"] {
  border: none; background: var(--dunkel); color: #fff;
}

@media (max-width: 720px) {
  .blatt-karte {
    left: 0; right: 0; top: auto; bottom: 0; transform: none;
    width: 100%; max-height: 92vh; border: none;
    padding: 20px 16px 0;
  }
  .blatt-felder { grid-template-columns: 1fr; }
  /* Am Telefon steht der Hauptknopf vorn und nimmt die Breite: mit dem
     Daumen trifft man ihn dann ohne hinzusehen. */
  .blatt-karte footer { flex-direction: column-reverse; }
  .blatt-karte footer .knopf { width: 100%; justify-content: center; min-height: 50px; }
}
.blatt-abschnitt {
  grid-column: 1 / -1; margin: 6px 0 0; font-size: 12px; font-weight: 700;
  letter-spacing: .07em; text-transform: uppercase; color: var(--tinte-leise);
  border-bottom: 1px solid rgba(var(--tinte-rgb),.10); padding-bottom: 7px;
}
.blatt-abschnitt:first-child { margin-top: 0; }

/* Der Knopf sitzt in der Suchleiste, rechts neben der Trefferzahl. Am
   Telefon rutscht er unter die Chips und nimmt die volle Breite — dort ist
   die Suchleiste ohnehin zweizeilig. */
/* `.neuer-mandant` ist am 17.08.2026 aus der Suchzeile an den
   Regelplatz oben rechts gewandert (Regel 3). Die Regeln hier sind damit
   gegenstandslos und entfallen — eine Regel ohne Element ist Ballast,
   der beim naechsten Umbau Raetsel aufgibt. */
@media (max-width: 720px) {
}

/* ── Kontenauswahl im Kontoauszug ─────────────────────────────────────────
   Sie steht in der Suchleiste, weil sie zur Liste darunter gehört: was
   gewählt ist, bestimmt, gegen welches Sachkonto zugeordnet wird. Ein
   eigener Kasten darüber wäre eine zweite Kopfzeile für eine Angabe. */
.kontowahl { display: flex; align-items: center; gap: 8px; min-width: 0; }
.kontowahl .kontofeld {
  min-height: 36px; padding: 7px 30px 7px 11px; border-radius: 0;
  border: 1px solid rgba(var(--tinte-rgb),.18);
  background: rgba(var(--hell-rgb),.55);
  font: inherit; font-size: 13.5px; color: var(--tinte);
  max-width: 320px; text-overflow: ellipsis;
  appearance: none; -webkit-appearance: none;
  background-image:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5 6 6.5l5-5' fill='none' stroke='%236c7176' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 10px center;
}
/* Ein Konto ist eine Angabe, keine Wahl — es steht als Text da. */
.kontowahl .kontoname {
  font-size: 13px; color: var(--tinte-matt); white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis; max-width: 340px;
}
@media (max-width: 720px) {
  .kontowahl { width: 100%; }
  .kontowahl .kontofeld { flex: 1 1 auto; max-width: none; min-height: 44px; }
  .kontowahl .kontoname { max-width: none; }
}

/* ── Rechnungen ───────────────────────────────────────────────────────────
   Dieselbe Zeilenaufteilung wie im Kontoauszug: Datum · wer · Zustand ·
   Betrag. Wer zwei Listen mit derselben Aufgabe unterschiedlich baut,
   zwingt zum zweimal Lernen. */
.rechnung { grid-template-columns: 52px minmax(0, 1fr) 120px 106px; }
/* Ein Entwurf ist unfertige Arbeit — dieselbe Kante wie „Beleg fehlt". */
.rechnung.entwurf { border-left-color: var(--warn); }
/* Storniertes bleibt lesbar, zählt aber nicht mehr. */
.rechnung.storno { opacity: .5; }
.rechnung.storno .summe { text-decoration: line-through; }

/* `.marke` gibt es zweimal: als Wortmarke in der Schiene (Zeile 161,
   weiss auf dunkel) und hier als Zustandsschild. Gleicher Name, zwei Orte —
   ohne Zurücksetzen erscheint das Schild als weisser Block auf hellem Grund
   und ist unsichtbar. Genau so sah es im ersten Entwurf aus. */
.dichtezeile .marke, .detailspalte .marke {
  width: auto; margin: 0; padding: 2px 9px; color: var(--tinte-matt);
  display: inline-flex; align-items: center; justify-self: start;
  font-size: 12px; letter-spacing: .02em; white-space: nowrap;
  border: 1px solid rgba(var(--tinte-rgb),.14); background: rgba(var(--hell-rgb),.5);
}
.dichtezeile .marke.entwurf, .detailspalte .marke.entwurf { color: var(--warn); border-color: rgba(217,149,33,.4); }
.dichtezeile .marke.fest, .detailspalte .marke.fest { color: var(--akzent); border-color: rgba(18,185,129,.4); }
.dichtezeile .marke.storno, .detailspalte .marke.storno { color: var(--tinte-leise); }

/* Eine Position: Text links, Betrag rechts, Entfernen ganz außen. Das
   Entfernen steht bewusst am Rand und nicht neben dem Betrag — sonst
   trifft man beim Zielen auf den Betrag den Löschknopf. */
.poszeile {
  display: grid; grid-template-columns: minmax(0,1fr) auto auto;
  gap: 10px; align-items: center; padding: 7px 0;
  border-bottom: 1px solid rgba(var(--tinte-rgb),.07);
}
.poszeile:last-of-type { border-bottom: none; }
.poszeile .postext { min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.poszeile .postext .name { font-size: 13.5px; color: var(--tinte); }
.poszeile .postext .zweck { font-size: 12px; color: var(--tinte-leise); }
.poszeile .summe {
  font-size: 13.5px; font-variant-numeric: tabular-nums; white-space: nowrap;
}
.poszeile-weg {
  border: none; background: none; cursor: pointer; font-size: 15px;
  color: var(--tinte-leise); line-height: 1;
  /* 32 px: klein genug, um nicht zu dominieren, groß genug zum Treffen. */
  width: 32px; height: 32px; border-radius: 0;
}
.poszeile-weg:hover { color: var(--alarm); background: rgba(208,88,76,.09); }

.summenzeile {
  display: flex; justify-content: space-between; align-items: baseline;
  gap: 16px; padding: 5px 0; font-size: 13.5px; color: var(--tinte-matt);
}
.summenzeile .wert { font-variant-numeric: tabular-nums; color: var(--tinte); }
.summenzeile.stark {
  border-top: 1px solid rgba(var(--tinte-rgb),.14); margin-top: 4px; padding-top: 9px;
  font-size: 15px; color: var(--tinte);
}
.summenzeile.stark .wert { font-size: 19px; }

@media (max-width: 900px) {
  /* Der Zustand fällt weg — er steht ohnehin als Kante links, und 120 px
     für ein Wort sind auf 390 px ein Drittel der Zeile. */
  .rechnung { grid-template-columns: 46px minmax(0, 1fr) 96px; }
  .rechnung .marke { display: none; }
}

/* `.dfeld` ist ein Flex-Container mit Umbruch — wer keine volle Basis hat,
   stellt sich neben seinen Nachbarn. Im ersten Entwurf standen deshalb
   „Netto 750,61 €" und „Umsatzsteuer 141,89 €" in EINER Zeile und der
   Knopf „+ Position" neben der letzten Position. Gemessen bei 1400 px. */
.detailspalte .poszeile,
.detailspalte .summenzeile { flex-basis: 100%; }

/* Ein Knopf, der eine Handlung an der ganzen Liste auslöst, nimmt die
   Breite — dann trifft man ihn auch mit dem Daumen und er steht nicht
   zufällig neben einer Position. */
.detailspalte .knopf.breit {
  flex-basis: 100%; justify-content: center; min-height: 44px;
}

/* ── Die Kontospalte spricht aus, was zu tun ist ──────────────────────────
   Baki: „was genau ist zu klären?" Gemessen: alle 240 offenen Klärfälle
   betreffen das Konto, keiner den Beleg. Also darf die Spalte es sagen. */
.buchung .kontospalte.vorschlag { color: var(--warn); }
.buchung .kontospalte.offen  { color: var(--alarm); font-variant-numeric: normal; }

/* ── Beleg direkt in der Zeile ────────────────────────────────────────────
   Der Knopf steht nur in Zeilen, in denen wirklich ein Beleg fehlt. Ein
   Knopf, der überall steht, ist keine Aufforderung mehr, sondern Muster. */
.belegzelle { display: flex; justify-content: flex-end; }
.belegdazu {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 3px 8px; min-height: 26px;
  border: 1px solid rgba(var(--tinte-rgb),.18); border-radius: 0;
  background: rgba(var(--hell-rgb),.6); cursor: pointer;
  font: inherit; font-size: 12px; color: var(--tinte-matt);
  white-space: nowrap;
}
.belegdazu:hover:not(:disabled) {
  border-color: var(--akzent); color: var(--akzent);
  background: var(--akzent-flach);
}
.belegdazu:active:not(:disabled) { transform: scale(.96); }
.belegdazu:disabled { opacity: .6; cursor: default; }
.belegdazu svg { stroke: currentColor; }

@media (max-width: 900px) {
  /* Auf dem Telefon fällt die Kontospalte weg — sie steht im Detail. Der
     Belegknopf bleibt: er IST die Arbeit, die man unterwegs macht, und
     wächst auf eine Fläche, die man mit dem Daumen trifft. */
  .buchung { grid-template-columns: 52px minmax(0, 1fr) 48px 96px; }
  /* Am Telefon fallen Konto und Statuswort weg — beides steht im Detail.
     Das Kästchen bleibt: ohne es kann man nichts freigeben. */
  .buchungssatz { grid-template-columns: 40px 52px minmax(0, 1fr) 96px; }
  .buchungssatz .kontospalte,
  .buchungssatz .zustand span:not(.ampel) { display: none; }
  .buchung .kontospalte, .buchung .zustand span:not(.ampel) { display: none; }
  /* 44, nicht 40. Der Telefondurchgang hat es erst gefunden, als die
     Belege-Ansicht auf diese Zeile umgestellt war — im Kontoauszug stand in
     den Probedaten keine einzige Zeile mit fehlendem Beleg, also wurde der
     Knopf nie gezeichnet und nie gemessen. Ein Prüfstand misst nur, was auch
     entsteht. */
  .belegdazu { min-height: 44px; width: 44px; padding: 0; justify-content: center; }
  .belegdazu span { display: none; }
}

/* Eine Zeile in den Einstellungen: Beschreibung links, Handlung rechts.
   `.seitenzeile` gab es noch nicht — die Einstellungsblöcke bauen ihre
   Zeilen bisher jeder für sich. Hier einmal, damit die nächste nicht
   wieder anders aussieht. */
.seitenzeile {
  display: flex; align-items: center; justify-content: space-between;
  gap: 16px; flex-wrap: wrap;
}

@media (max-width: 860px) {
  /* ── Die Fussleiste darf nichts verdecken ──────────────────────────────
     Sie liegt fest am unteren Rand. Ohne Platz darunter steht die letzte
     Zeile jeder Liste dahinter — gemessen an der Übersicht: „Transgourmet"
     lag zur Hälfte unter der Leiste. Das Detailfenster hatte diesen Abstand
     seit jeher (Zeile 2778), die Seite selbst nicht.

     78 px ist die Höhe der Leiste, 12 px Luft darüber, dazu der sichere
     Bereich des Geräts. */
  .buehne { padding-bottom: calc(90px + env(safe-area-inset-bottom)); }
}

/* ═════════════════════════════════════════════════════════════════════════
   TIPPZIELE AUF DEM TELEFON

   Der Telefondurchgang des Prüfstands (15.08.2026) fand in JEDER Ansicht
   Bedienelemente unter 44 px — dem Maß, mit dem ein Daumen sicher trifft.
   Die Zahl ist keine Meinung: sie steht in Apples Richtlinien seit dem
   ersten iPhone, und WCAG 2.5.8 nennt 24 px als absolute Untergrenze.

   Am Schirm bleiben die Maße, wie sie sind: dort zielt eine Maus, und
   34 px hohe Chips sind dort richtig. Getrennt zu behandeln ist kein
   Sonderfall, sondern der Unterschied zwischen Zeigefinger und Zeiger.
   ═════════════════════════════════════════════════════════════════════════ */
@media (max-width: 860px) {
  /* Das Zahnrad oben rechts war 40 px — mein eigener Fehler von vorhin. */
  .schiene .zahnrad { width: 44px; height: 44px; min-width: 44px; min-height: 44px; }

  /* Filterchips („Alle", „Mit Bankdaten", „25 / 50 / 100") */
  .filterchip, .filterreihe button, .filterknopf, .blaetterung button {
    min-height: 44px; padding-top: 0; padding-bottom: 0;
  }

  /* Einträge der Kontextleiste — Mandantenwahl und Filter. Sie sind das,
     was man auf dem Telefon am häufigsten trifft. */
  .leiste .punkt { min-height: 44px; }

  /* Eingabefelder: 16 px verhindert außerdem, dass iOS beim Antippen
     hineinzoomt — ein Zoom, aus dem man nur mit zwei Fingern wieder
     herauskommt. */
  input:not([type=checkbox]):not([type=radio]), select, textarea {
    min-height: 44px; font-size: 16px;
  }

  /* Knöpfe in Listenzeilen und Karten. `.klein` heißt klein für die Maus,
     nicht klein für den Daumen. */
  .knopf, .knopf.klein { min-height: 44px; }

}

/* Die Trefferfläche um ein Ankreuzfeld.
   Das Kästchen bleibt klein — in einer 40-px-Zeile wäre ein 44-px-Kasten
   ein Klotz. Anklickbar ist die Fläche drumherum: ein `label` um das Feld
   ist von sich aus ein Ziel, ganz ohne JavaScript. */
.wahlflaeche {
  display: inline-flex; align-items: center; justify-content: center;
  cursor: pointer;
}
@media (max-width: 860px) {
  .wahlflaeche { min-width: 44px; min-height: 44px; margin: -8px; }
}

/* ── „Diese Seite ist nicht mehr die aktuelle Fassung" ────────────────────
   Das Band steht unten und nicht oben: oben liegt der Kopf mit Titel und
   Aktionen, und ein Hinweis, der den verdeckt, nimmt genau das weg, wonach
   der Benutzer gerade greift. Unten ist es sichtbar und im Weg von nichts.
   Kein Schirm dahinter — es ist eine Auskunft, keine Frage. */
.fassungsband {
  position: fixed; z-index: 980;
  left: 50%; transform: translateX(-50%);
  bottom: calc(18px + env(safe-area-inset-bottom, 0px));
  display: flex; align-items: center; gap: 14px;
  max-width: calc(100vw - 32px);
  padding: 12px 14px;
  background: var(--dunkel, #22252a); color: #fff;
  box-shadow: 0 14px 40px rgba(0,0,0,.34);
  animation: fassung-herein var(--zeit-schub, .22s) var(--kurve-schub, ease) both;
}
@keyframes fassung-herein {
  from { opacity: 0; transform: translate(-50%, 12px); }
  to   { opacity: 1; transform: translate(-50%, 0); }
}
@media (prefers-reduced-motion: reduce) { .fassungsband { animation: none; } }
.fassungstext { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.fassungstext span { font-size: 14px; font-weight: 500; }
.fassungstext small {
  font-size: 11.5px; color: rgba(var(--schiene-hell),.62);
  font-variant-numeric: tabular-nums;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.fassungsband .knopf { flex: none; background: #fff; color: var(--dunkel, #22252a); }
.fassungsband .knopf.leise { background: transparent; color: rgba(var(--schiene-hell),.72); }

/* Am Telefon liegt unten die Fussleiste — das Band muss darueber. */
@media (max-width: 860px) {
  .fassungsband {
    bottom: calc(84px + env(safe-area-inset-bottom, 0px));
    left: 16px; right: 16px; transform: none; max-width: none;
  }
  @keyframes fassung-herein {
    from { opacity: 0; transform: translateY(12px); }
    to   { opacity: 1; transform: translateY(0); }
  }
}

/* Die Kachel mit Logo: das Bild deckt die Anfangsbuchstaben ab, statt sie zu
   ersetzen. Solange es nicht geladen ist, stehen die Buchstaben — ein leeres
   Feld waere schlechter als ein Platzhalter. */
.konto .bild.mit-logo { position: relative; overflow: hidden; }
.konto .bild.mit-logo img {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; display: block;
}

/* ═════════════════════════════════════════════════════════════════════════
   DER SCHWEBENDE KNOPF

   Baki: „Mach das Plus einfach über die rechts, schwebend, transparent. im
   Glossy Glas Liquid Glas Look."

   Echtes Glas hat vier Schichten, und jede einzelne fehlt, wenn man nur eine
   halbtransparente Farbe nimmt:

     1 · Unschaerfe DAHINTER  — man sieht, dass etwas darunter liegt
     2 · ein Verlauf         — Licht faellt von oben ein
     3 · eine Lichtkante oben und eine Schattenkante unten — Materialstaerke
     4 · ein weicher Schlagschatten — es liegt DARUEBER, nicht darin

   Dazu ein schmaler Glanzbogen oben links: das ist die Spiegelung, an der
   das Auge „Glas" erkennt und nicht „Milchplastik".

   Nur am Telefon. Am Schirm steht „Belege hochladen" im Kopf der Ansicht —
   zwei Wege zur selben Handlung waeren Redundanz. */
.plus-schweber { display: none; }

@media (max-width: 860px) {
  .plus-schweber {
    position: fixed;
    right: calc(16px + env(safe-area-inset-right, 0px));
    /* Ueber der Fussleiste, nicht auf ihr: 64 px Leiste + 16 px Luft. */
    bottom: calc(84px + env(safe-area-inset-bottom, 0px));
    z-index: 940;

    display: flex; align-items: center; justify-content: center;
    width: 58px; height: 58px; padding: 0;
    border-radius: 50%;
    cursor: pointer;
    color: var(--tinte, #22252a);

    /* 1 · was dahinterliegt, wird unscharf und gesaettigter — daran erkennt
       das Auge eine Scheibe statt einer Flaeche. */
    -webkit-backdrop-filter: blur(18px) saturate(190%);
            backdrop-filter: blur(18px) saturate(190%);

    /* 2 · der Verlauf. Oben mehr Licht als unten. */
    background:
      linear-gradient(160deg,
        rgba(var(--hell-rgb),.78) 0%,
        rgba(var(--hell-rgb),.46) 46%,
        rgba(var(--hell-rgb),.30) 100%);

    /* 3 · Materialstaerke: Lichtkante oben, Schattenkante unten, dazu eine
       haarfeine Aussenlinie, damit die Scheibe auf hellem Grund nicht
       ausfranst. */
    border: .5px solid rgba(var(--hell-rgb),.75);
    box-shadow:
      inset 0 1px 0 rgba(var(--hell-rgb),.95),
      inset 0 -1px 0 rgba(0,0,0,.10),
      inset 0 0 0 .5px rgba(var(--hell-rgb),.35),
      /* 4 · er liegt darueber */
      0 10px 26px rgba(20,24,28,.20),
      0 2px 6px rgba(20,24,28,.14);

    transition: transform .18s cubic-bezier(.22,1,.36,1),
                box-shadow .18s ease;
  }

  /* Der Glanzbogen oben links — die Spiegelung, an der Glas als Glas
     gelesen wird. Bewusst schmal: ein breiter Schein macht Milch. */
  .plus-schweber::after {
    content: ""; position: absolute; inset: 0; border-radius: inherit;
    background:
      radial-gradient(70% 46% at 30% 6%, rgba(var(--hell-rgb),.85), transparent 62%);
    pointer-events: none;
  }

  .plus-schweber svg {
    position: relative; z-index: 1;
    stroke: var(--tinte, #22252a); stroke-width: 2;
  }

  .plus-schweber:active {
    transform: scale(.94);
    box-shadow:
      inset 0 1px 0 rgba(var(--hell-rgb),.95),
      inset 0 -1px 0 rgba(0,0,0,.10),
      0 4px 12px rgba(20,24,28,.18);
  }

  @media (prefers-reduced-motion: reduce) {
    .plus-schweber { transition: none; }
  }
}

/* ── Der Beleg zum Ansehen ────────────────────────────────────────────────
   Baki: „Man muss auch vor allem selbst fotografierte Belege anschauen
   können […] damit man sehen kann, um welche Art von Beleg es überhaupt
   geht. Diese Funktion fehlt noch völlig."

   Fester Rahmen mit fester Hoehe: ein Kassenzettel ist hochkant, eine
   Rechnung quer, und eine Spalte, die je nach Beleg ihre Hoehe aendert, laesst
   alles darunter bei jedem Klick springen. */
.belegvorschau {
  margin-bottom: 10px;
  height: 260px; width: 100%;
  display: flex; align-items: center; justify-content: center;
  background: rgba(var(--tinte-rgb),.05);
  border: 1px solid rgba(var(--tinte-rgb),.12);
  overflow: hidden;
}
.belegvorschau img {
  max-width: 100%; max-height: 100%;
  width: auto; height: auto;
  object-fit: contain; display: block; cursor: zoom-in;
}
.belegvorschau object { width: 100%; height: 100%; border: 0; }
.belegvorschau .fein {
  font-size: 12.5px; color: var(--tinte-leise); text-align: center;
  padding: 0 14px;
}

/* Am Telefon steht die Spalte unter der Liste und der Platz ist knapper —
   aber ein Beleg, den man nicht erkennt, nuetzt gar nichts. 220 px ist die
   Hoehe, bei der eine Rechnungskopfzeile noch lesbar ist. */
@media (max-width: 900px) {
  .belegvorschau { height: 220px; }
}

/* ── Das Schliessen-Kreuz am Telefon ──────────────────────────────────────
   Baki, mit Foto: „Hier liegt das x genau hinter dem Einstellungsicon. Man
   ist auf dieser Seite gefangen."

   Das Zahnrad steht am Telefon `fixed` oben rechts mit z-index 60. Das
   Kreuz der Detailspalte laeuft im normalen Fluss an dieselbe Ecke und
   verschwindet darunter. Am Schirm gibt es das Problem nicht — dort steht
   das Zahnrad unten in der Schiene.

   Esc hilft nicht: eine Tastatur hat hier niemand. Ohne sichtbares Kreuz
   gibt es keinen Weg zurueck.

   Es wandert deshalb nach LINKS. Dort steht es auch bei jedem Blatt und in
   jeder App, die eine Ansicht ueber eine andere legt. */
@media (max-width: 900px) {
  .detailspalte .dkopf {
    justify-content: flex-start; gap: 10px;
  }
  .detailspalte .dschliessen {
    order: -1;
    width: 44px; height: 44px; min-width: 44px;
    margin: 0 0 0 -10px;
    font-size: 26px;
    /* Ueber allem, was sonst noch fest steht. */
    position: relative; z-index: 70;
  }
  /* Der Eingangstag rutscht mit nach rechts und bleibt lesbar. */
  .detailspalte .dtag { margin-left: auto; }
}

/* Das Zahnrad verschwindet, solange ein Blatt offen ist.
   Es steht am Telefon `fixed` mit z-index 60, die Detailspalte mit 50 — das
   Zahnrad schwebt also UEBER dem geoeffneten Beleg und deckt dort zu, was
   an derselben Stelle liegt. Baki, mit Foto: „Hier liegt das x genau hinter
   dem Einstellungsicon. Man ist auf dieser Seite gefangen."

   Das Kreuz steht seit heute links, damit ist die Kollision weg. Aber das
   Zahnrad ueber einem geoeffneten Beleg ist auch ohne Kollision falsch: es
   fuehrt aus dem Blatt heraus, ohne es zu schliessen. Waehrend ein Blatt
   offen ist, gibt es genau einen Weg zurueck, und der steht im Blatt. */
@media (max-width: 900px) {
  body:has(.detailspalte.offen) .schiene .zahnrad,
  body:has(.plus-schweber):has(.detailspalte.offen) .plus-schweber {
    display: none;
  }
}

/* Der schwebende Knopf gehoert nicht auf jede Seite.
   In den Einstellungen und bei den Rechnungen gibt es nichts hochzuladen —
   ein Knopf, der dort schwebt, verspricht etwas, das die Seite nicht kann
   (Regel 1). Im Foto vom 15.08. schwebte er ueber „Logo waehlen". */
body[data-ansicht="einstellungen"] .plus-schweber,
body[data-ansicht="rechnungen"] .plus-schweber { display: none; }

/* ── Gerätewege ──────────────────────────────────────────────────────────
   `.nurkamera`: der Fotografieren-Weg. Er existiert im Baum immer (so ist
   er messbar), gezeigt wird er nur an Geräten mit grobem Zeiger — dort
   liegt der Beleg auf dem Tisch, nicht im Downloads-Ordner.
   `.nurzeiger`: umgekehrt — Maus- und Zweitbildschirm-Dinge, die am
   Telefon nichts versprechen dürfen, was dort nicht geht (Regel 1).

   Dieser Block steht am ENDE der Datei, mit Absicht: `.belegdazu` und
   `.knopf` setzen `display` mit derselben Spezifität — stünde `display:
   none` weiter oben, gewänne die spätere Regel und der Kamera-Knopf wäre
   auf jedem Gerät sichtbar. Genau so gemessen, bevor der Block wanderte. */
.nurkamera { display: none; }
@media (pointer: coarse) {
  .nurkamera { display: inline-flex; }
  .nurzeiger { display: none; }

  /* Auswahlfelder in Fingergröße. Bakis Foto von der Betreuungsliste am
     Telefon: die Felder waren Mauszeiger-Größe. 44 px ist das übliche
     Mindestziel, und 16 px Schrift verhindert, dass iOS beim Antippen in
     die Seite hineinzoomt. Die zusätzlichen Selektoren sind kein Schmuck:
     ein select mit eigener Klasse (`.feld`, Anbieterwahl im Postfachform)
     schlug das nackte `select` in der Spezifität und blieb bei 14,5 px —
     von der Fingerprobe gefunden. */
  select,
  .ansicht select,
  .blatt-karte select { min-height: 44px; font-size: 16px; padding: 8px 12px; }
}

/* Die Wischlade der Rechnungsliste: Entwurf nach links ziehen legt
   „Löschen" frei — die übliche Geste. Die Zeile deckt den Knopf mit
   eigenem Grund ab, sonst schimmert er durch. `touch-action: pan-y`:
   senkrecht gehört dem Rollen, nur waagerecht der Geste. */
.wischhuelle { position: relative; overflow: hidden; }
.wischhuelle .wischweg {
  position: absolute; inset: 0 0 0 auto; width: 96px;
  border: none; border-radius: 0; cursor: pointer;
  background: var(--alarm); color: #fff;
  font: inherit; font-size: 14px; font-weight: 600;
}
.wischhuelle > .dichtezeile {
  position: relative; z-index: 1;
  background: var(--flaeche);
  touch-action: pan-y;
  transition: transform var(--zeit-druck) ease;
}

/* ── Fragen an die Kanzlei (Mandanten-Übersicht) ─────────────────────────
   Dieselbe ruhige Kartenform wie überall — die Antwort hebt sich als
   eingelassener Kasten ab, damit Frage und Antwort nicht verschwimmen. */
.fragenliste { display: flex; flex-direction: column; gap: 10px;
  margin-bottom: 26px; }
.fragenliste > .knopf { align-self: flex-start; }
.frage {
  background: var(--flaeche-hoch); border: 1px solid rgba(var(--tinte-rgb),.08);
  padding: 12px 14px; display: flex; flex-direction: column; gap: 6px;
}
.frage .fkopf { display: flex; justify-content: space-between; gap: 12px;
  align-items: baseline; }
.frage .ftitel { font-weight: 600; }
.frage .fantwort {
  background: var(--flaeche-matt); padding: 10px 12px; margin-top: 4px;
  display: flex; flex-direction: column; gap: 4px; line-height: 1.5;
}
.frage .foffen { color: var(--warn); }

/* Die Kontozeile der Einstellungen: zwei Eingaben, Artwort, Knopf. Auf
   einem Telefon passen die nicht nebeneinander — die Zeile bricht um,
   und jede Eingabe behält Daumenhöhe. Ohne das quetschte die 390-px-
   Messung beide Felder unter 44 px (gemessen, nicht vermutet). */
.kontozeile { flex-wrap: wrap; }
.kontozeile input { flex: 1 1 150px; min-width: 0; }
@media (pointer: coarse) {
  .kontozeile input { min-height: 44px; font-size: 16px; }
}

/* ═══ Bewegung: die Bausteine ════════════════════════════════════════════
   Gehoert ans Dateiende wie der Geraetewege-Block: was spaeter steht,
   gewinnt in der Kaskade, und diese Klassen sollen sich nicht von einer
   fruehen Regel ueberstimmen lassen. */

/* Eintritt einer Zeile. `--stufe` setzt bewegung.js je Zeile; ohne das
   Skript ist sie 0 und alles erscheint gleichzeitig — nie unsichtbar. */
@keyframes eintreten {
  from { opacity: 0; transform: translateY(var(--weg-klein)); }
  to   { opacity: 1; transform: none; }
}
.eintritt {
  animation: eintreten var(--zeit-klein) var(--kurve-raus) backwards;
  animation-delay: calc(var(--stufe, 0) * var(--stufung));
}

/* Auf- und Zuklappen ohne Hoehenrechnerei. `0fr` → `1fr` ist animierbar,
   `height: auto` nicht. Der Inhalt braucht `min-height: 0`, sonst
   weigert sich das Raster, ihn kleiner als seinen Inhalt zu machen. */
.klappe {
  display: grid; grid-template-rows: 0fr;
  transition: grid-template-rows var(--zeit-mittel) var(--kurve-raus);
}
.klappe.offen { grid-template-rows: 1fr; }
.klappe > .klappe-inhalt { min-height: 0; overflow: hidden; }

/* ═══ Der Gespraechsverlauf am Vorgang ═══════════════════════════════════
   Drei Arten, drei Anmutungen — der Unterschied muss ohne Lesen erkennbar
   sein: die Kanzlei rechts wie im Nachrichtenprogramm, der Mandant links,
   die interne Notiz quer ueber die volle Breite mit gelbem Rand, damit
   niemand sie fuer eine verschickte Antwort haelt. */
/* ACHTUNG NAMENSKOLLISION (17.08.2026): Diese Liste hiess zuerst
   `.verlauf` — den Namen trug aber schon das Einnahmen/Ausgaben-Diagramm
   weiter oben (Zeile ~3261). Meine `flex-direction: column` hat dessen
   waagerechte Balkenreihe senkrecht gestellt; Baki mit Bild: „du hast das
   zerschossen". Wer eine neue Klasse erfindet, muss vorher pruefen, ob es
   sie schon gibt — `grep` kostet fuenf Sekunden. */
.gespraech { display: flex; flex-direction: column; gap: 10px; }
.beitrag {
  max-width: min(78%, 640px); padding: 10px 13px;
  border: 1px solid rgba(var(--tinte-rgb), .14);
  background: var(--flaeche-hoch); font-size: 14.5px; line-height: 1.55;
}
.beitrag .wer {
  font-size: 12px; color: var(--tinte-leise); margin-bottom: 4px;
  display: flex; gap: 8px; align-items: baseline;
}
.beitrag .text { white-space: pre-wrap; overflow-wrap: anywhere; }
.beitrag.kanzlei { align-self: flex-end; background: var(--akzent-flach); }
.beitrag.mandant { align-self: flex-start; }
.beitrag.intern {
  align-self: stretch; max-width: none;
  background: rgba(214, 158, 46, .10);
  border-left: 3px solid #d69e2e;
}
.beitrag.intern .wer { color: #8a6118; font-weight: 600; }
/* Ereignisse stehen zwischen den Beitraegen — eine Zeile, kein Kasten.
   Ein Statuswechsel ist kein Gespraechsbeitrag und darf nicht so aussehen. */
.gespraechereignis {
  align-self: center; font-size: 12px; color: var(--tinte-leise);
  padding: 2px 0;
}

/* ── Bausteine für die Antwort ────────────────────────────────────────
   Baki: „verschieden Bausteine … die man per drag and drop automatisch in
   das Fenster ziehen kann". Sie stehen ÜBER dem Schreibfeld, weil sie es
   füllen — was hineinfließt, gehört über das Gefäß. Anklicken tut
   dasselbe wie Ziehen; am Telefon gibt es kein Ziehen. */
.bausteine {
  display: flex; flex-wrap: wrap; gap: 8px;
  margin-top: 12px;
}
.bausteine[hidden] { display: none; }
.bausteinekopf {
  flex-basis: 100%; font-size: 12px; color: var(--tinte-leise);
}
.baustein {
  display: flex; flex-direction: column; gap: 2px; align-items: flex-start;
  padding: 8px 12px; min-height: 44px;
  border: 1px dashed rgba(var(--tinte-rgb), .28);
  background: rgba(var(--hell-rgb), .5); color: var(--tinte);
  font: inherit; text-align: left; cursor: grab;
  transition: border-color var(--zeit-klein) var(--kurve-raus),
              background var(--zeit-klein) var(--kurve-raus);
}
.baustein:hover, .baustein:focus-visible {
  border-color: var(--akzent); background: var(--akzent-flach);
}
.baustein:active { cursor: grabbing; }
.bausteintitel { font-size: 13.5px; font-weight: 600; }
.bausteinzahl {
  font-variant-numeric: tabular-nums; font-size: 12px;
  color: var(--daten); font-weight: 600;
}
.bausteinhinweis { font-size: 11.5px; color: var(--tinte-leise); }

/* Das Schreibfeld als Ziel — nur während gezogen wird. */
.gespraechfeld.zielt {
  border-color: var(--akzent) !important;
  background: var(--akzent-flach) !important;
}

/* Was am Entwurf hängt. Steht unter dem Feld, weil es dem Text folgt. */
.entwurfanhang {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin-top: 8px; padding: 8px 12px;
  border: 1px solid rgba(var(--tinte-rgb), .18);
  background: rgba(var(--hell-rgb), .5);
  font-size: 13px;
}
.entwurfanhang[hidden] { display: none; }
.anhangname { font-weight: 600; }
.anhangzahl {
  font-variant-numeric: tabular-nums; color: var(--tinte-leise);
}
.anhangweg {
  margin-left: auto; font: inherit; font-size: 12.5px;
  min-height: 32px; padding: 4px 10px;
  border: 1px solid rgba(var(--tinte-rgb), .18);
  background: none; color: var(--tinte-leise); cursor: pointer;
}
.anhangweg:hover { color: var(--alarm); border-color: var(--alarm); }

/* Die Zeile der Ticketliste folgt der Auszugszeile (Regel 3) und ergaenzt
   nur die Nummer und den Zustandspunkt. */
.tnummer {
  font-variant-numeric: tabular-nums; color: var(--tinte-leise);
  font-size: 12.5px; flex: none;
}
.tpunkt {
  width: 8px; height: 8px; border-radius: 50%; flex: none;
  background: var(--tinte-matt);
  transition: background var(--zeit-klein) var(--kurve-raus);
}
.tpunkt.neu            { background: var(--akzent); }
.tpunkt.wartet_kanzlei { background: #d69e2e; }
.tpunkt.wartet_mandant { background: var(--tinte-matt); }
.tpunkt.erledigt       { background: transparent;
                         box-shadow: inset 0 0 0 1.5px var(--tinte-matt); }
.tprio {
  font-size: 12px; padding: 1px 6px; flex: none;
  border: 1px solid rgba(var(--tinte-rgb), .18); color: var(--tinte-leise);
}
.tprio.dringend { border-color: var(--alarm); color: var(--alarm); }
.tprio.hoch     { border-color: #d69e2e; color: #8a6118; }

/* ── Die mitlaufende Belegvorschau im Auszug-Detail ──────────────────────
   FESTE Hoehe, auch waehrend des Ladens: sonst springt die Detailspalte
   bei jedem Zeilenwechsel, und wer mit den Pfeiltasten durch die Liste
   geht, sieht die Kontierung darunter huepfen. Das ist der Layout-Sprung,
   den Bewegung verhindern soll, nicht verursachen.

   HEISST BEWUSST NICHT `.belegvorschau` — den Namen traegt schon die
   Vorschau im Posteingang (Zeile ~3840, feste 260 px am Kasten selbst).
   Zweite Namenskollision desselben Tages; die erste hat das
   Einnahmen-Diagramm zerlegt. Seitdem wird vor jeder neuen Klasse
   gegriffen, nicht geraten. */
.belegmitlauf { margin: 12px 0 4px; }
.bvplatz {
  height: 260px; background: var(--flaeche-matt);
  border: 1px solid rgba(var(--tinte-rgb), .14);
  display: flex; align-items: center; justify-content: center;
  overflow: hidden; cursor: zoom-in;
}
.bvplatz img { max-width: 100%; max-height: 100%; object-fit: contain;
               display: block; }
.bvplatz object { width: 100%; height: 100%; border: 0; }
.bvfuss {
  display: flex; gap: 8px; align-items: baseline; justify-content: space-between;
  padding: 5px 2px 0; font-size: 12.5px; color: var(--tinte-leise);
}
.bvname { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Am Telefon ist die Detailspalte selbst schon knapp — dort reicht die
   halbe Hoehe, sonst schiebt die Vorschau alles Bedienbare aus dem Bild. */
@media (max-width: 860px) {
  .bvplatz { height: 180px; }
}
@media (prefers-reduced-motion: no-preference) {
  .bvplatz img, .bvplatz object {
    animation: eintreten var(--zeit-klein) var(--kurve-raus) backwards;
  }
}

/* ── Der Sprunglink ──────────────────────────────────────────────────────
   Unsichtbar, bis er den Fokus bekommt. Nicht `display:none` — das nimmt
   ihn auch dem Tabulator weg, und dann ist er kein Sprunglink mehr,
   sondern gar nichts. Deshalb aus dem Bild geschoben und beim Fokus
   zurueckgeholt. */
.sprunglink {
  position: fixed; top: 8px; left: -9999px; z-index: 2000;
  /* 44 px auch hier: sobald er sichtbar ist, ist er ein Ziel wie jedes
     andere. Die 390-px-Messung hat ihn mit 40 px sofort beanstandet —
     zu Recht, und das war die erste Probe, die ihn ueberhaupt sah. */
  min-height: 44px; display: inline-flex; align-items: center;
  padding: 10px 16px; background: var(--flaeche-hoch); color: var(--tinte);
  border: 1px solid var(--akzent); font-size: 15px; text-decoration: none;
}
.sprunglink:focus { left: 8px; }

/* Der Themenschalter im Burger-Menue: drei Knoepfe in einer Reihe, der
   gewaehlte hervorgehoben. Bewusst kein Auswahlfeld — bei drei Werten ist
   eine Reihe schneller als ein Aufklappen. */
.menue-thema {
  display: flex; gap: 6px; padding: 4px 18px 10px;
}
.menue-themawahl {
  flex: 1; min-height: 36px; padding: 6px 8px;
  border: 1px solid rgba(var(--tinte-rgb),.18);
  background: none; font: inherit; font-size: 13.5px;
  color: var(--tinte-leise); cursor: pointer;
  transition: background var(--zeit-klein) ease, color var(--zeit-klein) ease;
}
.menue-themawahl:hover { background: rgba(var(--tinte-rgb),.06); }
.menue-themawahl.aktiv {
  color: var(--tinte); border-color: var(--akzent);
  background: var(--akzent-flach);
}

/* ── Das Erklärfenster am Begriff ─────────────────────────────────────
   Baki: „ein kleines erklärefenster … dass GANZ GENAU sagt, was konto
   Fehlt überhaupt bedeutet. damit der Nutzer weiß, was er überhaupt machen
   muss."

   Es liegt an `document.body` und ist `fixed` — läge es im Element, würde
   jede Liste mit `overflow: hidden` es abschneiden. z-index 990: über dem
   Blatt (950) und dem Menü (980), weil man auch DORT einen Begriff
   erklären können muss; unter dem Sprunglink (2000). */
.begrifffenster {
  position: fixed; z-index: 990;
  max-width: 340px; padding: 12px 14px;
  background: var(--grund); color: var(--tinte);
  border: 1px solid rgba(var(--tinte-rgb), .22);
  box-shadow: 0 8px 28px rgba(0,0,0,.18);
  font-size: 13px; line-height: 1.5;
  /* Der Zeiger darf nicht am eigenen Fenster hängen bleiben — sonst
     flackert es, wenn man knapp daneben fährt. */
  pointer-events: none;
  opacity: 0; transform: translateY(-3px);
  transition: opacity var(--zeit-klein) var(--kurve-raus),
              transform var(--zeit-klein) var(--kurve-raus);
}
.begrifffenster.da { opacity: 1; transform: none; }
.begriffwort { display: block; font-size: 13.5px; margin-bottom: 4px; }
.begrifftext { margin: 0; }
/* Der Handlungsteil ist abgesetzt — er ist der Grund, warum es das Fenster
   gibt. Wer nur die Bedeutung liest, weiß noch nicht, was er tun soll. */
.begriffmarke {
  display: block; margin-top: 10px; margin-bottom: 2px;
  font-size: 10.5px; letter-spacing: .06em; text-transform: uppercase;
  color: var(--akzent); font-weight: 700;
}
.begrifftun { margin: 0; }
.begriffwarum {
  margin: 8px 0 0; padding-top: 8px;
  border-top: 1px solid rgba(var(--tinte-rgb), .12);
  color: var(--tinte-leise); font-size: 12.5px;
}
/* Ein Begriff mit Erklärung bekommt eine dezente Markierung — sonst weiß
   niemand, wo es etwas zu holen gibt. Gepunktet, nicht durchgezogen: eine
   durchgezogene Linie liest sich als Link. */
.hatErklaerung { text-decoration: underline dotted
  rgba(var(--tinte-rgb), .35); text-underline-offset: 3px; cursor: help; }
.lagechip.hatErklaerung { text-decoration: none; cursor: pointer; }

/* ── Die Legende ──────────────────────────────────────────────────────
   Dieselben Texte wie im Erklärfenster, aus derselben Quelle (glossar.js).
   Hier zum Durchlesen statt zum Nachschlagen. */
.legende { display: flex; flex-direction: column; gap: 22px; }
.legenderubrik { display: flex; flex-direction: column; gap: 10px; }
.legendetitel {
  font-size: 11px; letter-spacing: .06em; text-transform: uppercase;
  color: var(--tinte-leise); font-weight: 700;
}
.legendeeintrag {
  padding: 12px 14px;
  border: 1px solid rgba(var(--tinte-rgb), .14);
  background: rgba(var(--hell-rgb), .45);
}
.legendewort { display: block; font-weight: 600; margin-bottom: 4px; }
.legendebedeutung { margin: 0; font-size: 13.5px; line-height: 1.55; }
.legendetun {
  margin: 8px 0 0; font-size: 13.5px; line-height: 1.55;
}
.legendetun strong { color: var(--akzent); }
.legendewarum {
  margin: 8px 0 0; padding-top: 8px;
  border-top: 1px solid rgba(var(--tinte-rgb), .12);
  color: var(--tinte-leise); font-size: 12.5px; line-height: 1.5;
}
