
  :root{
    --paper:#fbfaf8; --ink:#1a1a1a; --muted:#6b6b66; --line:#e4e1da;
    --green:#0d6e5f; --green-soft:#e7f1ee; --red:#b3402a; --tab:#f1eee7;
    /* Farbrollen fuer die dunkle Darstellung (03.11.2026). Im Hellen genau die
       Werte, die vorher fest im Code standen -- hell aendert sich nichts.
       --karte: Karten, Felder, Masken (vorher #fff). --gruen-fill: gruene
       FLAECHE mit weisser Schrift; --green bleibt Text, Symbol, Rand -- im
       Dunkeln braucht Schrift ein helleres Gruen als ein Knopf. */
    --karte:#fff; --karte-klar:rgba(255,255,255,0); --gruen-fill:#0d6e5f;
    --rot-flaeche:#fdecea; --rot-rand:#e8b3a7;
    /* --auf-tinte: Schrift auf einer Flaeche in Schriftfarbe (Hinweis unten, gewaehlte
       Belegart, Zahl am Papierkorb) -- im Dunkeln wird die Flaeche hell, die Schrift
       dunkel. --rot-fill: rote FLAECHE mit weisser Schrift, in beiden gleich kraeftig;
       --red ist im Dunkeln hell und taugt dort nur als Schrift. */
    --auf-tinte:#fff; --rot-fill:#b3402a;

    /* ---------- Bearbeitungsstand: drei Farben, ueberall dieselben ----------
       grau  = noch nichts passiert  (neu gemeldet, leer stehend, nichts angeboten)
       beige = in Arbeit             (gekuendigt, laeuft aus, unbestaetigt, offen)
       gruen = erledigt              (vermietet, abgeschlossen, bezahlt)

       Gruen ist das Zetaro-Gruen, nicht irgendein Gruen -- dieselbe Farbe
       wie Marke und Knoepfe. Vorher erfand jede Stelle ihren eigenen
       Beige-Ton (sieben verschiedene Hex-Werte fuer dieselbe Aussage), und
       die Mieteranliegen waren sogar andersherum eingefaerbt als die
       Vorgaenge: dort hiess gruen "in Arbeit" und gelb "neu".

       Rot gehoert bewusst NICHT in diese Skala. Es ist eine andere
       Aussage -- Fehler, ueberfaelliges Geld, ablaufende Frist -- und
       verliert seine Warnwirkung, sobald es als vierter Bearbeitungsstand
       mitlaeuft. Wer eine neue Kennzeichnung baut, nimmt eine der drei. */
    --st-grau-flaeche:#f1eee7;  --st-grau-rand:#d9d2c0;  --st-grau-text:#6b6b66;  --st-grau-punkt:#b4b0a6;
    /* Der beige Text war bis zum 07.10.2026 #8a6d1f: auf der beigen Fläche
       4,27:1, auf dem Seitengrund 4,30:1 -- knapp unter den 4,5:1, die
       WCAG 2.2 (1.4.3) für normale Schrift verlangt. Gemessen am Bildschirm,
       nicht geschätzt. #80651c ergibt 4,82:1 und 4,86:1 und sieht aus wie
       vorher. Wer die Fläche ändert, misst den Text dazu. */
    --st-beige-flaeche:#faeeda; --st-beige-rand:#e8d3a8; --st-beige-text:#80651c; --st-beige-punkt:#c98a12;
    --st-gruen-flaeche:#e7f1ee; --st-gruen-rand:#bcd8d0; --st-gruen-text:#0d6e5f; --st-gruen-punkt:#0d6e5f;
  }
  *{ box-sizing:border-box; }
  html,body{ margin:0; }
  html{ font-size:16px; }
  /* Die Seite selbst scrollt niemals seitwärts. Auf dem Handy hat sich
     bisher beim Schieben der Reiterleiste die ganze Seite mitbewegt —
     Überschrift, Karten, alles — statt nur der Leiste.

     `clip` und nicht `hidden`: `hidden` macht aus dem Element einen
     Scroll-Container, und damit hört `position:sticky` weiter innen auf
     zu funktionieren (die erste Tabellenspalte bliebe nicht mehr
     stehen). `clip` schneidet ab, ohne das zu tun.

     Damit dabei nichts unerreichbar wird, muss jeder wirklich breite
     Inhalt seinen eigenen Scroll-Kasten haben — siehe die Liste bei
     #docList weiter unten und .ptabs. */
  html, body{ overflow-x:clip; }
  body{
    font-family:-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
    background:var(--paper); color:var(--ink); line-height:1.55; min-height:100vh; min-height:100dvh;
  }
  a{ color:var(--green); }
  button{ font:inherit; cursor:pointer; }
  input, select{ font:inherit; }
  textarea{ font:inherit; resize:vertical; box-sizing:border-box; }
  a:focus-visible, button:focus-visible, input:focus-visible, select:focus-visible,
  textarea:focus-visible, [tabindex]:focus-visible{
    outline:2px solid var(--green); outline-offset:2px;
  }

  /* `hidden` muss immer stärker sein als jede Klassenregel.

     Der Browser setzt das Attribut nur mit der Priorität einer
     Element-Regel auf `display:none` -- **jede Klasse mit eigenem
     `display` gewinnt dagegen.** Genau daran hing der leere gelbe Balken,
     den der Inhaber am 13.08.2026 auf jeder Seite sah: `.avv-bar` steht
     auf `display:flex`, `bar.hidden = true` blieb dadurch wirkungslos, und
     übrig blieb ein Kasten ohne Inhalt.

     Deshalb hier einmal zentral statt je Klasse. Ein `!important` ist hier
     richtig: `hidden` bedeutet „nicht anzeigen", und dagegen soll sich
     nichts durchsetzen können. */
  [hidden]{ display:none !important; }

  /* ---------- Bausteine ---------- */
  .btn{
    border:1px solid var(--gruen-fill); background:var(--gruen-fill); color:#fff;
    border-radius:8px; padding:10px 18px; font-weight:600;
  }
  a.btn{ text-decoration:none; }
  .btn:hover{ filter:brightness(1.06); }
  .btn:disabled{ opacity:0.55; cursor:default; }
  /* Ein Druck antwortet sofort, auch bevor die Maske oder Antwort da ist. */
  .btn, .linkbtn, .chip-btn{ touch-action:manipulation; }
  @media (prefers-reduced-motion: no-preference){
    .btn, .chip-btn{ transition:transform .08s ease, filter .12s ease; }
    .btn:active:not(:disabled), .chip-btn:active{ transform:scale(0.97); }
  }
  .btn.ghost{ background:transparent; color:var(--green); }
  .btn.quiet{ border-color:var(--line); background:var(--karte); color:var(--ink); font-weight:500; }
  .btn.danger{ border-color:var(--red); background:transparent; color:var(--red); }
  /* Die zweite Stufe neben der Hauptaktion: heller Grund, kein Rahmen. */
  .btn.ton{ border-color:transparent; background:var(--green-soft); color:var(--green); }
  .btn.ton:hover{ filter:none; background:color-mix(in srgb, var(--green) 14%, var(--karte)); }
  .field{ display:block; margin-bottom:14px; }
  .field span{ display:block; font-size:0.85rem; color:var(--muted); margin-bottom:4px; }
  .field input, .field select, .field textarea{
    width:100%; padding:10px 12px; border:1px solid var(--line); border-radius:8px; background:var(--karte);
    font:inherit; box-sizing:border-box;
  }
  .field textarea{ resize:vertical; min-height:70px; }
  .search-input{
    display:block; width:100%; max-width:320px; padding:9px 12px; margin:0 0 12px;
    border:1px solid var(--line); border-radius:8px; background:var(--karte); font:inherit;
  }
  .msg{ border-radius:8px; padding:10px 14px; font-size:1rem; margin:12px 0; display:none; }
  .msg.err{ background:var(--rot-flaeche); color:var(--red); border:1px solid var(--rot-rand); }
  .msg.ok{ background:var(--green-soft); color:var(--green); border:1px solid var(--st-gruen-rand); }
  .chip{
    display:inline-block; font-size:0.75rem; font-weight:600; letter-spacing:0.02em;
    background:var(--green-soft); color:var(--green); border-radius:999px; padding:2px 10px;
  }

  /* ---------- Der dritte Zustand: „weiss noch nicht" ----------
     ⚠️ Bis zum 22.08.2026 gab es nur zwei Zustaende: Anmeldemaske oder
     App. Beim Laden war die ANMELDEMASKE sichtbar, und erst wenn
     supabase-js vom CDN da war UND getSession() geantwortet hatte,
     wurde umgeschaltet. Wer angemeldet war, sah also bei JEDEM Neuladen
     erst das Anmeldeformular aufblitzen -- gemeldet als „es haengt kurz
     und dann laedt die Seite".

     Der Ladezustand ist bewusst fast leer: nur die Wortmarke. Ein
     Spinner behauptet Arbeit, wo meist nur ein Lesevorgang aus dem
     localStorage stattfindet; sichtbar wird er nur, wenn es wirklich
     dauert (Einblendung mit Verzoegerung). */
  #bootView{
    min-height:100vh; display:grid; place-items:center;
    background:var(--bg); gap:10px; align-content:center;
  }
  #bootView .wordmark{ font-size:1.6rem; }
  #bootView .boot-hinweis{
    color:var(--muted); font-size:0.9rem; opacity:0;
    animation:bootEin .3s ease 1.2s forwards;
  }
  @keyframes bootEin{ to{ opacity:1; } }
  @media (prefers-reduced-motion: reduce){
    #bootView .boot-hinweis{ animation:none; opacity:1; }
  }
  /* Die Anmeldemaske startet versteckt und wird von render() gezeigt.
     Ohne JavaScript bliebe sonst nur der Ladezustand stehen -- dagegen
     das <noscript> im Markup. */
  #authView{ display:none; }

  /* ---------- Auth-Ansicht: geteilter Auftritt ---------- */
  #authView.an{ min-height:100vh; display:grid; grid-template-columns:minmax(360px, 44%) 1fr; }
  .wordmark{ font-weight:800; font-size:1.35rem; letter-spacing:-0.02em; }
  .wordmark em{ font-style:normal; color:var(--green); }

  .brand-pane{
    background:linear-gradient(165deg, #0e7767 0%, #0d6e5f 45%, #0a5a4e 100%);
    color:#fff; padding:46px 44px; display:flex; flex-direction:column; gap:34px;
  }
  .brand-pane .wordmark{ color:#fff; font-size:1.5rem; }
  .brand-pane .wordmark em{ color:#ffd98e; }
  .brand-head h2{
    font-size:clamp(1.6rem, 2.6vw, 2.15rem); line-height:1.18; letter-spacing:-0.02em; margin:0 0 10px; font-weight:800;
  }
  .brand-head p{ margin:0; color:rgba(255,255,255,0.82); max-width:38ch; }
  .brand-points{ list-style:none; margin:0; padding:0; display:grid; gap:12px; font-size:0.94rem; }
  .brand-points li{ display:flex; gap:10px; align-items:baseline; color:rgba(255,255,255,0.92); }
  .brand-points li::before{ content:"—"; color:#ffd98e; font-weight:700; }

  /* Signatur: die Mappe, in die sich Dokumente einsortieren */
  .filing{ position:relative; width:min(320px, 100%); height:190px; margin-top:auto; }
  .filing .paper{
    position:absolute; left:50%; top:0; width:150px; margin-left:-75px;
    background:var(--karte); color:var(--ink); border-radius:7px; padding:9px 12px;
    font-size:0.74rem; font-weight:600; box-shadow:0 8px 18px rgba(0,0,0,0.18);
    opacity:0; z-index:1; animation:file-in 5.4s infinite ease-in-out;
  }
  .filing .paper small{ display:block; font-weight:400; color:var(--muted); margin-top:2px; }
  .filing .paper:nth-child(2){ animation-delay:1.8s; }
  .filing .paper:nth-child(3){ animation-delay:3.6s; }
  .filing .folder-back, .filing .folder-front{
    position:absolute; left:0; right:0; border-radius:12px;
  }
  .filing .folder-back{
    bottom:8px; height:92px; background:#d9d2c0;
  }
  .filing .folder-back::before{
    content:""; position:absolute; top:-13px; left:0; width:42%; height:14px;
    background:#d9d2c0; border-radius:8px 8px 0 0;
  }
  .filing .folder-front{
    bottom:0; height:76px; z-index:2; background:var(--tab);
    box-shadow:0 -4px 14px rgba(0,0,0,0.08) inset;
    display:flex; align-items:center; justify-content:center;
    color:var(--green); font-weight:700; font-size:0.88rem; letter-spacing:0.01em;
  }
  @keyframes file-in{
    0%   { transform:translateY(-6px) rotate(-4deg); opacity:0; }
    12%  { opacity:1; }
    46%  { transform:translateY(76px) rotate(0deg); opacity:1; }
    62%  { transform:translateY(96px) rotate(0deg); opacity:0; }
    100% { transform:translateY(96px); opacity:0; }
  }
  @media (prefers-reduced-motion: reduce){
    .filing .paper{ animation:none; opacity:0; }
    .filing .paper:first-child{ opacity:1; transform:translateY(40px); }
  }

  .form-pane{ display:flex; align-items:center; justify-content:center; padding:40px 24px; }
  .auth-card{ width:100%; max-width:380px; }
  .auth-card h1{ font-size:1.5rem; margin:0 0 4px; letter-spacing:-0.01em; }
  .auth-card .lead{ color:var(--muted); font-size:0.95rem; margin:0 0 22px; }
  .auth-tabs{ display:flex; gap:4px; margin:0 0 22px; border:1px solid var(--line); border-radius:9px; padding:3px; background:var(--karte); }
  .auth-tabs button{
    flex:1; border:0; background:transparent; border-radius:7px; padding:9px 0; font-weight:600; color:var(--muted);
    min-height:44px; display:flex; align-items:center; justify-content:center;
  }
  .auth-tabs button.active{ background:var(--gruen-fill); color:#fff; }
  .pwd-wrap{ position:relative; }
  .pwd-wrap input{ padding-right:70px; }
  .pwd-toggle{
    position:absolute; right:6px; top:50%; transform:translateY(-50%);
    border:0; background:none; color:var(--green); font-weight:600; font-size:0.82rem; padding:6px 8px;
  }
  .terms{ font-size:0.8rem; color:var(--muted); margin:12px 0 0; display:none; }
  .agb-check{ display:none; align-items:flex-start; gap:9px; margin:14px 0; font-size:0.85rem; color:var(--muted); cursor:pointer; }
  .agb-check input{ width:auto; margin-top:3px; flex:none; min-width:20px; min-height:20px; }
  .agb-check a{ color:var(--muted); text-decoration:underline; }
  /* ⚠️ `.agb-check` ist oben AUSGEBLENDET -- für die Anmeldemaske, wo
     setMode() je Reiter einblendet. In einer Maske gibt es kein setMode:
     dort war jedes Häkchen dieser Klasse unsichtbar (display:none, Höhe 0).
     Betroffen seit ihrem Bau: „Protokoll abschließen" in der Übergabe
     (01.09.2026, live -- ein Übergabeprotokoll ließ sich über die
     Oberfläche nicht abschließen) und alle Häkchen der Schreiben an die
     Mietpartei (14.09.2026, nur Entwicklung). Gefunden am 24.09.2026 beim
     Bau der Wohnungsgeberbestätigung, an der echten Maske gemessen.
     `[hidden]` bleibt wirksam: es steht oben mit !important. */
  .bearbeiten-dialog .agb-check{ display:flex; }
  .auth-alt{ text-align:center; font-size:0.85rem; margin-top:16px; }
  .install-box{ margin-top:14px; text-align:center; }
  .install-box .btn{ width:100%; }
  /* Auf iOS eine Anleitung statt eines Knopfes -- Apple bietet keine
     Schnittstelle zum Ablegen an. Ein Aufklapper, damit die Anmeldung
     nicht von einem Hinweis verdraengt wird, den die meisten schon
     kennen. */
  .install-hilfe{ font-size:0.85rem; color:var(--muted); }
  .install-hilfe summary{ cursor:pointer; color:var(--green); font-weight:600; padding:8px; }
  .install-hilfe p{ margin:6px 0 0; text-align:left; line-height:1.5; }
  .auth-foot{ margin-top:34px; text-align:center; font-size:0.78rem; color:var(--muted); }
  .auth-foot a{ color:var(--muted); }

  @media (max-width:860px){
    #authView.an{ grid-template-columns:1fr; }
    .brand-pane{ padding:28px 24px 22px; gap:18px; }
    .brand-head h2{ font-size:1.4rem; }
    .filing{ width:min(260px, 100%); height:150px; }
  }
  @media (max-width:560px){
    .brand-pane{ padding:24px 20px; gap:14px; }
    .filing{ display:none; }
  }

  /* ---------- App-Rahmen ---------- */
  #appView{ display:none; }
  header{
    display:flex; align-items:center; justify-content:space-between;
    padding:14px 22px; border-bottom:1px solid var(--line); background:var(--karte);
    /* Guertel und Hosentraeger: meldet iOS doch einen Einzug oben
       (Querformat, Dynamic Island), waechst der Kopf mit. Bei
       `default` ist der Wert 0 und die Zeile tut nichts. */
    padding-top:calc(14px + env(safe-area-inset-top));
  }
  .brand{ display:flex; align-items:center; gap:9px; background:none; border:0; padding:0; cursor:pointer; color:inherit; font:inherit; -webkit-tap-highlight-color:transparent; }
  .brand:hover .wordmark{ opacity:0.82; }
  .brand:focus-visible{ outline:2px solid var(--green); outline-offset:3px; border-radius:8px; }
  .logo{ width:28px; height:28px; flex:none; }
  .panel-head{ display:flex; align-items:center; gap:9px; font-weight:700; }
  .panel-head svg{ width:20px; height:20px; color:var(--green); flex:none; }

  /* Aufklapper INNERHALB einer Karte. (Die Pillenschaltfläche `.aufklapp`
     gibt es seit dem 20.10.2026 nicht mehr -- ihre letzten Benutzer,
     Mietkonto und „Neue Abrechnung", sind Masken geworden.)
     Hier trägt die Zusammenfassung dieselbe Gestalt wie ein Kartenkopf,
     nur mit einem Winkel am rechten Rand. */
  .panel-klapp > summary{
    display:flex; align-items:center; gap:9px; font-weight:700;
    cursor:pointer; list-style:none; min-height:44px;
  }
  .panel-klapp > summary::-webkit-details-marker{ display:none; }
  .panel-klapp > summary svg{ width:20px; height:20px; color:var(--green); flex:none; }
  .panel-klapp > summary > span{ flex:1; min-width:0; }
  .panel-klapp > summary::after{
    content:'⌄'; flex:none; color:var(--muted); font-size:0.9rem;
    transition:transform .18s ease;
  }
  .panel-klapp[open] > summary::after{ transform:rotate(180deg); }
  .panel-klapp > summary:hover span{ color:var(--green); }
  @media (prefers-reduced-motion: reduce){ .panel-klapp > summary::after{ transition:none; } }

  /* ---------- Tarife ---------- */
  /* Hinweis auf eine Funktion, die der aktuelle Tarif nicht enthaelt.
     Bewusst freundlich und nicht rot -- es ist kein Fehler des Nutzers. */
  .lock-note{
    display:flex; align-items:center; justify-content:space-between; gap:14px; flex-wrap:wrap;
    background:var(--green-soft); border:1px solid var(--st-gruen-rand); border-radius:10px;
    padding:14px 16px; font-size:0.92rem;
  }
  .lock-note .lock-sub{ color:var(--muted); font-size:0.86rem; margin-top:3px; }

  /* Zwei Spalten statt einer langen Liste von Panels. `.split` fuer einen
     breiten Hauptbereich mit schmalerer Nebenspalte, `.split.even` fuer
     gleichwertige Bereiche. Unter 900px immer einspaltig -- auf dem Handy ist
     Untereinander richtig. */
  .split, .profile-grid{ display:grid; grid-template-columns:minmax(0,1.55fr) minmax(0,1fr); gap:20px; align-items:start; margin-top:20px; }
  .split.even{ grid-template-columns:repeat(auto-fit, minmax(330px,1fr)); }
  .split-col, .profile-col{ display:grid; gap:20px; align-content:start; }
  .split > .panel, .split-col > .panel,
  .profile-grid > .panel, .profile-col > .panel{ margin-top:0; }
  @media (max-width:900px){ .split, .profile-grid, .split.even{ grid-template-columns:1fr; } }

  /* Breite Datentabellen scrollen in ihrem eigenen Kasten, statt aus dem
     Panel herauszulaufen und abgeschnitten zu werden. Betrifft vor allem
     schmale Fenster und die Dokumentenliste mit ihren Aktionsspalten.

     `min-width:0` ist der Teil, der wirklich zählt: ein Kind in einem
     Flex- oder Grid-Kasten hat von Haus aus `min-width:auto` und
     weigert sich damit, unter seine Inhaltsbreite zu schrumpfen. Das
     `overflow-x:auto` läuft dann ins Leere — der Kasten wird breiter
     als der Bildschirm, und geschoben wird die ganze Seite statt der
     Tabelle. Genau das war auf dem Handy zu sehen. */
  #docList, #taxBox, #tenantBox, #trashBox, #inboxArea, #logBox,
  #leaseBox, #caseList, #contactList, #radarBox, #nkPanel{
    min-width:0; max-width:100%;
  }
  /* Nur die Tabelle scrollt, nicht der ganze Kasten. Vorher lag das
     overflow am Kasten — und damit wanderte die Suchleiste darüber beim
     Schieben mit nach links aus dem Bild. */
  .tab-scroll{
    overflow-x:auto; -webkit-overflow-scrolling:touch;
    min-width:0; max-width:100%; margin-top:8px;
  }
  /* Eine Spalte festhalten ist eine Entscheidung des Nutzers, keine
     Vorgabe. Standardmäßig klebt nichts — bei einer Tabelle, die ganz
     auf den Schirm passt, wäre eine klebende Spalte nur ein Schatten
     ohne Zweck.

     Wichtig: Fixieren heißt UMSORTIEREN. `position:sticky` allein wirkt
     nur für die erste Spalte; jede andere klebte zwar bei left:0, läge
     aber hinter den Spalten davor. Die angeheftete Spalte wandert
     deshalb nach vorne — mehrere stapeln sich in der Reihenfolge, in der
     man sie angeheftet hat. */
  /* Überschrift und Nadel bleiben zusammen in einer Zeile. Ohne das
     bricht die Nadel bei knapper Spaltenbreite darunter um und steht
     wie ein eigener Eintrag unter dem Wort (am 12.08.2026 gemeldet:
     „VORGANG" und „GRÖSSE" hatten ihre Nadel eine Zeile tiefer).
     Für Überschriften ist nowrap unbedenklich -- sie sind kurz, und die
     Tabelle scrollt im eigenen Rahmen, statt die Seite aufzuschieben. */
  .tab-scroll th{ position:relative; white-space:nowrap; }
  .pin{
    border:0; background:none; padding:0 0 0 6px; margin:0;
    font-size:0.78rem; line-height:1; cursor:pointer; opacity:0.55;
    display:inline-block; vertical-align:middle; transition:transform .15s ease, opacity .15s ease;
  }
  /* 55 statt 25 % (02.11.2026): so leise war die Nadel für 60+ kaum zu finden. */
  .pin:hover, .pin:focus-visible{ opacity:0.85; }
  /* Angeheftet: die Nadel steht aufrecht statt schräg zu liegen. */
  .pin.an{ opacity:1; transform:rotate(-45deg); }
  @media (prefers-reduced-motion: reduce){ .pin{ transition:none; } }
  .tab-scroll th.fix, .tab-scroll td.fix{
    position:sticky; z-index:2; background:var(--karte);
    max-width:min(46vw, 260px); overflow-wrap:break-word;
  }
  /* Der Schatten nur an der letzten angehefteten Spalte — sonst hätte
     jede ihren eigenen und es sähe nach Streifen aus. */
  .tab-scroll th.fix-rand, .tab-scroll td.fix-rand{
    box-shadow:6px 0 6px -6px rgba(26,26,26,0.18);
  }
  .panel table{ min-width:520px; }
  /* KEIN overflow-wrap:anywhere an den Zellen. Am 11.08. probiert, um
     lange Dateinamen zu bändigen — und damit die Tabelle zerstört:
     „anywhere" erlaubt den Umbruch nach jedem Zeichen, also sinkt die
     Mindestbreite jeder Textspalte auf ein Zeichen. Die automatische
     Tabellenaufteilung gibt den Platz dann den Auswahlfeldern, und
     Überschriften wie GRÖSSE standen buchstabenweise untereinander.
     Richtig ist das Gegenteil: die Spalten behalten ihre Breite, und
     die Tabelle scrollt in ihrem Kasten. */
  .panel td, .panel th{ overflow-wrap:normal; }
  /* Nur der Dateiname darf umbrechen, und zwar an sinnvollen Stellen —
     nach Unterstrich oder Bindestrich, nicht mitten im Wort. */
  .panel td .dateiname{ overflow-wrap:break-word; word-break:normal; }

  /* Die erste Spalte klebte hier bis zum 11.08.2026 fest verdrahtet.
     Gedacht war es gut — auf dem Handy verschwindet sonst die Angabe, an
     der man die Zeile erkennt. In der Praxis klebte sie aber auch dort,
     wo die Tabelle ohnehin ganz auf den Schirm passt, und nahm mit einem
     langen Dateinamen die halbe Breite ein.

     Jetzt entscheidet der Nutzer: ein Klick auf eine Überschrift heftet
     die Spalte an, ein zweiter löst sie wieder. Siehe .tab-scroll th.fix
     weiter oben und tabellenScrollbar() im Skript. */
  /* Die Kopfzeile bleibt beim Hochscrollen oben haengen, damit die
     Spaltenbeschriftung nicht verlorengeht. Braucht z-index ueber den
     Datenzellen, sonst schiebt sich die klebende erste Spalte darueber. */
  .panel table th{ position:sticky; top:0; background:var(--karte); z-index:3; }
  #docList table th:first-child, #tenantBox table th:first-child,
  #trashBox table th:first-child, #inboxArea table th:first-child,
  #logBox table th:first-child{ z-index:4; }

  /* Ziehen und Ablegen: der Hinweis ist dezent, bis eine Datei ueber dem
     Panel schwebt -- dann wird das ganze Feld sichtbar zur Ablageflaeche. */
  .drop-hint{ font-size:0.85rem; color:var(--muted); margin:6px 0 0; }
  #upPanel{ transition:border-color .15s ease, background .15s ease; }
  #upPanel.drop-over{ border-color:var(--green); background:var(--green-soft); }
  #upPanel.drop-over .drop-hint{ color:var(--green); font-weight:600; }
  @media (prefers-reduced-motion: reduce){ #upPanel{ transition:none; } }

  /* Vorschau: Datei ansehen, ohne die App zu verlassen. */
  .preview-back{
    position:fixed; inset:0; background:rgba(26,26,26,0.55); z-index:1600;
    display:flex; align-items:center; justify-content:center; padding:24px;
  }
  .preview-box{
    background:var(--karte); border-radius:14px; width:min(1000px, 100%); height:min(90vh, 100%);
    display:flex; flex-direction:column; overflow:hidden; box-shadow:0 18px 50px rgba(0,0,0,0.28);
  }
  .preview-head{
    display:flex; align-items:center; justify-content:space-between; gap:12px;
    padding:12px 16px; border-bottom:1px solid var(--line);
  }
  .preview-name{ font-weight:700; font-size:0.95rem; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .preview-body{ flex:1; min-height:0; background:var(--cream); }
  /* ---------- Mieteranliegen als Nachrichtenkarten (13.08.2026) ----------
     Vorher eine Tabelle mit sechs Spalten. Die Meldung -- der Inhalt, um
     den es geht -- bekam wenige Zentimeter, Datum und Status je eine
     volle Spalte, und rechts musste man scrollen, um an „Antworten" zu
     kommen. Eine Nachricht liest man aber nicht spaltenweise.

     Jetzt eine Karte je Meldung: oben wer und wann, in der Mitte der
     Text, unten was man tun kann. Der farbige linke Rand zeigt den
     Bearbeitungsstand, ohne dass man ihn lesen muss. */
  .anliegen-liste{ display:grid; gap:12px; }
  .anliegen-karte{
    background:var(--karte); border:1px solid var(--line); border-left:4px solid var(--line);
    border-radius:10px; padding:14px 16px;
  }
  /* Bis zum 18.08.2026 war das hier genau andersherum als bei den
     Vorgaengen: neu war gelb, "in Arbeit" gruen, erledigt blass grau.
     Dieselbe Farbe bedeutete also je nach Liste etwas anderes. Jetzt
     ueberall dieselbe Skala -- grau, beige, gruen. */
  .anliegen-karte.st-neu{ border-left-color:var(--st-grau-punkt); }
  .anliegen-karte.st-in_arbeit{ border-left-color:var(--st-beige-punkt); }
  .anliegen-karte.st-erledigt{ border-left-color:var(--st-gruen-punkt); }

  .ak-kopf{ display:flex; justify-content:space-between; gap:12px; flex-wrap:wrap; align-items:flex-start; }
  .ak-wer{ display:flex; flex-direction:column; min-width:0; }
  .ak-kontakt{ font-size:0.8rem; color:var(--muted); overflow-wrap:break-word; }
  /* Schrumpfen erlaubt (07.11.2026): mit flex:none blieb die Gruppe so breit wie alle Marken in
     einer Reihe, und mit „Notfall" ragte das Datum bei 320 px über die Karte. Umgebrochen wird
     trotzdem zuerst die ganze Gruppe -- die Zeile bricht nach der Grundbreite. */
  .ak-rechts{ display:flex; align-items:center; gap:8px; flex-wrap:wrap; flex:0 1 auto; min-width:0; }
  .ak-datum{ font-size:0.8rem; color:var(--muted); font-variant-numeric:tabular-nums; }

  .anliegen-text{
    margin:10px 0 0; white-space:pre-wrap; overflow-wrap:break-word;
    /* Vier Zeilen: in einer Karte ist mehr Platz als in einer Tabellenzelle,
       aber eine Meldung darf die nächste nicht aus dem Bild schieben. */
    display:-webkit-box; -webkit-line-clamp:4; -webkit-box-orient:vertical;
    overflow:hidden;
  }
  .anliegen-text.offen{ -webkit-line-clamp:unset; overflow:visible; }
  .anliegen-mehr{ padding:2px 0; font-size:0.82rem; }
  /* Freiwillige Angaben der Mietpartei (07.11.2026): eine Zeile über der Beschreibung. */
  .ak-fakten{ margin:8px 0 0; font-size:0.84rem; color:var(--muted); overflow-wrap:break-word; }
  /* Auf --rot-fill steht Weiss (Kopf der Datei); --auf-tinte waere im Dunkeln fast schwarz, 3,3:1. */
  .chip.ak-notfall{ background:var(--rot-fill); color:#fff; font-weight:700; }
  .chip.ak-eilt{ background:var(--st-beige-flaeche); color:var(--st-beige-text); font-weight:600; }
  .ak-fotohinweis{ font-size:0.78rem; color:var(--muted); margin-top:4px; }
  /* Sprachnachricht der Mietpartei (Migration 100) */
  .ak-ton{ margin-top:10px; }
  .ak-ton audio{ display:block; width:100%; max-width:420px; }

  .ak-fuss{
    display:flex; justify-content:space-between; gap:12px; flex-wrap:wrap; align-items:center;
    margin-top:14px; padding-top:12px; border-top:1px solid var(--line);
  }
  .ak-status{ display:flex; align-items:center; gap:8px; flex:none; }
  .ak-status > span{ font-size:0.78rem; text-transform:uppercase; letter-spacing:0.05em; color:var(--muted); }
  .ak-status select{
    padding:7px 10px; border:1px solid var(--line); border-radius:8px; background:var(--karte); font:inherit;
    font-size:0.88rem; width:auto;
  }
  .ak-tun{ display:flex; gap:4px; flex-wrap:wrap; align-items:center; }

  /* ---------- Fremde Maildienste in ihrer eigenen Farbe ----------
     Wer sein Postfach bei Gmail hat, findet den richtigen Knopf schneller
     an der Farbe als am Wort. Der Versand **über Zetaro** bleibt bewusst
     im Zetaro-Grün: die Farbe sagt hier, wessen Weg man nimmt.

     Bewusst nur die Farbe, keine Logos. Ein Markenzeichen auf einer
     Schaltfläche kann nach Zusammenarbeit aussehen; ein farbiger Knopf mit
     dem blossen Namen ist eine Wegbeschreibung. Die Beschriftung bleibt
     deshalb Text und wird nicht durch ein Zeichen ersetzt.

     Nur ein farbiger Rand mit farbiger Schrift, keine Vollfläche: sonst
     stünden drei kräftige Blöcke neben dem einen grünen Knopf, der
     wirklich etwas auslöst, und zögen die Aufmerksamkeit auf sich. */
  .btn.dienst{
    background:var(--karte); border:1.5px solid currentColor; font-weight:600;
    text-decoration:none;
  }
  .btn.dienst:hover, .btn.dienst:focus-visible{ background:color-mix(in srgb, currentColor 8%, var(--karte)); }
  .btn.dienst.gmail{ color:#c5221f; }     /* Gmail-Rot, etwas abgedunkelt für Kontrast */
  .btn.dienst.outlook{ color:#0f6cbd; }   /* Outlook-Blau */
  .btn.dienst.yahoo{ color:#5f01d1; }     /* Yahoo-Violett */
  /* Dieselbe Idee für die Immobilienportale: wer bei Kleinanzeigen
     inseriert, findet den Knopf an der Farbe schneller als am Wort.
     Wieder nur Farbe und Name, keine Logos -- ein Markenzeichen auf einer
     Schaltfläche kann nach Zusammenarbeit aussehen.

     Die Töne folgen dem wiedererkennbaren Markenton und sind für den
     Kontrast auf Weiss abgedunkelt, wie schon beim Gmail-Rot. Beim
     dritten zählt vor allem, dass sich die drei auf einen Blick trennen
     lassen; eine exakte Markendefinition wird hier nicht behauptet. */
  /* Der fertige Anzeigentext als eigener, sichtbar gerahmter Kasten --
     nicht als nacktes Eingabefeld zwischen zwei Knöpfen. Er ist das
     Ergebnis der ganzen Maske und soll auch so aussehen. */
  /* Die Vorschau des Inseratstexts. Reiner Text, kein Formularfeld --
     Begründung im Markup. `pre-wrap` behält die Absätze des erzeugten
     Textes, ohne dass lange Zeilen aus dem Kasten laufen. */
  .txt-kopfzeile{
    display:flex; align-items:center; justify-content:space-between;
    gap:10px; margin-bottom:8px; font-size:0.82rem; color:var(--muted);
    font-variant-numeric:tabular-nums;
  }
  .txt-vorschau{
    white-space:pre-wrap; overflow-wrap:break-word;
    background:var(--karte); border:1px solid var(--line); border-radius:10px;
    padding:14px 16px; font-size:0.9rem; line-height:1.6;
    max-height:46vh; overflow-y:auto;
  }
  .txt-vorschau:empty::before{
    content:'Noch kein Text erzeugt.'; color:var(--muted);
  }
  /* Das Textfeld, das neben jeder .txt-vorschau liegt und beim
     Bearbeiten an ihre Stelle tritt.
     ⚠️ Bis zum 22.08.2026 gab es dafuer GAR KEINE Regel. Ein <textarea>
     ist von Haus aus inline und `cols=20` breit -- der Kuendigungstext
     brach deshalb nach zwei bis drei Woertern um, und "Aenderung
     uebernehmen" stand daneben statt darunter, weil ein inline-Element
     den Knopf in dieselbe Zeile zieht. Aufgefallen ist es nie, weil man
     das Feld erst nach einem Klick aufs Zahnrad zu sehen bekommt.
     Betroffen waren alle drei erzeugten Texte: Kuendigung, Inserat und
     Handwerker-Anfrage. */
  .txt-vorschau + textarea{
    display:block; width:100%; box-sizing:border-box;
    background:var(--karte); border:1px solid var(--line); border-radius:10px;
    padding:14px 16px; font:inherit; font-size:0.9rem; line-height:1.6;
    min-height:46vh; resize:vertical;
  }
  .ad-ergebnis{
    border:1px solid var(--st-gruen-rand); border-radius:10px;
    background:var(--st-gruen-flaeche); padding:12px 13px;
  }
  .ad-ergebnis-kopf{
    display:flex; align-items:baseline; justify-content:space-between; gap:10px;
    margin-bottom:8px;
  }
  .ad-ergebnis-kopf strong{ font-size:0.93rem; color:var(--green); }
  .ad-ergebnis-kopf span{ font-size:0.8rem; color:var(--muted); font-variant-numeric:tabular-nums; }
  .ad-ergebnis textarea{
    display:block; width:100%; box-sizing:border-box;
    padding:12px; border:1px solid var(--st-gruen-rand); border-radius:8px;
    background:var(--karte); font:inherit; font-size:0.9rem; line-height:1.55;
  }
  .ad-ergebnis-fuss{ font-size:0.8rem; color:var(--muted); margin:8px 0 0; }
  .btn.dienst.kleinanzeigen{ color:#3f8f1f; }
  .btn.dienst.is24{ color:#c2410c; }
  .btn.dienst.immowelt{ color:#0b4f9e; }
  #rqMail{ text-decoration:none; }

  /* Die laufende Version im Konto-Menü -- unauffällig, aber ablesbar. */
  .account-dropdown .stand-zeile{
    border-top:1px solid var(--line); margin-top:4px; padding-top:8px;
    font-size:0.76rem; color:var(--muted); font-variant-numeric:tabular-nums;
  }

  /* ---------- Zwei-Faktor im Profil ---------- */
  .mfa-box{ margin-top:14px; }
  .mfa-an, .mfa-aus{
    display:flex; align-items:center; justify-content:space-between; gap:14px; flex-wrap:wrap;
    border:1px solid var(--line); border-radius:10px; padding:12px 14px;
  }
  .mfa-an{ background:var(--green-soft); border-color:var(--st-gruen-rand); }
  .mfa-sub{ font-size:0.82rem; color:var(--muted); margin-top:3px; max-width:44ch; }
  /* Der Kasten fuer die Wiederherstellungscodes haengt unter dem
     Zwei-Faktor-Kasten und ist bewusst ruhig gehalten: er ist kein
     Fehler und keine Warnung, sondern eine Vorsorge, die man einmal
     trifft. */
  .mfa-wh{ margin-top:10px; padding:12px 14px; border:1px solid var(--line);
           border-radius:10px; background:var(--paper); }
  .mfa-wh .mfa-sub{ margin:3px 0 10px; }
  /* Die Codes selbst: gesperrt gesetzt und mit Ziffernbreite, damit man
     sie vom Bildschirm abschreiben kann, ohne sich zu verlesen. */
  .wh-codes{ font-family:ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
             font-size:1.05rem; line-height:2; letter-spacing:0.08em;
             background:var(--paper); border:1px solid var(--line);
             border-radius:10px; padding:14px 16px; margin:0 0 14px;
             white-space:pre; overflow-x:auto; }
  .mfa-qr{ display:flex; justify-content:center; padding:10px; background:#fff; border:1px solid var(--line); border-radius:10px; }
  .mfa-qr img{ display:block; width:200px; height:200px; }
  .mfa-secret{
    display:block; background:var(--tab); border-radius:8px; padding:9px 11px;
    font-size:0.85rem; letter-spacing:0.08em; word-break:break-all;
  }
  /* Zwei Wege nebeneinander (28.09.2026): Code aus einer App und
     Face ID / Touch ID. Ruhig gehalten wie der Kasten der Codes. */
  .mfa-wege{ margin-top:10px; display:grid; gap:8px; }
  .mfa-weg{ display:flex; align-items:center; justify-content:space-between; gap:12px; flex-wrap:wrap;
            padding:12px 14px; border:1px solid var(--line); border-radius:10px; background:var(--paper); }
  .mfa-weg > div{ flex:1 1 220px; min-width:0; }
  .mfa-geraet-weg{ padding:4px 0; margin-right:14px; font-size:0.84rem; }
  .mfa-schluessel{ display:flex; gap:8px; align-items:stretch; }
  .mfa-schluessel .mfa-secret{ flex:1; min-width:0; }
  .mfa-tipp{ font-size:0.8rem; color:var(--muted); margin:-4px 0 12px; }
  .mfa-oder{ display:flex; align-items:center; gap:10px; margin:16px 0 10px; font-size:0.82rem; color:var(--muted); }
  .mfa-oder::before, .mfa-oder::after{ content:""; flex:1; height:1px; background:var(--line); }
  .mfa-symbol{ width:18px; height:18px; flex:none; margin-right:8px; vertical-align:-4px; }
  a.btn .mfa-symbol, button.btn .mfa-symbol{ display:inline-block; }

  /* ---------- Bestellübersicht (§ 312j BGB) ----------
     Bewusst nüchtern und ohne Werbung: hier wird eine rechtsverbindliche
     Erklärung abgegeben, und alles, was davon ablenkt, ist an dieser
     Stelle ein Risiko. */
  .bestell-dialog{
    border:0; border-radius:16px; padding:24px; max-width:min(94vw, 540px);
    background:var(--karte); color:var(--ink); box-shadow:0 24px 60px rgba(26,26,26,0.28);
  }
  .bestell-dialog::backdrop{ background:rgba(26,26,26,0.45); }
  .bestell-dialog h3{ margin:0 0 16px; font-size:1.15rem; }
  .bestell-zeile{
    display:flex; justify-content:space-between; gap:14px; align-items:baseline;
    padding:9px 0; border-bottom:1px solid var(--line); font-size:0.92rem;
  }
  .bestell-zeile span{ color:var(--muted); flex:none; }
  .bestell-zeile strong{ text-align:right; }
  .bestell-ust{ font-size:0.82rem; color:var(--muted); margin:10px 0 4px; }
  .bestell-liste{ margin:8px 0 0; padding-left:20px; font-size:0.86rem; color:var(--muted); }
  .bestell-liste li{ margin-bottom:4px; }
  .bestell-haken{
    display:flex; gap:10px; align-items:flex-start; margin:6px 0 12px;
    font-size:0.85rem; line-height:1.5; cursor:pointer;
  }
  .bestell-haken input{ margin-top:3px; flex:none; width:auto; }
  .bestell-recht{ font-size:0.8rem; color:var(--muted); margin:0 0 18px; }
  .bestell-knoepfe{ display:flex; gap:10px; flex-wrap:wrap; }
  .bestell-knoepfe .btn:disabled{ opacity:0.45; cursor:not-allowed; }

  /* ---------- Kopfzeile einer Liste: Suche und Filter ----------
     Beide stehen ausserhalb des Scroll-Rahmens der Tabelle, sonst wandern
     sie beim seitlichen Schieben mit aus dem Bild. */
  .listen-kopf{
    display:flex; gap:10px; align-items:center; flex-wrap:wrap; margin-bottom:12px;
  }
  .listen-kopf .search-input{ flex:1; min-width:190px; margin:0; }
  .filter-chips{ display:flex; gap:6px; flex-wrap:wrap; }
  .chip-btn{
    display:inline-flex; align-items:center; gap:6px;
    padding:7px 12px; min-height:38px;
    border:1px solid var(--line); border-radius:999px; background:var(--karte);
    font-size:0.85rem; font-weight:600; color:var(--muted); cursor:pointer;
  }
  .chip-btn span{
    font-variant-numeric:tabular-nums; font-weight:700;
    background:var(--line); color:var(--ink);
    border-radius:999px; padding:1px 7px; font-size:0.78rem;
  }
  /* Der Interessenten-Postkorb. Der Eingangsstempel ist derselbe wie im
     Posteingang -- links der Tag, rechts was daraus wurde. Kantig und um
     zwei Grad gedreht: er zitiert den Posteingangsstempel auf Papier,
     nicht einen Statuspunkt. */
  /* Der Aufklapper in einer beendeten Vertragskarte. Randlos, weil er
     schon in der Karte steckt -- ein zweiter Rahmen darin sieht aus wie
     eine zweite Karte. */
  /* Der Kontaktweg am Fuss jeder Erklaerung. Abgesetzt, damit er nicht
     wie ein Teil des Hilfetexts aussieht, aber sichtbar -- wer die
     Erklaerung aufschlaegt, hat schon gesucht und nicht gefunden. */
  .hilfe-support{
    margin:18px 0 0; padding-top:13px; border-top:1px solid var(--line);
    font-size:0.88rem; color:var(--muted);
  }
  .hilfe-support a{
    display:inline-flex; align-items:center; gap:5px;
    color:var(--green); font-weight:600; text-decoration:none; margin-left:4px;
  }
  .hilfe-support a:hover{ text-decoration:underline; }
  .hilfe-support > span{
    display:block; margin-top:5px; font-size:0.82rem;
  }
  .hilfe-support > span a{ font-weight:400; margin-left:0; }

  .vk-klapp{ border:0; background:none; padding:0; margin:0; }
  .vk-klapp > summary{
    border-top:1px solid var(--line); border-radius:0;
    padding:11px 2px; font-size:0.88rem; color:var(--muted);
  }
  .vk-klapp[open] > summary{ color:var(--ink); }

  .pk-karte{ padding:14px 16px; }
  .pk-liste{ list-style:none; margin:10px 0 0; padding:0; }
  .pk-zeile{
    display:flex; align-items:flex-start; gap:12px;
    padding:10px 0; border-top:1px solid var(--line);
  }
  .pk-zeile:first-of-type{ border-top:0; }
  .pk-zeile[hidden]{ display:none; }
  .pk-stempel{
    flex:none; width:46px; text-align:center; padding:3px 0;
    border:1.5px solid var(--st-grau-rand); border-radius:3px;
    transform:rotate(-2deg); line-height:1.15;
  }
  .pk-stempel span{ display:block; font-size:0.62rem; letter-spacing:0.1em; color:var(--muted); }
  .pk-stempel strong{ display:block; font-size:1.02rem; font-variant-numeric:tabular-nums; }
  @media (prefers-reduced-motion: reduce){ .pk-stempel{ transform:none; } }
  .pk-text{ flex:1; min-width:0; }
  .pk-kopf{ display:flex; align-items:center; gap:7px; flex-wrap:wrap; }
  .pk-text > span{ display:block; font-size:0.83rem; color:var(--muted); overflow-wrap:break-word; }
  .pk-text em{ font-style:normal; }
  .pk-notiz{ display:block; font-size:0.83rem; color:var(--ink); margin-top:3px; }
  .pk-umschalt{ margin-left:auto; padding:5px 0; font-size:0.85rem; }
  .pk-vergleich{ margin-top:10px; }
  .pk-leer{ margin:12px 0 0; font-size:0.86rem; color:var(--muted); }
  /* Der Satz zur Datensparsamkeit steht sichtbar in der Karte, nicht in
     einem Hilfetext: er begruendet, warum hier Felder FEHLEN, die andere
     Anwendungen anbieten. */
  .pk-recht{
    margin:14px 0 0; padding-top:11px; border-top:1px solid var(--line);
    font-size:0.82rem; color:var(--muted); line-height:1.55;
  }

  /* Eine Meldung, die man beheben kann: Satz links, Weg rechts.
     Vorher eine Aufzaehlung in einem roten Kasten -- man musste die
     Stelle selbst suchen, und bei der Wohnflaeche gab es sie nicht. */
  .nk-meldung{
    display:flex; align-items:flex-start; justify-content:space-between;
    gap:12px; flex-wrap:wrap; margin-top:10px;
    background:#fdeeee; border:1px solid #f0c9c9; border-radius:10px;
    padding:11px 13px; font-size:0.88rem; color:#8a2b2b;
  }
  .nk-meldung > span{ flex:1; min-width:200px; }
  .nk-meldung .nk-fix{ flex:none; padding:6px 12px; font-size:0.84rem; }
  .nk-blocker-kopf{ margin:0 0 2px; font-weight:700; color:#8a2b2b; font-size:0.9rem; }
  /* Die angesprungene Kostenposition leuchtet kurz auf -- sonst weiss man
     nach dem Sprung nicht, welche Zeile gemeint war. */
  tr.hervor > td{ background:var(--st-beige-flaeche); transition:background 0.6s; }

  /* Die Stammdaten einer Einheit. Bis zum 19.08.2026 gab es dafuer kein
     Feld -- die Spalten waren pflegbar und wurden gelesen, nur nie
     eingegeben. */
  .eh-zeile{
    display:flex; align-items:center; gap:11px;
    background:var(--karte); border:1px solid var(--line); border-radius:10px;
    padding:10px 13px; margin-bottom:10px;
  }
  .eh-zeile.offen{ background:var(--st-beige-flaeche); border-color:var(--st-beige-rand); }
  .eh-text{ flex:1; min-width:0; }
  .eh-text strong{ display:block; font-size:0.92rem; }
  .eh-text span{ display:block; font-size:0.83rem; color:var(--muted); }
  .eh-zeile.offen .eh-text em{ font-style:normal; color:var(--st-beige-text); font-weight:600; }
  .fz-unter{ display:block; font-size:0.83rem; color:var(--muted); margin-top:2px; }
  .flaeche-zeile.offen{ background:var(--st-beige-flaeche); border-color:var(--st-beige-rand); }
  .pk-zahl{
    display:inline-block; margin-left:6px; padding:1px 8px; border-radius:999px;
    background:var(--st-grau-flaeche); color:var(--st-grau-text);
    font-size:0.76rem; font-weight:700; font-variant-numeric:tabular-nums;
  }

  /* Auswahlfelder ausserhalb einer .field-Huelle. Acht Stueck trugen
     dieselben sechs Regeln als Inline-Stil, in vier leicht verschiedenen
     Fassungen (5, 6 oder 8 px Innenabstand, drei Hoechstbreiten) -- so
     entsteht Uneinheitlichkeit: nicht durch eine Entscheidung, sondern
     dadurch, dass jede Stelle ihre Werte selbst nochmal hinschreibt. */
  .wahlfeld{
    padding:8px 10px; border:1px solid var(--line); border-radius:8px;
    background:var(--karte); font-size:0.9rem; max-width:230px;
  }
  /* In einer Tabellenzelle: enger, kleiner, und schrumpffaehig -- ohne
     min-width:0 sprengt ein langer Optionstext die Spalte. */
  .wahlfeld.zelle{
    padding:6px 8px; font-size:0.85rem; max-width:190px;
    flex:0 1 auto; min-width:0;
  }
  .wahlfeld:disabled{ background:var(--tab); color:var(--muted); }
  /* Die Betriebskostenart in der Belegliste: Auswahl und das kleine i in
     einer Zeile. Bis zum 10.10.2026 als Inline-Stil am Element -- der schlug
     jede Regel fürs Handy, auch die, die das Feld in der zugeklappten Karte
     ausblendet. */
  .bk-zelle{ margin-top:6px; display:flex; align-items:center; gap:6px; flex-wrap:nowrap; }
  .bk-vorschlag{ margin-top:2px; }
  .bescheid-datum{ display:flex; align-items:center; gap:6px; flex-wrap:nowrap; }

  /* „bezahlt am" in Belegliste und Posteingang (Migration 060): ein
     sichtbares Wort über dem Feld -- ein Datumsfeld ohne Beschriftung unter
     dem Ablagedatum sagt nicht, welches Datum es will. */
  .bezahlt-feld{
    display:flex; flex-direction:column; align-items:flex-start; gap:3px;
    margin-top:6px; font-size:0.78rem; color:var(--muted);
  }

  /* „Maske leeren" -- klein, und am FUSS der Maske ganz rechts. Es ist
     kein Ziel, sondern ein Ausweg; in Aktionsgroesse direkt neben dem
     Hauptknopf waere es eine Einladung zum Fehlgriff -- deshalb schiebt
     margin-left:auto es von den Aktionen weg an den rechten Rand.
     Trotzdem MIT Text: die Zielgruppe ist ausdruecklich auch 60+, und
     ein Symbol allein ist eine Vokabel, die man raten muss.

     Bis zum 13.09.2026 stand es OBEN, rechts neben dem Einleitungssatz.
     Beanstandet: „da kommt der Text und dann direkt daneben der Button"
     -- es las sich wie ein Teil des Satzes. Am Fuss steht es dort, wo
     man mit der Maske fertig ist oder von vorn anfangen will. */
  .masken-fuss{ display:flex; align-items:center; gap:8px; flex-wrap:wrap; margin-top:16px; }
  .masken-fuss > .leeren-knopf{ margin-left:auto; }
  .leeren-knopf{
    flex:none; display:inline-flex; align-items:center; gap:5px;
    background:none; border:0; padding:2px 0;
    font-size:0.8rem; color:var(--muted); cursor:pointer;
  }
  .leeren-knopf:hover{ color:var(--green); text-decoration:underline; }

  /* Eine Standmarke fuer Tabellenzellen -- Farben aus der Skala, kein
     neuer Hex-Wert. Grau: noch nichts passiert. Beige: in Arbeit. Gruen:
     erledigt. Wer eine weitere Kennzeichnung baut, nimmt diese hier. */
  .stand-marke{
    display:inline-block; padding:2px 9px; border-radius:999px;
    font-size:0.75rem; font-weight:700; white-space:nowrap;
    background:var(--st-grau-flaeche); color:var(--st-grau-text);
    border:1px solid var(--st-grau-rand);
  }
  .stand-marke.beige{ background:var(--st-beige-flaeche); color:var(--st-beige-text); border-color:var(--st-beige-rand); }
  .stand-marke.gruen{ background:var(--st-gruen-flaeche); color:var(--st-gruen-text); border-color:var(--st-gruen-rand); }

  /* Kennzahlen sehen aus wie Chips, sind aber keine Schaltflaechen --
     deshalb ohne Hover, ohne Zeigefinger und ohne den `an`-Zustand. */
  .kennzahlen{ display:flex; gap:6px; flex-wrap:wrap; margin-bottom:12px; }
  .kennzahl{
    display:inline-flex; align-items:center; gap:6px;
    padding:7px 12px; min-height:38px;
    border:1px solid var(--line); border-radius:999px; background:var(--tab);
    font-size:0.85rem; font-weight:600; color:var(--muted);
  }
  .kennzahl span{
    font-variant-numeric:tabular-nums; font-weight:700; color:var(--ink);
  }
  .chip-btn:hover{ border-color:var(--green); color:var(--green); }
  .chip-btn.an{ background:var(--gruen-fill); border-color:var(--gruen-fill); color:#fff; }
  /* Die Zahl am gewählten Filter: weiß mit grüner Schrift (6,15:1). Bis zum
     08.10.2026 stand sie weiß auf einem Viertel Weiß über Grün -- gemessen
     3,64:1 bei 12 px, zu wenig (WCAG 1.4.3). */
  .chip-btn.an span{ background:var(--karte); color:var(--green); }

  /* ---------- Auswahlliste am Textfeld ----------
     Der Rahmen muss `position:relative` sein, damit die Liste am Feld
     klebt und nicht an der Seite. Genau das ging beim nativen <datalist>
     nicht -- dessen Aufklappfeld zeichnet der Browser selbst. */
  .combo{ position:relative; display:block; }
  .combo-liste{
    position:absolute; left:0; right:0; top:100%; z-index:40;
    margin:4px 0 0; padding:4px; list-style:none;
    max-height:240px; overflow-y:auto;
    background:var(--karte); border:1px solid var(--line); border-radius:10px;
    box-shadow:0 10px 24px rgba(26,26,26,0.12);
  }
  .combo-liste[hidden]{ display:none; }
  .combo-liste li{
    padding:9px 11px; border-radius:7px; cursor:pointer; font-size:0.92rem;
  }
  .combo-liste li:hover, .combo-liste li.an{ background:var(--green-soft); color:var(--green); }

  .vorschau-laedt{
    display:flex; align-items:center; justify-content:center; height:100%;
    color:var(--muted); font-size:0.9rem;
  }
  .preview-body iframe, .preview-body img{ width:100%; height:100%; border:0; display:block; object-fit:contain; }
  @keyframes preview-in{ from{ opacity:0; } to{ opacity:1; } }
  .preview-back{ animation:preview-in .15s ease; }
  @media (prefers-reduced-motion: reduce){ .preview-back{ animation:none; } }

  /* Zugeklappte Assistenten sollen als anklickbare Zeile erkennbar sein und
     nicht wie eine tote Ueberschrift wirken. */
  details.panel > summary{
    cursor:pointer; list-style:none; display:flex; align-items:center;
    justify-content:space-between; gap:10px;
  }
  details.panel > summary::-webkit-details-marker{ display:none; }
  details.panel > summary::after{
    content:'▾'; color:var(--muted); font-size:0.8rem; transition:transform .15s ease;
  }
  details.panel[open] > summary::after{ transform:rotate(180deg); }
  details.panel:not([open]) > summary:hover{ color:var(--green); }
  details.panel[open] > summary{ margin-bottom:2px; }
  @media (prefers-reduced-motion: reduce){ details.panel > summary::after{ transition:none; } }

  /* Bewegung nur dort, wo sie etwas erklaert: Inhalte, die neu erscheinen,
     kommen von unten herein statt zu blinken. Reihum leicht versetzt, damit
     das Auge der Reihenfolge folgt. */
  @keyframes rise-in{ from{ opacity:0; transform:translateY(7px); } to{ opacity:1; transform:none; } }
  .ptab-sec.active{ animation:rise-in .2s ease both; }
  .tiles > *, .folders > *, .case-cards > *, .tier-cards > *{ animation:rise-in .3s ease both; }
  .tiles > *:nth-child(2), .folders > *:nth-child(2), .case-cards > *:nth-child(2), .tier-cards > *:nth-child(2){ animation-delay:.04s; }
  .tiles > *:nth-child(3), .folders > *:nth-child(3), .case-cards > *:nth-child(3), .tier-cards > *:nth-child(3){ animation-delay:.08s; }
  .tiles > *:nth-child(4), .folders > *:nth-child(4), .case-cards > *:nth-child(4){ animation-delay:.12s; }
  .tiles > *:nth-child(5), .folders > *:nth-child(5), .case-cards > *:nth-child(5){ animation-delay:.16s; }
  .tiles > *:nth-child(n+6), .folders > *:nth-child(n+6), .case-cards > *:nth-child(n+6){ animation-delay:.2s; }

  /* Erfolgs- und Fehlermeldungen wechseln von display:none auf block --
     dabei startet die Animation von selbst, ohne Zutun im JavaScript. */
  @keyframes msg-in{ from{ opacity:0; transform:translateY(-4px); } to{ opacity:1; transform:none; } }
  .msg{ animation:msg-in .2s ease; }

  @media (prefers-reduced-motion: reduce){
    .ptab-sec.active, .tiles > *, .folders > *, .case-cards > *, .tier-cards > *, .msg{ animation:none; }
  }
  .tier-cards{ display:grid; grid-template-columns:repeat(auto-fit, minmax(200px,1fr)); gap:14px; margin-top:14px; }
  .tier-card{ border:1px solid var(--line); border-radius:12px; padding:16px 18px; display:flex; flex-direction:column; gap:8px; }
  .tier-card.featured{ border-color:var(--green); box-shadow:0 0 0 1px var(--green) inset; }
  .tier-hero{ background:linear-gradient(135deg, var(--green-soft), var(--karte)); border:1px solid var(--st-gruen-rand); border-radius:14px; padding:20px 22px; margin-top:14px; }
  .tier-hero-top{ display:flex; align-items:baseline; justify-content:space-between; flex-wrap:wrap; gap:8px; }
  .tier-hero-name{ font-size:1.25rem; font-weight:800; color:var(--green); letter-spacing:-0.01em; }
  /* „Ihr Tarif": so heißt die Stelle in den AGB (§ 3 Abs. 2, § 4 Abs. 1). */
  .tier-hero-label{ font-size:0.78rem; font-weight:600; color:var(--muted); letter-spacing:0; margin-bottom:2px; }
  .tier-hero-price{ font-weight:700; color:var(--green); font-size:0.95rem; }
  /* Der Kündigungs- bzw. Abbuchungshinweis im Tarifkasten.
     Farben aus der Skala, kein neuer Hex-Wert: beige heisst „in
     Arbeit" -- eine Kündigung läuft noch --, grün heisst „alles in
     Ordnung". KEIN ROT: eine Kündigung ist kein Fehler, sondern eine
     Entscheidung des Nutzers. Rot ist hier für fehlendes Geld und
     ablaufende Fristen reserviert und verlöre sonst seine Wirkung. */
  .abo-hinweis{
    margin-top:12px; padding:10px 13px; border-radius:10px;
    font-size:0.9rem; line-height:1.55;
  }
  .abo-hinweis.gekuendigt{
    background:var(--st-beige-flaeche); border:1px solid var(--st-beige-rand);
    color:var(--st-beige-text);
  }
  .abo-hinweis.laeuft{
    background:var(--st-gruen-flaeche); border:1px solid var(--st-gruen-rand);
    color:var(--st-gruen-text);
  }
  .abo-hinweis-klein{ margin-top:6px; font-size:0.84rem; }
  /* Beige und nicht gruen: ein geschenkter Tarif ist kein Fehler und
     kein Erfolg, sondern ein Zustand, den jemand anderes gesetzt hat. */
  .tier-geschenkt{
    margin:10px 0 0; padding:10px 12px; border-radius:9px;
    background:var(--st-beige-flaeche); border:1px solid var(--st-beige-rand);
    color:var(--st-beige-text); font-size:0.9rem; line-height:1.5;
  }
  .tier-hero-sub{ margin:14px 0 6px; font-size:0.9rem; color:var(--ink); font-weight:600; }
  .tier-hero-list{ margin:0; padding-left:20px; font-size:0.9rem; display:grid; gap:5px; color:var(--ink); }
  .tier-more{ margin-top:16px; }
  .tier-more summary{
    cursor:pointer; font-weight:700; color:var(--green); padding:12px 2px; list-style:none;
    display:flex; align-items:center; gap:7px; min-height:44px;
  }
  .tier-more summary::-webkit-details-marker{ display:none; }
  .tier-more summary::after{ content:'▾'; font-size:0.72rem; transition:transform .15s ease; color:var(--muted); }
  .tier-more[open] summary::after{ transform:rotate(180deg); }
  .tier-card .tc-name{ font-weight:700; }
  .tier-card .tc-price{ font-size:1.4rem; font-weight:800; }
  .tier-card .tc-price small{ font-size:0.8rem; font-weight:500; color:var(--muted); }
  .tier-card ul{ margin:0; padding-left:18px; font-size:0.88rem; display:grid; gap:4px; color:var(--muted); }
  .topnav{
    display:flex; gap:4px; overflow-x:auto; -webkit-overflow-scrolling:touch;
    padding:8px 22px; background:var(--karte); border-bottom:1px solid var(--line);
  }
  .topnav button{
    display:flex; align-items:center; gap:8px; border:0; background:transparent; border-radius:8px; padding:11px 16px;
    font-weight:600; color:var(--muted); white-space:nowrap; min-height:44px; flex:none;
  }
  .topnav button svg{ width:18px; height:18px; flex:none; }
  .topnav button.active{ background:var(--green-soft); color:var(--green); }
  .topnav .nav-kurz{ display:none; }
  /* Die Bereichsauswahl im Profil (Migration 088): ein Kästchen je Bereich,
     die ganze Zeile ist das Tippziel. */
  /* Bereich wechseln (14.10.2026): ein Knopf neben dem Konto, der den
     Bereich nennt, in dem man arbeitet, und ein Menü wie das Konto-Menü.
     Vorher ein Schalter zwischen Marke und Suche -- dort eingeklemmt, auf
     dem Handy eine eigene Zeile. */
  .bereich-menu{ position:relative; margin-right:10px; }
  .bereich-menu[hidden]{ display:none; }
  .bereich-trigger{ display:flex; align-items:center; gap:7px; white-space:nowrap; }
  .bereich-trigger .b-symbol{ display:inline-flex; width:18px; height:18px; color:var(--green); flex:none; }
  .bereich-trigger .b-symbol svg{ width:100%; height:100%; }
  .bereich-trigger .b-name{ font-weight:600; }
  .bereich-trigger .caret{ font-size:0.7rem; color:var(--muted); }
  .account-dropdown.bereich-dropdown{ min-width:300px; }
  .bereich-dropdown .bd-titel{
    font-size:0.74rem; font-weight:700; letter-spacing:0.06em; text-transform:uppercase;
    color:var(--muted); padding:8px 12px 4px;
  }
  .account-dropdown.bereich-dropdown button{ align-items:flex-start; }
  .bereich-dropdown .b-symbol{ display:inline-flex; width:20px; height:20px; margin-top:1px; flex:none; color:var(--muted); }
  .bereich-dropdown .b-symbol svg{ width:100%; height:100%; }
  .bereich-dropdown .b-text{ flex:1; min-width:0; display:block; }
  .bereich-dropdown .b-text strong{ display:block; }
  .bereich-dropdown .b-text em{ display:block; font-style:normal; font-weight:400; font-size:0.85rem; color:var(--muted); margin-top:1px; }
  .bereich-dropdown .b-haken{ flex:none; width:16px; font-weight:700; color:var(--green); }
  .bereich-dropdown button.an, .bereich-dropdown button.an .b-symbol{ color:var(--green); }
  .rk-steuerfall{ display:flex; align-items:center; gap:10px; flex-wrap:wrap; margin:12px 0 4px; font-size:0.92rem; }
  .rk-steuerfall label{ font-weight:600; color:var(--muted); }
  .bereich-wahl{
    display:flex; align-items:flex-start; gap:12px; min-height:44px; padding:10px 12px; margin-top:8px;
    border:1px solid var(--line); border-radius:10px; cursor:pointer;
  }
  .bereich-wahl input{ flex:none; width:20px; height:20px; margin:2px 0 0; accent-color:var(--green); }
  .bereich-wahl span{ min-width:0; }
  .bereich-wahl strong{ display:block; }
  .bereich-wahl em{ display:block; font-style:normal; font-size:0.86rem; color:var(--muted); margin-top:2px; }
  .bereich-wahl:has(input:checked){ border-color:var(--st-gruen-rand); background:var(--st-gruen-flaeche); }

  /* ---------- Handy: die Navigation gehört an den unteren Rand ----------
     Bis zum 12.08.2026 stand sie auch hier oben und scrollte seitwärts.
     Damit waren von fünf Bereichen zwei bis drei sichtbar und der Rest
     lag außerhalb des Bildes -- ohne Hinweis, dass dort noch etwas ist.
     Weggescrollte Navigation zählt als verdeckt, und verdeckte
     Navigation wird etwa halb so oft gefunden wie sichtbare.

     Dazu die Ergonomie: der Daumen erreicht bequem das untere Drittel,
     nicht die obere Kante. Deshalb liegt bei jeder App, die auf dem
     Telefon ernsthaft benutzt wird, die Hauptnavigation unten.

     Fünf Ziele ist genau die Obergrenze, bei der das noch trägt --
     ein sechstes müsste sich etwas anderes suchen. */
  @media (max-width:767px){
    .topnav{
      position:fixed; left:0; right:0; bottom:0; z-index:40;
      padding:6px 4px calc(6px + env(safe-area-inset-bottom));
      border-bottom:0; border-top:1px solid var(--line);
      overflow-x:visible;
      box-shadow:0 -2px 10px rgba(26,26,26,0.06);
    }
    .topnav button{
      flex:1 1 0; min-width:0; flex-direction:column; gap:3px;
      padding:6px 2px; font-size:0.68rem; font-weight:600; line-height:1.15;
      border-radius:10px; min-height:52px; justify-content:center;
    }
    .topnav button svg{ width:21px; height:21px; }
    /* Die lange Beschriftung passt in 75 px nicht; das kurze Wort steht
       daneben im Markup, damit die Vorlesehilfe die lange Fassung behält. */
    .topnav .nav-lang{ display:none; }
    .topnav .nav-kurz{ display:block; }
    /* Platz, damit der letzte Inhalt nicht unter der Leiste verschwindet. */
      /* ⚠️ 74 px waren zu knapp: auf dem Handy verschwand die letzte Zeile
         der Fusszeile halb hinter der Leiste (gemeldet am 29.08.2026, im
         Bild war es "Verträge hier kündigen"). Die Leiste ist 52 px hoch
         plus Innenabstand -- gerechnet reichte es knapp, gemessen nicht,
         weil iOS die Adressleiste ein- und ausblendet und dabei die
         Viewporthoehe aendert. Jetzt mit Luft. */
      /* ⚠️ `body main` und nicht `main`: die Grundregel weiter unten
         (`main{ … padding:30px 22px 70px }`) hat dieselbe Spezifitaet,
         und eine Media-Query erhoeht sie nicht -- bei Gleichstand
         gewinnt die spaetere. Das Polster hat deshalb seit dem Umbau
         vom 12.08.2026 NIE gewirkt; gemessen kamen immer 70 px heraus.
         Am 29.08. mit einer Messung im Handy-Format gefunden, nachdem
         der Inhaber "geht nie komplett runter" gemeldet hatte. */
      body main{ padding-bottom:calc(112px + env(safe-area-inset-bottom)); }
      /* Dieselbe Ueberlegung gilt fuer JEDE Regel in diesem Block:
         die Grundregeln stehen weiter unten in derselben Datei. Wer
         hier etwas ergaenzt, schreibt `body …` davor -- sonst wirkt
         es nicht, und man sieht es dem Quelltext nicht an.
         tools/syntax-pruefen.mjs meldet es seit dem 29.08.2026. */
      /* Und die Kaesten weiter auseinander. Auf dem Handy stehen sie
         untereinander statt nebeneinander, und der Abstand, der am
         Schreibtisch ausreicht, laesst sie dort wie einen Block wirken. */
      body .panel{ margin-top:26px; }
      body .setup{ margin-top:24px; }
      /* Tippziele. Das Projekt vergroessert Symbole schon ueber ein
         Pseudo-Element (`inset:-6px`), damit sichtbar 32 px und
         beruehrbar 44 px sind. Beim kleinen i reicht das nicht: 20 + 12
         sind 32. Auf dem Handy deshalb mehr. */
      body .info-knopf::after{ inset:-12px; }
      /* Und innen etwas mehr Luft: 22 px Rand plus enge Abstaende lassen
         die Kaesten auf dem Handy wie einen Block wirken. */
      body .vk-band{ margin-top:18px; }
      /* Zeilen mit Streifen, Text und Handlungen (.nk-zeile). Die Handlungen
         hatten `flex:none` und nahmen sich auf dem Handy ihre volle Breite:
         bei den wiederkehrenden Pflichten (drei Handlungen, 275 px) blieb dem
         Text eine Breite von NULL, beim Stichtag-Hinweis 93 px -- die Zeile
         war über 1.000 px hoch. Gemessen am 08.10.2026 bei 375 px; live war
         das seit dem 23.09.2026. Jetzt rutschen die Handlungen unter den
         Text, sobald daneben weniger als 170 px für ihn blieben; passt ein
         kurzes „Öffnen" daneben, bleibt es dort. */
      body .nk-zeile{ flex-wrap:wrap; }
      body .nk-zeile .nk-text{ flex:1 1 170px; }
      body .nk-zeile .nk-tun{ flex:0 1 auto; max-width:100%; margin-left:auto; justify-content:flex-end; }
      /* Dieselbe Falle in der Einrichtungsliste (08.10.2026): neben „Adresse
         zeigen" blieben dem Text 94 px -- und diese Liste ist das Erste, was
         ein neues Konto auf dem Handy sieht. Der Knopf rutscht unter den Text. */
      body .setup li{ flex-wrap:wrap; }
      body .setup .s-text{ flex:1 1 170px; }
      body .setup .s-tun{ flex:0 1 auto; margin-left:36px; }
  }
  .account-menu{ position:relative; }
  .account-trigger{ display:flex; align-items:center; gap:7px; }
  .account-trigger svg{ width:19px; height:19px; flex:none; }
  .account-trigger .caret{ font-size:0.7rem; color:var(--muted); }
  .account-dropdown{
    position:absolute; right:0; top:calc(100% + 8px); min-width:210px; background:var(--karte);
    border:1px solid var(--line); border-radius:12px; box-shadow:0 10px 28px rgba(26,26,26,0.14);
    padding:6px; display:flex; flex-direction:column; gap:2px; z-index:900;
  }
  /* Ohne diese Zeile ist das Konto-Menue nie zu. Das display:flex darueber
     ueberschreibt das display:none, das der Browser dem hidden-Attribut
     mitgibt -- Autorenregeln schlagen die des Browsers. Der JavaScript-Teil
     setzte hidden also brav, nur sah man davon nichts. Gefunden am
     04.08.2026, nachdem es auf jedem Handy-Screenshot offen stand. */
  .account-dropdown[hidden]{ display:none; }
  .account-dropdown button{
    display:flex; align-items:center; gap:11px; border:0; background:none; text-align:left;
    padding:11px 12px; border-radius:8px; font:inherit; font-size:0.95rem; font-weight:600; color:var(--ink);
    min-height:44px; width:100%;
  }
  .account-dropdown button svg{ width:18px; height:18px; color:var(--muted); flex:none; }
  .account-dropdown button:hover, .account-dropdown button:focus-visible{ background:var(--green-soft); color:var(--green); }
  .account-dropdown button:hover svg, .account-dropdown button:focus-visible svg{ color:var(--green); }
  main{ max-width:960px; margin:0 auto; padding:30px 22px 70px; }
  @keyframes main-fade{ from{ opacity:0; } to{ opacity:1; } }
  main.fade-in{ animation:main-fade .18s ease; }
  @media (prefers-reduced-motion: reduce){ main.fade-in{ animation:none; } }
  h1{ font-size:1.45rem; margin:0 0 4px; letter-spacing:-0.01em; }
  .sub{ color:var(--muted); font-size:0.95rem; margin:0 0 26px; }

  .onboarding-banner{
    display:flex; align-items:center; justify-content:space-between; gap:14px; flex-wrap:wrap;
    background:var(--green-soft); border:1px solid var(--st-gruen-rand); border-radius:10px; padding:12px 16px; margin:16px 0 0;
    color:var(--green); font-size:0.92rem;
  }

  /* Hinweis auf den noch nicht geschlossenen Auftragsverarbeitungsvertrag.
     Sitzt zwischen Navigation und Inhalt: sichtbar in jedem Bereich, aber
     ohne den Zugang zu verstellen -- der Vertrag wird erst gebraucht, wenn
     tatsaechlich Mieter- oder Betriebsdaten verarbeitet werden. */
  .avv-bar{
    max-width:960px; margin:14px auto 0; padding:13px 16px;
    background:var(--st-beige-flaeche); border:1px solid var(--st-beige-rand); border-radius:10px;
    display:flex; align-items:center; justify-content:space-between; gap:14px; flex-wrap:wrap;
    font-size:0.92rem; color:var(--st-beige-text);
  }
  .avv-bar strong{ color:var(--st-beige-text); }
  .avv-bar a{ color:var(--st-beige-text); }
  .avv-bar .avv-tun{ display:flex; gap:8px; align-items:center; flex-wrap:wrap; }

  /* ---------- Geführte Hilfe je Ansicht ----------
     Bewusst <details> und kein eigenes Aufklappen: funktioniert ohne
     JavaScript, ist über die Tastatur bedienbar, und der Inhalt steht auch
     zugeklappt im Markup. Der Zustand wird gemerkt -- eine Hilfe, die man
     jeden Tag neu wegklickt, ist keine Hilfe. */
  /* Erklaerung genau dort, wo entschieden wird -- nicht am Kopf der
     Ansicht. Bewusst <details> statt eines eigenen Ueberlagerungsfensters:
     das funktioniert ohne JavaScript, ist mit der Tastatur bedienbar, und
     der Text steht im Markup (Suche, Drucken). Und bewusst kein Hover:
     auf dem Handy gibt es kein Darueberfahren, eine Hilfe, die dort fehlt,
     ist keine. */
  .info-anker{ display:inline-block; vertical-align:middle; }
  /* Die Hilfe ist ein Fragezeichen an der Überschrift, kein Knopf
     darunter. Vorher stand dort ein breiter Textknopf, der aussah wie
     die Hauptaktion der Ansicht — obwohl das Erste, was jemand tun soll,
     immer etwas anderes ist.

     .kopf ist eine Flex-Zeile: links Überschrift und Unterzeile, rechts
     das Symbol. Wird die Hilfe aufgeklappt, springt sie über
     flex-basis:100% und order in eine eigene Zeile darunter und nimmt
     die volle Breite ein — sonst stünde die Erklärung in einer schmalen
     Spalte neben der Überschrift. */
  /* ---------- Sprechblase für Erklärungen ---------- */
  #hinweisDialog{
    border:1px solid var(--line); border-radius:16px; padding:0;
    width:min(520px, calc(100vw - 32px)); max-height:min(80vh, 640px);
    background:var(--karte); color:var(--ink);
    box-shadow:0 18px 48px rgba(0,0,0,0.22);
  }
  #hinweisDialog::backdrop{ background:rgba(26,26,26,0.45); }
  /* Ein Dialog ohne Animation wirkt wie ein Sprung. @starting-style ist
     die moderne Art, den Eintritt zu animieren; Browser, die es nicht
     kennen, zeigen ihn einfach sofort — das ist kein Verlust. */
  #hinweisDialog[open]{ animation:hinweis-auf .16s ease-out; }
  @keyframes hinweis-auf{ from{ opacity:0; transform:translateY(8px) scale(.98); } }
  @media (prefers-reduced-motion: reduce){ #hinweisDialog[open]{ animation:none; } }
  .hinweis-kopf{
    display:flex; align-items:flex-start; gap:12px;
    padding:18px 18px 10px; border-bottom:1px solid var(--line);
    position:sticky; top:0; background:var(--karte); border-radius:16px 16px 0 0;
  }
  .hinweis-kopf h2{ margin:0; font-size:1.02rem; flex:1; }
  .hinweis-zu{
    flex:none; width:34px; height:34px; border-radius:999px;
    border:1px solid var(--line); background:var(--karte); color:var(--muted);
    font-size:1.3rem; line-height:1; cursor:pointer;
  }
  .hinweis-zu:hover, .hinweis-zu:focus-visible{ border-color:var(--ink); color:var(--ink); }
  .hinweis-inhalt{ padding:16px 18px 20px; overflow-y:auto; }
  .hinweis-inhalt h4{ margin:14px 0 4px; font-size:0.86rem; color:var(--green); letter-spacing:0.02em; }
  .hinweis-inhalt h4:first-child{ margin-top:0; }
  .hinweis-inhalt p{ margin:0 0 10px; font-size:0.94rem; line-height:1.6; }
  .hinweis-inhalt p:last-child{ margin-bottom:0; }
  .hinweis-inhalt .leise{ color:var(--muted); }

  /* Der Auslöser: rundes Fragezeichen an der Überschrift, rundes „i"
     neben einem einzelnen Feld. Beide öffnen dieselbe Sprechblase. */
  .hilfe-knopf, .info-knopf{
    display:inline-flex; align-items:center; justify-content:center;
    border-radius:999px; border:1px solid var(--line); background:var(--karte);
    color:var(--muted); font-weight:700; line-height:1; cursor:pointer;
    position:relative; flex:none; vertical-align:middle;
  }
  .hilfe-knopf{ width:32px; height:32px; font-size:0.95rem; }
  .info-knopf{ width:20px; height:20px; font-size:0.74rem; }
  /* Sichtbar 32 bzw. 20 Pixel, berührbar 44 — das Pseudo-Element
     vergrößert das Ziel, ohne das Symbol aufzublasen. */
  .hilfe-knopf::after, .info-knopf::after{ content:''; position:absolute; inset:-6px; border-radius:999px; }
  .info-knopf::after{ inset:-12px; }
  .hilfe-knopf:hover, .hilfe-knopf:focus-visible,
  .info-knopf:hover, .info-knopf:focus-visible{
    border-color:var(--green); color:var(--green); background:var(--green-soft);
  }

  /* Ein Feld, das nicht reagiert, muss auch aussehen wie eines, das nicht
     reagiert -- sonst hält man es für kaputt. Der Grund steht daneben im
     Klartext, nicht als Randbemerkung am Satzende. */
  /* ---------- Blätterleiste ----------
     Steht unter der Liste und ausserhalb des Scroll-Rahmens. Zeigt immer
     beides: wo man ist (1–25 von 340) und wie weit es geht. Eine reine
     „Weiter"-Schaltfläche verrät nicht, ob noch zwei oder zweihundert
     Einträge kommen. */
  .blaetter{
    display:flex; align-items:center; justify-content:space-between; gap:12px; flex-wrap:wrap;
    margin-top:12px; padding-top:12px; border-top:1px solid var(--line);
    font-size:0.86rem; color:var(--muted);
  }
  .blaetter[hidden]{ display:none; }
  .blaetter .bl-knoepfe{ display:flex; align-items:center; gap:6px; }
  .blaetter .bl-seite{ font-weight:600; color:var(--ink); }
  .blaetter .bl-btn{
    min-width:44px; min-height:44px; border:1px solid var(--line); border-radius:8px;
    background:var(--karte); color:var(--ink); font-size:1.1rem; line-height:1; cursor:pointer;
  }
  .blaetter .bl-btn:hover:not(:disabled){ border-color:var(--green); color:var(--green); }
  .blaetter .bl-btn:disabled{ opacity:0.35; cursor:default; }

  .rq-link-feld.gesperrt{ cursor:not-allowed; }
  .rq-link-feld.gesperrt > span{ color:var(--muted); }
  .rq-link-feld.gesperrt input{ cursor:not-allowed; }

  .kopf{ display:flex; align-items:flex-start; gap:14px; flex-wrap:wrap; }
  .kopf-text{ flex:1; min-width:min(100%, 220px); }
  .kopf-text h1{ margin-bottom:2px; }
  .kopf > .hilfe-knopf{ margin-top:6px; }
  .ptab-sec > .hilfe-knopf{ display:flex; margin:0 0 14px auto; }

  /* In den Reitern der Objekt-Akte gibt es keine Überschrift — dort ist
     die Reiterleiste die Überschrift. Das Symbol sitzt deshalb rechts
     oben in der Sektion. */
  /* `margin-left:auto` allein reicht hier nicht: ein <details> ist
     display:block und füllt die Breite ohnehin aus, die Marge liefe ins
     Leere. Als Flex-Spalte rückt das Symbol nach rechts, während die
     aufgeklappte Erklärung über align-self:stretch die volle Breite
     behält. */


  /* ---------- Dashboard (Start) ---------- */
  /* ---------- Einrichtungsliste ----------
     Ersetzt die selbststartende Tour als Einstieg. Eine Tour erklärt die
     Reiter und ist danach weg; diese Liste sagt, was zu tun ist, und
     bleibt stehen, bis es getan ist. Ihr Zustand kommt aus den Daten
     selbst — ein Merkmal am Profil könnte behaupten, etwas sei erledigt,
     ohne dass es passiert ist. */
  .setup{ background:var(--karte); border:1px solid var(--line); border-radius:12px; padding:18px 20px; margin-top:20px; }
  .setup-kopf{ display:flex; align-items:baseline; justify-content:space-between; gap:12px; flex-wrap:wrap; margin-bottom:4px; }
  .setup-kopf h2{ margin:0; font-size:1.05rem; }
  /* 40 px Mindesthoehe: 29 px waren es im ersten Anlauf, und am
     Schreibtisch mit der Maus faellt das nicht auf. Am 29.08.2026 mit
     einer Messung im Handy-Format gefunden. */
  .setup-klapp{
    background:none; border:0; padding:8px 10px; color:var(--green);
    font:inherit; font-size:0.85rem; font-weight:600; cursor:pointer;
    border-radius:8px; min-height:40px;
  }
  .setup-klapp:hover{ background:var(--green-soft); }
  .setup-zaehler{ font-size:0.85rem; color:var(--muted); font-weight:600; }
  .setup-balken{ height:6px; border-radius:999px; background:var(--line); overflow:hidden; margin:10px 0 14px; }
  .setup-balken i{ display:block; height:100%; background:var(--gruen-fill); border-radius:999px; transition:width .4s ease; }
  @media (prefers-reduced-motion: reduce){ .setup-balken i{ transition:none; } }
  .setup ol{ list-style:none; margin:0; padding:0; display:grid; gap:2px; }
  .setup li{
    display:flex; align-items:center; gap:12px; padding:10px 0;
    border-top:1px solid var(--line);
  }
  .setup li:first-child{ border-top:0; }
  .setup .s-haken{
    flex:none; width:24px; height:24px; border-radius:999px; border:2px solid var(--line);
    display:flex; align-items:center; justify-content:center; font-size:0.8rem; font-weight:700;
    color:transparent;
  }
  .setup li.fertig .s-haken{ background:var(--gruen-fill); border-color:var(--gruen-fill); color:#fff; }
  .setup .s-text{ flex:1; min-width:0; }
  .setup .s-text strong{ display:block; font-weight:600; font-size:0.95rem; }
  .setup .s-text em{ font-style:normal; display:block; font-size:0.85rem; color:var(--muted); margin-top:1px; }
  .setup li.fertig .s-text strong{ color:var(--muted); text-decoration:line-through; }
  .setup li.fertig .s-text em{ display:none; }
  .setup .s-tun{ flex:none; }
  .setup li.fertig .s-tun{ display:none; }

  /* Der Rechtsteil war bis zum 12.08.2026 das Erste nach dem Login: drei
     Paragraphen, bevor irgendetwas zu tun war. Das ist die Begründung des
     Anbieters, nicht das Ziel des Nutzers — und sie steht ohnehin auf der
     Landing Page. Jetzt aufgeklappt nur auf Wunsch. */
  .dash-info{ background:var(--green-soft); border:1px solid var(--st-gruen-rand); border-radius:12px; padding:0 22px; margin-top:20px; }
  .dash-info[open]{ padding-bottom:20px; }
  .dash-info summary{
    cursor:pointer; padding:16px 0; font-weight:700; color:var(--green); font-size:1rem;
    list-style:none; display:flex; align-items:center; gap:8px; min-height:44px;
  }
  .dash-info summary::-webkit-details-marker{ display:none; }
  .dash-info summary::after{ content:'▾'; font-size:0.8rem; transition:transform .15s ease; }
  .dash-info[open] summary::after{ transform:rotate(180deg); }
  @media (prefers-reduced-motion: reduce){ .dash-info summary::after{ transition:none; } }
  .dash-info ul{ margin:0; padding-left:20px; display:grid; gap:8px; }
  .dash-info li{ font-size:0.95rem; }
  .dash-info .more{ display:inline-block; margin-top:12px; font-weight:600; }
  .tiles{ display:grid; grid-template-columns:repeat(auto-fill, minmax(220px,1fr)); gap:14px; margin-top:22px; }
  .tile{
    background:var(--karte); border:1px solid var(--line); border-radius:12px; padding:16px;
    text-align:left; display:flex; gap:12px; align-items:flex-start; min-height:44px;
    transition:transform .12s ease, box-shadow .12s ease;
  }
  .tile:hover{ transform:translateY(-2px); box-shadow:0 6px 18px rgba(26,26,26,0.07); }
  .tile .ti-icon{ flex:none; width:30px; height:30px; color:var(--green); }
  .tile .ti-icon svg{ width:100%; height:100%; }
  /* min-width:0: ohne das wird der Text nie schmaler als sein längstes
     Wort -- „Verfahrensdokumentation" ragte bei drei Kacheln je Zeile über
     den Rand (14.10.2026). Die Silbengrenze setzt ein weiches Trennzeichen
     im Titel (renderDashTiles) -- hyphens:auto trennt nicht in jedem
     Browser, overflow-wrap bleibt der Rückfall. */
  .tile .ti-body{ display:block; min-width:0; overflow-wrap:break-word; hyphens:auto; }
  .tile strong{ display:block; margin-bottom:2px; }
  .tile em{ font-style:normal; display:block; font-size:0.88rem; color:var(--muted); }
  .status-line{ display:flex; gap:8px 20px; flex-wrap:wrap; font-size:0.92rem; color:var(--muted); margin-top:24px; padding-top:16px; border-top:1px solid var(--line); }
  .status-line strong{ color:var(--ink); }
  @media (prefers-reduced-motion: reduce){ .tile{ transition:none; } }

  /* ---------- Vorgänge & Fristen: Karten ---------- */
  /* ---------- Vorgangskarte (umgebaut 13.08.2026) ----------
     Vorher lag alles flach untereinander, und eine Karte mit Angeboten
     wurde dreimal so hoch wie eine leere. Jetzt drei feste Zonen: Kopf,
     Frist, Details — Details als Aufklapper mit Zusammenfassungszeile.

     280 statt 230 Pixel Mindestbreite: bei 230 brach ein Titel wie
     „Wasser / Sanitär: TESTMELDUNG …" in sieben Zeilen um. */
  .case-cards{ display:grid; grid-template-columns:repeat(auto-fill, minmax(280px,1fr)); gap:14px; margin-top:14px; }
  .case-card{
    background:var(--karte); border:1px solid var(--line); border-left:4px solid var(--line); border-radius:10px;
    padding:14px 16px; display:flex; flex-direction:column; gap:8px;
  }
  .case-card.warn{ border-left-color:var(--red); }
  .case-card.ok{ border-left-color:var(--green); }
  .case-card.done{ border-left-color:var(--muted); }
  /* Eine Fristkarte, die zu ihrem Vorgang führt. Sie muss aussehen wie
     etwas, das man drücken kann -- sonst ist sie zwar klickbar, aber
     niemand versucht es. Nur `.case-card[role=button]`, damit die
     Vorgangs- und Kontaktkarten unberührt bleiben. */
  .case-card[role="button"]{ cursor:pointer; transition:border-color .15s, box-shadow .15s; }
  .case-card[role="button"]:hover{ box-shadow:0 2px 10px rgba(0,0,0,.07); }
  .case-card[role="button"]:focus-visible{ outline:2px solid var(--green); outline-offset:2px; }

  /* `.cc-top` gibt es weiterhin: Fristen-Übersicht, Kontaktkarten und die
     Beispielansicht benutzen dieselbe Kartenhülle, aber ohne Vorgangsnummer.
     `.cc-kopf` ist die Variante der Vorgangskarte mit Nummer links. */
  /* Suchfeld links, Handlungen rechts -- eine Zeile, ein Baustein.
     Sie stand vorher als Inline-Stil in jeder Ansicht neu geschrieben. */
  .werkzeugleiste{
    display:flex; gap:10px; flex-wrap:wrap; align-items:center; margin-bottom:4px;
  }
  .werkzeugleiste .search-input{ flex:1; min-width:200px; margin:0; }

  .case-card .cc-top{ display:flex; justify-content:space-between; align-items:flex-start; gap:8px; }
  /* Der Chip bricht nicht mehr um. Bei knapper Kartenbreite stand
     "Reparatur (2 J.)" auf zwei Zeilen und schob sich unter den Titel --
     am 19.08.2026 am Bildschirm gemeldet. Dieselbe Regel wie bei den
     Tabellenueberschriften: kurze Beschriftungen brechen nie. */
  .case-card .cc-top .chip{ flex:none; white-space:nowrap; align-self:flex-start; }
  .case-card .cc-kopf{ display:flex; justify-content:space-between; align-items:center; gap:8px; }
  /* Die Vorgangsnummer wie ein Aktenzeichen: einmal breit gesperrt, damit
     man sie am Telefon vorlesen kann, ohne sie zu suchen. */
  .case-card .cc-nr{
    font-size:0.78rem; font-weight:800; color:var(--green);
    letter-spacing:0.08em; font-variant-numeric:tabular-nums;
  }
  /* Zwei Zeilen, dann Schluss. Der ganze Titel steht im title-Attribut. */
  .case-card .cc-title{
    margin:0; font-size:0.98rem; font-weight:700; line-height:1.35;
    display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical;
    overflow:hidden; overflow-wrap:break-word;
  }
  .case-card .cc-status{
    display:flex; align-items:center; gap:7px; flex-wrap:wrap;
    font-size:0.85rem; color:var(--muted);
  }
  .case-card .cc-punkt{
    width:8px; height:8px; border-radius:999px; background:var(--muted); flex:none;
  }
  .case-card .cc-status.s-in_arbeit{ color:var(--ink); font-weight:600; }
  .case-card .cc-status.s-in_arbeit .cc-punkt{ background:var(--st-beige-punkt); }
  .case-card .cc-status.s-abgeschlossen .cc-punkt{ background:var(--st-gruen-punkt); }
  .case-card .cc-herkunft{
    font-size:0.76rem; background:var(--tab); border-radius:999px; padding:2px 8px; color:var(--muted);
  }
  .case-card .cc-frist{ border-top:1px solid var(--line); padding-top:8px; }
  .case-card .cc-meta{ font-size:0.85rem; color:var(--muted); }
  .case-card .cc-warranty{ font-size:0.86rem; font-weight:600; margin-bottom:4px; }
  .case-card .cc-actions{ margin-top:auto; padding-top:6px; text-align:right; }
  .case-card .cc-leer{ font-size:0.82rem; color:var(--muted); }

  /* Aufklapper in der Karte. Die Zusammenfassungszeile trägt die Zahl,
     nach der man sucht; die Einzelheiten liegen dahinter. */
  .case-card .cc-block{ font-size:0.85rem; border-top:1px solid var(--line); padding-top:8px; }
  .case-card .cc-block > summary{
    display:flex; align-items:center; gap:8px; cursor:pointer; list-style:none;
    color:var(--green); font-weight:600; min-height:28px;
  }
  .case-card .cc-block > summary::-webkit-details-marker{ display:none; }
  .case-card .cc-block > summary > span:first-child{ flex:1; min-width:0; }
  .case-card .cc-block > summary::after{
    content:'⌄'; color:var(--muted); font-size:0.85rem; flex:none; transition:transform .18s ease;
  }
  .case-card .cc-block[open] > summary::after{ transform:rotate(180deg); }
  .case-card .cc-liste{ margin:8px 0 0; padding-left:18px; }
  .case-card .cc-liste li{ margin-bottom:8px; word-break:break-word; }
  .case-card .cc-desc-text{ white-space:pre-wrap; color:var(--muted); margin-top:8px; }
  @media (prefers-reduced-motion: reduce){
    .case-card .cc-block > summary::after{ transition:none; }
  }
  /* Sprung aus dem Mieterkanal in den Vorgang -- ohne kurze Markierung
     sucht man die Karte im Raster selbst. */
  .case-card.hervor{ box-shadow:0 0 0 2px var(--green); transition:box-shadow .4s ease; }

  /* ---------- Vorgangszeile mit Aktenreiter (13.08.2026) ----------
     Zweiter Umbau am selben Tag. Die Kartenfassung war besser als die
     flache Liste, brauchte aber immer noch drei bis vier Zeilen für eine
     Auskunft, die in eine passt. Jetzt: Reiter links mit der Nummer,
     rechts Titel und Summe, darunter Kennzahlen und Fortschritt. */
  .vorgang-liste{ display:grid; gap:10px; margin-top:14px; }
  .vorgang-zeile{
    display:flex; align-items:stretch;
    background:var(--karte); border:1px solid var(--line); border-radius:12px; overflow:hidden;
  }
  /* Der Reiter zitiert den Registerreiter der Akte -- dasselbe Motiv wie
     die Fristschiene und der Eingangsstempel. */
  .vz-reiter{
    flex:none; width:58px; background:var(--tab);
    display:flex; flex-direction:column; align-items:center; justify-content:center;
    border-right:1px solid var(--line);
  }
  .vz-v{ font-size:0.66rem; letter-spacing:0.14em; color:var(--muted); }
  .vz-nr{ font-size:1.02rem; font-weight:800; font-variant-numeric:tabular-nums; letter-spacing:0.02em; }
  /* Der Reiter färbt sich nach dem Bearbeitungsstand -- das ist die Frage,
     mit der man auf eine Vorgangsliste schaut. Grau: noch nichts passiert.
     Beige: in Arbeit. Grün: erledigt. Die Gewährleistungsfrist bleibt als
     roter Text in den Kennzahlen sichtbar; sie hier zusätzlich zu
     verfärben hiesse, zwei Aussagen in eine Farbe zu legen. */
  .vorgang-zeile.st-offen .vz-reiter{ background:var(--st-grau-flaeche); }
  .vorgang-zeile.st-offen .vz-nr{ color:var(--st-grau-text); }
  .vorgang-zeile.st-in_arbeit .vz-reiter{ background:var(--st-beige-flaeche); border-right-color:var(--st-beige-rand); }
  .vorgang-zeile.st-in_arbeit .vz-nr{ color:var(--st-beige-text); }
  .vorgang-zeile.st-abgeschlossen .vz-reiter{ background:var(--st-gruen-flaeche); border-right-color:var(--st-gruen-rand); }
  .vorgang-zeile.st-abgeschlossen .vz-nr{ color:var(--st-gruen-text); }

  .vz-inhalt{ flex:1; min-width:0; padding:12px 14px; }
  .vz-kopf{ display:flex; justify-content:space-between; gap:12px; align-items:baseline; }
  .vz-titel{
    margin:0; font-size:0.98rem; font-weight:700; line-height:1.35; min-width:0;
    display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical;
    overflow:hidden; overflow-wrap:break-word;
  }
  .vz-summe{ flex:none; font-weight:700; font-variant-numeric:tabular-nums; }
  .vz-kennzahlen{
    display:flex; align-items:center; gap:6px 12px; flex-wrap:wrap;
    margin-top:6px; font-size:0.82rem; color:var(--muted);
  }
  .vz-status{ display:inline-flex; align-items:center; gap:6px; }
  .vz-status.s-in_arbeit{ color:var(--ink); font-weight:600; }
  .vz-status.s-in_arbeit .cc-punkt{ background:var(--st-beige-punkt); }
  .vz-status.s-abgeschlossen .cc-punkt{ background:var(--st-gruen-punkt); }

  /* Die vier Takte. „Übersprungen" ist blass und nicht leer -- ein
     Vorgang ohne Fremdvergabe soll nicht dauerhaft unfertig aussehen. */
  .vz-takte{ margin-top:10px; }
  .vz-balken{ display:flex; gap:4px; }
  .vz-takt{ flex:1; height:4px; border-radius:2px; background:var(--line); }
  .vz-takt.fertig{ background:var(--gruen-fill); }
  .vz-takt.uebersprungen{ background:var(--line); opacity:0.45; }
  .vz-namen{
    display:flex; gap:4px; margin-top:4px;
    font-size:0.7rem; color:var(--muted);
  }
  .vz-namen span{ flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .vz-namen span.fertig{ color:var(--green); font-weight:600; }
  .vz-namen span.uebersprungen{ opacity:0.45; text-decoration:line-through; }

  .vorgang-zeile .cc-block{ border-top:1px solid var(--line); margin-top:10px; }
  .vorgang-zeile .cc-actions{ margin-top:10px; padding-top:0; text-align:right; }
  @media (max-width:520px){
    .vz-reiter{ width:46px; }
    .vz-namen{ display:none; }   /* auf dem Handy nur der Balken */
  }

  /* Wege zu einer Aufgabe, keine Aktionen -- deshalb in der Farbe der
     Verweise und nicht als Knöpfe. Sie stehen untereinander, damit man
     sie beim Überfliegen als Paar erkennt. */
  .zugang-wege{ display:flex; flex-direction:column; align-items:flex-start; gap:2px; margin:10px 0 14px; }
  .zugang-wege .linkbtn{ padding:6px 0; }

  /* ---------- Bearbeiten-Dialog ----------
     Alles, was man ändert, liegt im Vordergrund und schiebt die Seite
     nicht auf. Auf dem Handy nimmt er fast die volle Breite -- ein
     schmaler Dialog mit umbrechenden Feldern wäre schlechter als die
     aufgeklappte Fassung, die er ersetzt. */
  .bearbeiten-dialog{
    border:0; border-radius:16px; padding:0; width:min(94vw, 560px);
    max-height:min(88vh, 800px);      /* Rueckfall fuer aeltere Browser */
    /* ⚠️ Auf iOS meint `vh` die GROSSE Viewporthoehe -- die ohne
       Adressleiste. Solange die eingeblendet ist, ragt der Dialog unter
       den sichtbaren Bereich, und unten fehlen genau die Knoepfe.
       `dvh` meint die tatsaechliche. Gemeldet am 29.08.2026 vom Handy. */
    max-height:min(88dvh, 800px);
    background:var(--karte); color:var(--ink);
    box-shadow:0 24px 60px rgba(26,26,26,0.28);
    display:flex; flex-direction:column;
  }
  /* ⚠️ Ohne diese Zeile steht ein geschlossener Dialog trotzdem auf der
     Seite. `display:flex` oben überschreibt die Browser-Regel
     `dialog:not([open]) { display:none }`.

     Das ist bis zum 18.08.2026 nie aufgefallen, weil bearbeitenDialog()
     das Element erzeugt und im selben Atemzug öffnet -- der geschlossene
     Zustand kam schlicht nie vor. Als der Verwaltungsbereich vier feste
     Dialoge ins Markup bekam, standen alle vier gleichzeitig sichtbar
     untereinander.

     Merksatz: eine Regel, die nie geschadet hat, ist nicht geprüft --
     sie war nur nie in dem Zustand, für den sie falsch ist. */
  .bearbeiten-dialog:not([open]){ display:none; }
  .bearbeiten-dialog.breit{ width:min(94vw, 760px); }
  @media (max-width:767px){
    /* Als Blatt von unten: die gewohnte Form auf dem Handy, und der
       Daumen erreicht die Knoepfe, ohne zu strecken. */
    .bearbeiten-dialog, .bearbeiten-dialog.breit{
      width:100%; max-width:100%; max-height:92dvh;
      border-radius:16px 16px 0 0;
      margin:auto auto 0 auto;
    }
    body .bd-fuss{
      border-radius:0;
      padding-bottom:calc(14px + env(safe-area-inset-bottom));
    }
    /* Nebeneinander statt uebereinander -- sonst schiebt eine dritte
       Schaltflaeche den Inhalt aus dem Bild. */
    .bd-fuss .btn{ flex:1 1 auto; min-width:0; }
  }
  .bearbeiten-dialog::backdrop{ background:rgba(26,26,26,0.45); }
  .bd-kopf{
    display:flex; align-items:center; justify-content:space-between; gap:12px;
    padding:16px 20px; border-bottom:1px solid var(--line); flex:none;
  }
  .bd-kopf h3{ margin:0; font-size:1.05rem; }
  /* ⚠️ `min-height:0` ist der Teil, der hier wirklich zaehlt -- dieselbe
     Falle wie `min-width:0` bei den Scroll-Kaesten, nur in der anderen
     Achse. Ein Kind im Flex-Kasten hat `min-height:auto` und schrumpft
     nicht unter seine Inhaltshoehe; `overflow-y:auto` laeuft dann ins
     Leere, der Inhalt drueckt den Kasten auf, und `max-height` schneidet
     unten ab -- also dort, wo die Knoepfe sitzen.

     Am Schreibtisch faellt das nie auf, weil dort fast immer Platz ist.
     Auf dem Handy war die Maske dadurch praktisch unbenutzbar: Kopf,
     eine halbe Zeile Inhalt, dann schon die Fussleiste. */
  .bd-inhalt{ padding:18px 20px; overflow-y:auto; flex:1 1 auto; min-height:0; }

  /* ⚠️ UND der eigentliche Grund, warum `min-height:0` allein nicht
     reichte: manche Masken legen ein <form> ZWISCHEN Dialog und Inhalt.
     Der Aufbau ist dann

         dialog  →  .bd-kopf  +  form  →  .bd-inhalt + .bd-fuss

     Das Flex-Element ist also das Formular, und `.bd-inhalt` sitzt in
     einem Element, das gar kein Flex-Kasten ist -- sein `flex:1` und
     sein `min-height:0` gehen damit ins Leere. Gemessen am 29.08.2026
     beim Anlegen eines Kontakts: der Inhalt blieb 465 px hoch in einem
     303 px hohen Dialog, und die Fussleiste lag ausserhalb des Bildes.

     Der Zwischenschritt wird deshalb selbst zum Flex-Kasten und darf
     schrumpfen. Danach: Inhalt 160 px, Rollbalken greift, Knoepfe im
     Bild. */
  .bearbeiten-dialog > form{
    display:flex; flex-direction:column; flex:1 1 auto; min-height:0;
  }
  .bd-inhalt .field:last-child{ margin-bottom:0; }
  .bd-fuss{
    display:flex; gap:10px; flex-wrap:wrap;
    padding:14px 20px; border-top:1px solid var(--line); flex:none;
    background:var(--tab); border-radius:0 0 16px 16px;
  }

  /* ---------- Profil-Übersicht statt Dauerformular ----------
     Angaben, die man einmal einträgt, gehören nicht dauerhaft als
     Eingabemaske auf den Bildschirm. Beschriftung links, Wert rechts --
     eine Definitionsliste ist genau das. */
  .prof-liste{ margin:14px 0 0; display:grid; gap:1px; background:var(--line); border-radius:10px; overflow:hidden; }
  .prof-liste > div{
    display:flex; justify-content:space-between; gap:16px;
    background:var(--karte); padding:10px 14px; font-size:0.9rem;
  }
  .prof-liste dt{ color:var(--muted); flex:none; }
  .prof-liste dd{ margin:0; text-align:right; overflow-wrap:break-word; min-width:0; }
  /* Noch nicht hinterlegt: grau, mit einer Zeile wozu. Kein Mahnton --
     freiwillig bleibt freiwillig, hier steht nur der Nutzen. */
  .prof-liste dd.prof-offen{ color:var(--muted); }
  .prof-liste dd.prof-offen em{
    display:block; font-style:normal; font-size:0.78rem; margin-top:1px;
  }
  .prof-fehlt{
    display:flex; align-items:flex-start; gap:8px; margin-top:14px;
    background:var(--st-beige-flaeche); border:1px solid var(--st-beige-rand); border-radius:10px;
    padding:10px 12px; font-size:0.85rem; color:var(--st-beige-text);
  }
  .prof-fehlt svg{ flex:none; margin-top:2px; }

  /* ---------- Zahlungsverlauf als Monatskacheln ----------
     Der Balken ist am 18.08.2026 zum vierten Mal abgelehnt worden, und zu
     Recht: seine Hoehe bedeutet nichts. Gefragt ist "welcher Monat war
     das" -- und die Antwort ist ein Monatsname, kein Saeulchen.

     Kacheln sind dieselbe Sprache wie der Kalenderstreifen der
     Nachmietersuche, nur eine Ebene groeber. Zwoelf Stueck, auch wenn der
     Vertrag kuerzer ist: die Monate ausserhalb der Laufzeit bleiben blass,
     und man sieht, dass ein Vertrag im August begann. */
  /* Eine Zeile, die seitwärts schiebt: auf dem Handy nahmen acht Jahre zwei Zeilen ein. */
  .mk-jahre{
    display:flex; gap:6px; flex-wrap:nowrap; overflow-x:auto; scrollbar-width:none;
    scroll-snap-type:x proximity; padding:2px; margin:0 -2px 8px;
  }
  .mk-jahre::-webkit-scrollbar{ display:none; }
  .mk-jahre .chip-btn{ flex:none; scroll-snap-align:start; }
  .mk-kacheln{ display:flex; gap:4px; flex-wrap:wrap; }
  .mk-kachel{
    width:44px; height:34px; border-radius:7px; border:1px solid transparent;
    background:var(--st-grau-flaeche); color:var(--muted);
    font-size:0.76rem; font-weight:600; padding:0;
  }
  .mk-kachel.k-bezahlt{ background:var(--st-gruen-flaeche); border-color:var(--st-gruen-rand); color:var(--st-gruen-text); }
  /* Unterstellt, nicht bestaetigt -- beige, nicht gruen. */
  .mk-kachel.k-automatisch{ background:var(--st-beige-flaeche); border-color:var(--st-beige-rand); color:var(--st-beige-text); }
  .mk-kachel.k-offen{ background:var(--rot-flaeche); border-color:var(--rot-rand); color:var(--red); }
  .mk-kachel.k-kommt{ background:var(--st-grau-flaeche); color:var(--muted); }
  /* Ausserhalb der Laufzeit: blass und nicht anklickbar -- dort gibt es
     nichts zu sehen, und ein Klick ins Leere waere eine Enttaeuschung. */
  /* Ein Monat außerhalb des Mietverhältnisses: bewusst blass, aber lesbar.
     Bis zum 07.10.2026 stand das Monatskürzel in der Linienfarbe da (1,31:1
     auf Weiß) -- zu sehen war nur der Rahmen. Jetzt 3,4:1. */
  .mk-kachel.k-leer{ background:transparent; border-color:var(--line); color:#8f8b82; }
  .mk-kachel[disabled]{ cursor:default; }
  .mk-kachel.jetzt{ outline:2px solid var(--green); outline-offset:1px; }
  /* Der Sprunglink (siehe #sprungLink): außerhalb des Bildes, bis er den
     Fokus hat. Nicht display:none -- dann erreichte ihn die Tabulatortaste
     nicht. */
  .sprung-link{ position:fixed; left:-9999px; top:10px; z-index:2000; background:var(--gruen-fill); color:#fff; border:0;
    border-radius:999px; padding:11px 18px; font:inherit; font-weight:600; cursor:pointer; box-shadow:0 6px 20px rgba(0,0,0,0.18); }
  .sprung-link:focus, .sprung-link:focus-visible{ left:10px; outline:3px solid #fff; outline-offset:-5px; }
  #main:focus{ outline:none; }
  .mk-kachel.klein{ width:20px; height:20px; border-radius:4px; }

  /* Das Raster ueber mehrere Jahre: Zeile je Jahr, Spalte je Monat.
     Erst ab zwei Jahren erreichbar -- bei einem waere es eine Zeile. */
  .mk-raster{ display:flex; flex-direction:column; gap:3px; overflow-x:auto; }
  .mk-raster-kopf, .mk-raster-zeile{ display:flex; gap:3px; align-items:center; }
  .mk-raster-kopf span{ width:20px; text-align:center; font-size:0.66rem; color:var(--muted); }
  .mk-raster-kopf span:first-child, .mk-raster-jahr{
    width:36px; flex:none; font-size:0.72rem; color:var(--muted);
    font-variant-numeric:tabular-nums; text-align:left;
  }
  /* Kurz aufleuchten, wenn man aus einer Kachel in den Auszug springt --
     sonst weiss man nicht, welche der Zeilen gemeint war. */
  .mk-zeile.hervor{ background:var(--st-gruen-flaeche); border-radius:8px; }

  /* ---------- Dauerauftrag am Mietkonto ---------- */
  .mk-dauer{
    display:flex; align-items:center; gap:12px; flex-wrap:wrap;
    border:1px solid var(--st-grau-rand); background:var(--st-grau-flaeche);
    border-radius:10px; padding:11px 14px; margin-bottom:14px;
  }
  .mk-dauer.offen{ border-color:var(--st-beige-rand); background:var(--st-beige-flaeche); }
  .mk-dauer-text{ flex:1; min-width:200px; }
  .mk-dauer-text strong{ display:block; font-size:0.92rem; }
  .mk-dauer-text span{ font-size:0.84rem; color:var(--muted); }
  .mk-dauer.offen .mk-dauer-text strong{ color:var(--st-beige-text); }
  .mk-stoerung{
    background:var(--st-beige-flaeche); border:1px solid var(--st-beige-rand);
    border-radius:10px; padding:11px 13px; font-size:0.88rem; margin-bottom:16px;
  }
  /* ---------- Mietkonto: Kopfzeile und Auszug (18.08.2026) ----------
     Zweiter Anlauf. Der erste hatte drei nummerierte Schritte -- besser
     als das flache Nebeneinander davor, aber immer noch unübersichtlich:
     der Nutzer sah weiterhin ein Formular und einen Aufklapper, obwohl er
     in neun von zehn Fällen nur wissen will, ob die Miete da ist.

     Jetzt: oben **ein Satz** mit dem Stand und daneben die Wege, die
     alle in eine Maske im Vordergrund führen. Darunter der Verlauf und
     der Auszug -- eine Zeile je Monat, wie ein Kontoauszug bei der Bank.
     Ein Mietkonto IST ein Kontoauszug; die Zeilenform beantwortet "was
     war in diesem Monat los" besser als vier Zahlenspalten, in denen man
     die Frage erst zusammensuchen muss. */
  /* Der Kopf des Mietkontos ist derselbe Bau wie in den beiden anderen
     Baendern der Vertragskarte: Ueberschrift links, Handlungen rechts.
     Darunter erst die Antwort ("Miete ist eingegangen"), dann die Lage.
     Vorher sassen Stand und Wege nebeneinander auf einer Hoehe und die
     Ueberschrift fehlte ganz -- am 19.08.2026 als "zusammengeschnitten"
     gemeldet. */
  .mk-gross{
    margin:12px 0 2px; font-size:1.12rem; font-weight:700;
    font-variant-numeric:tabular-nums;
  }
  .mk-lage{ margin:0 0 14px; font-size:0.85rem; color:var(--muted); }
  .mk-wege{ display:flex; gap:14px; flex-wrap:wrap; align-items:center; }
  /* Die Aktionen im Mietkonto in Stufen: eine Hauptaktion, eine zweite, der Rest ruhig.
     Alles bleibt sichtbar, ein „Mehr"-Menü versteckte gerade das Gesuchte. */
  .mk-aktionen{ gap:8px; }
  .mk-aktionen > .btn{ min-height:44px; padding:8px 18px; font-size:0.92rem; line-height:1.25; }
  .mk-nebenwege{ display:contents; }
  .mk-nebenwege > .linkbtn{ min-height:44px; padding:8px 10px; font-size:0.9rem; line-height:1.25; }
  /* Loeschen in der Bearbeiten-Maske: abgesetzt, damit es nicht neben
     "Speichern" wie eine gleichrangige Wahl aussieht. */
  .bd-gefahr{ margin:12px 0 0; padding-top:10px; border-top:1px solid var(--line); }

  /* Es gab hier eine zweite, fast gleiche Kopie der Filterknoepfe
     (.mk-filter / .mk-chipf), nur mit anderer Hoehe, ohne Hover-Zustand
     und mit anders gesetzter Zahl. Sie ist am 19.08.2026 entfallen:
     Mietkonto, Mieteranliegen, Dokumente und Vorgaenge benutzen jetzt
     dieselben `.filter-chips` / `.chip-btn` wie ueberall sonst.
     Aufgefallen ist die Doppelung nie, weil die beiden Filterleisten in
     verschiedenen Reitern liegen und man sie nie nebeneinander sieht. */

  /* Die Sammelaktion steht rechts in der Filterzeile -- sie gilt fuer
     genau das, was der Filter zeigt, und gehoert deshalb dorthin. */
  .mk-sammel{ margin-left:auto; padding:5px 0; font-size:0.85rem; }
  .mk-sammel[hidden]{ display:none; }
  /* Der Status als zusammenhängendes Segment: genau eines ist gewählt. */
  body .filter-chips.mk-status{ gap:0; margin-top:10px; }
  body .filter-chips.mk-status .chip-btn{
    flex:1 1 0; justify-content:center; min-height:44px; margin-left:-1px; padding:6px; border-radius:0;
  }
  body .filter-chips.mk-status .chip-btn:first-child{ margin-left:0; border-radius:12px 0 0 12px; }
  body .filter-chips.mk-status .chip-btn:has(+ .mk-sammel){ border-radius:0 12px 12px 0; }
  body .filter-chips.mk-status .chip-btn.an{ position:relative; z-index:1; }
  body .filter-chips.mk-status .mk-sammel{ flex:1 0 100%; margin:6px 0 0; text-align:right; }
  /* Vier Felder passen auf dem Handy nicht in eine Reihe („Unbestätigt 12"). */
  @media (max-width:520px){
    body .filter-chips.mk-status:has(> [data-mkf="auto"]){ display:grid; grid-template-columns:1fr 1fr; gap:6px; }
    body .filter-chips.mk-status:has(> [data-mkf="auto"]) .chip-btn{ margin-left:0; border-radius:12px; }
    body .filter-chips.mk-status:has(> [data-mkf="auto"]) .mk-sammel{ grid-column:1 / -1; }
  }
  .mk-auszug{ list-style:none; margin:0; padding:0; }
  /* Der Abschluss unter dem Auszug -- wie die Summenzeile eines
     Kontoauszugs. Er bezieht sich auf alle Monate des Vertrags, nicht auf
     das gerade Sichtbare. */
  .mk-fuss{
    display:flex; align-items:baseline; justify-content:space-between;
    gap:12px; flex-wrap:wrap; margin-top:10px; padding-top:11px;
    border-top:2px solid var(--line);
  }
  .mk-summe{ display:flex; gap:16px; flex-wrap:wrap; font-size:0.85rem; color:var(--muted); }
  .mk-summe strong{ color:var(--ink); font-variant-numeric:tabular-nums; }
  .mk-fuss .linkbtn{ padding:0; font-size:0.85rem; }
  /* Die gespeicherten Zahlungserinnerungen und Mahnungen (Migration 072)
     unter dem Abschluss -- dieselbe Zeilenform wie die Schreiben. */
  .mk-mahnungen{ margin-top:18px; }
  .mk-mahnungen .vk-label{ margin:0 0 8px; }
  .mk-leer{
    margin:0; padding:16px 0; text-align:center;
    font-size:0.88rem; color:var(--muted);
  }
  .mk-leer[hidden]{ display:none; }
  /* Die Zeilen der Nebenkosten-Zeiträume sind dieselbe Bauform wie die
     Monate im Mietkonto -- deshalb dieselben Regeln und keine zweite,
     leicht abweichende Kopie. */
  /* Die wiederholbaren Zeilen der Uebergabemaske. Eine Zeile ist eine
     Flex-Reihe, die auf schmalen Bildschirmen umbricht -- `min-width:0`
     an den Feldern, sonst schiebt ein langer Platzhalter die Zeile aus
     dem Dialog (die Falle, die im Handbuch bei den Scroll-Kaesten steht). */
  .uep-block{ margin:0 0 18px; }
  .uep-titel{ margin:0 0 4px; font-size:0.93rem; font-weight:600; }
  .uep-hinweis{ margin:0 0 8px; font-size:0.83rem; color:var(--muted); line-height:1.5; }
  .uep-zeile{ display:flex; gap:8px; flex-wrap:wrap; align-items:center; margin:0 0 6px; }
  .uep-zeile input, .uep-zeile select{ flex:1 1 130px; min-width:0; }
  .uep-zeile .uep-weg{ flex:none; padding:2px 4px; color:var(--muted); }
  .uep-zeile .uep-weg:hover{ color:var(--red); }
  /* Fotos je Raum und Mangel (seit dem 20.10.2026): ein Knopf in der Zeile,
     darunter die Bilder als kleine Marken über die ganze Breite. */
  .uep-zeile .uep-foto{ flex:none; padding:2px 4px; }
  .uep-fotos{ flex:1 1 100%; display:flex; flex-wrap:wrap; gap:6px; min-width:0; }
  .uep-fotos:empty{ display:none; }
  .uep-foto-chip{
    display:inline-flex; align-items:center; gap:6px; max-width:100%; min-width:0;
    padding:3px 4px 3px 4px; border:1px solid var(--line); border-radius:10px; font-size:0.82rem;
  }
  .uep-foto-chip img{ width:34px; height:34px; object-fit:cover; border-radius:6px; flex:none; }
  .uep-foto-chip > span{ min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; max-width:190px; }
  /* Das Kreuz ist ein Tippziel: 44 px, ohne die Marke höher zu machen. */
  .uep-foto-chip .linkbtn{ color:var(--muted); min-width:44px; min-height:44px; margin:-6px 0; padding:0;
    display:inline-flex; align-items:center; justify-content:center; }
  .uep-kopfzeile{ margin:0 0 6px; max-width:260px; }

  /* Die Frist des § 548 Abs. 1 BGB. Drei Stufen, und die Farbe folgt
     der Regel des Projekts: beige heisst "laeuft", rot ist der
     Warnung vorbehalten -- hier dem Fall, dass sie vorbei ist. */
  .uep-frist{
    margin:0 0 12px; padding:10px 12px; border-radius:9px;
    border:1px solid var(--st-grau-rand); background:var(--st-grau-flaeche);
  }
  .uep-frist strong{ display:block; font-size:0.95rem; }
  .uep-frist span{ display:block; font-size:0.84rem; color:var(--muted); margin-top:3px; line-height:1.5; }
  .uep-frist.laeuft{ border-color:var(--st-gruen-rand); background:var(--st-gruen-flaeche); }
  .uep-frist.laeuft strong{ color:var(--st-gruen-text); }
  .uep-frist.knapp{ border-color:var(--st-beige-rand); background:var(--st-beige-flaeche); }
  .uep-frist.knapp strong{ color:var(--st-beige-text); }
  .uep-frist.ab{ border-color:var(--red); }
  .uep-frist.ab strong{ color:var(--red); }
  .mk-zeile, .nk-zeile{
    display:flex; align-items:flex-start; gap:11px;
    padding:10px 0; border-top:1px solid var(--line);
  }
  .nk-zeile:first-of-type{ border-top:0; }
  .nk-balken{ flex:none; width:5px; align-self:stretch; min-height:32px; border-radius:3px; background:var(--st-grau-rand); }
  .nk-zeile.nk-entwurf .nk-balken{ background:var(--st-beige-punkt); }
  .nk-zeile.nk-ok      .nk-balken{ background:var(--st-gruen-punkt); opacity:0.55; }
  .nk-zeile.nk-frist   .nk-balken{ background:var(--red); }
  .nk-text{ flex:1; min-width:0; }
  .nk-text strong{ display:block; font-size:0.93rem; }
  .nk-text span{ display:block; font-size:0.83rem; color:var(--muted); margin-top:1px; }
  .nk-zeile.nk-frist .nk-text span{ color:var(--red); }
  .nk-zeile.nk-ok .nk-text strong{ color:var(--st-gruen-text); }
  .nk-tun{ flex:none; display:flex; gap:10px; flex-wrap:wrap; }
  .nk-tun .linkbtn{ padding:2px 0; font-size:0.85rem; }
  /* Belege aus der Akte zuordnen (Migration 074): eine Zeile je Beleg, die
     ganze Zeile ist das Ziel, das Kästchen links. */
  .mb-wahl{ display:flex; align-items:flex-start; gap:10px; padding:10px 2px; border-top:1px solid var(--line); cursor:pointer; }
  .mb-wahl:first-of-type{ border-top:0; }
  .mb-wahl[hidden]{ display:none; }
  .mb-wahl input{ flex:none; width:18px; height:18px; margin-top:2px; }
  .mb-wahl strong{ display:block; font-size:0.92rem; overflow-wrap:anywhere; }
  .mb-wahl small{ display:block; font-size:0.82rem; color:var(--muted); margin-top:1px; }
  /* Der geöffnete Zeitraum bekommt einen ruhigen Grund, damit man sieht,
     wozu der Inhalt darunter gehört. */
  .nk-zeile.auf{ background:var(--st-grau-flaeche); border-radius:8px 8px 0 0; padding-left:8px; padding-right:8px; }
  .nk-detail{ background:var(--st-grau-flaeche); border-radius:0 0 8px 8px; padding:4px 10px 16px; margin-bottom:10px; }
  /* Kopfzeile der Detailansicht -- dieselbe Bauform wie im Mietkonto:
     die Antwort oben und gross, die Wege daneben. Die Probe entscheidet
     über alles Weitere und traegt deshalb die Farbe. */
  .nk-kopf{
    display:flex; align-items:center; justify-content:space-between;
    gap:14px; flex-wrap:wrap; padding:12px 14px; margin:10px 0 12px;
    border:1px solid var(--st-grau-rand); background:var(--karte); border-radius:12px;
  }
  .nk-kopf.gut{   border-color:var(--st-gruen-rand); background:var(--st-gruen-flaeche); }
  .nk-kopf.offen{ border-color:var(--st-beige-rand); background:var(--st-beige-flaeche); }
  /* Die Abrechnung in vier Schritten, als eigener Bildschirm. */
  .nk-schritte{ display:grid; grid-template-columns:repeat(4, minmax(0, 1fr)); gap:2px; margin:10px 0 8px; }
  .nk-schritt{ display:flex; flex-direction:column; align-items:center; gap:4px; min-width:0; min-height:56px; padding:5px 0;
    background:none; border:0; border-radius:10px; font:inherit; font-size:0.78rem; color:var(--muted); cursor:pointer; }
  .nk-schritt[disabled]{ cursor:default; opacity:0.55; }
  .nk-schritt i{ font-style:normal; width:26px; height:26px; border-radius:50%; display:grid; place-items:center;
    font-weight:700; font-size:0.82rem; background:var(--karte); border:1.5px solid var(--line); }
  .nk-schritt.fertig i{ background:var(--st-gruen-flaeche); border-color:var(--st-gruen-rand); color:var(--st-gruen-text); }
  .nk-schritt.an{ color:var(--ink); font-weight:700; }
  .nk-schritt.an i{ background:var(--gruen-fill); border-color:var(--gruen-fill); color:#fff; }
  .nk-schritt-text{ margin:0 0 10px; }
  .nk-schritt-text h4{ margin:0 0 2px; font-size:1.3rem; outline:none; }
  .nk-schritt-text p{ margin:0; font-size:0.88rem; color:var(--muted); }
  .nk-schritt-fuss{ display:flex; justify-content:space-between; gap:10px; }
  .nk-detail.nk-fokus{ position:fixed; inset:0; z-index:950; margin:0; border-radius:0; overflow-y:auto; overscroll-behavior:contain;
    background:var(--paper); padding:env(safe-area-inset-top) 16px 0; }
  .nk-fokus > *:not(dialog){ max-width:760px; margin-left:auto; margin-right:auto; }
  .nk-uebernahme{ background:var(--karte); border:1px solid var(--st-gruen-rand); border-radius:12px; padding:14px 16px; margin-top:12px; }
  .nk-uebernahme h4{ margin:0 0 2px; font-size:0.98rem; }
  .nk-ueb{ display:flex; align-items:center; gap:10px; min-height:44px; padding:6px 0; border-top:1px solid var(--line); font-size:0.9rem; cursor:pointer; }
  .nk-ueb input{ flex:none; width:20px; height:20px; accent-color:var(--green); }
  .nk-ueb span{ flex:1; min-width:0; overflow-wrap:break-word; }
  .nk-ueb small{ display:block; color:var(--muted); font-size:0.82rem; }
  .nk-ueb strong{ flex:none; font-variant-numeric:tabular-nums; }
  .nk-fokus-kopf{ position:sticky; top:0; z-index:5; display:flex; align-items:center; gap:10px; padding:12px 0; background:var(--paper); border-bottom:1px solid var(--line); }
  .nk-fokus-kopf strong{ display:block; font-size:0.95rem; }
  .nk-fokus-kopf span{ font-size:0.8rem; color:var(--muted); }
  .nk-fokus .nk-schritt-fuss{ position:sticky; bottom:0; z-index:5; margin-top:16px; padding:12px 0 max(12px, env(safe-area-inset-bottom)); background:var(--paper); border-top:1px solid var(--line); }
  .nk-kopf-stand strong{ display:block; font-size:1.05rem; font-variant-numeric:tabular-nums; }
  .nk-kopf-stand span{ font-size:0.84rem; color:var(--muted); }
  .nk-kopf-probe{ font-size:0.86rem; font-weight:600; }
  .nk-kopf.gut   .nk-kopf-probe{ color:var(--st-gruen-text); }
  .nk-kopf.offen .nk-kopf-probe{ color:var(--st-beige-text); }
  .nk-wege{ display:flex; gap:14px; flex-wrap:wrap; }
  .nk-wege .linkbtn{ padding:2px 0; }
  .mk-zeile[hidden]{ display:none; }
  .mk-zeile:first-child{ border-top:0; }
  /* Der farbige Streifen links sagt den Stand, bevor man liest. Rot ist
     hier zulässig und gemeint: fehlendes Geld ist keine Bearbeitungsstufe,
     sondern eine Warnung. Beige = unterstellt, grün = geprüft, grau =
     kommt erst noch. */
  .mk-balken{ flex:none; width:5px; align-self:stretch; min-height:32px; border-radius:3px; background:var(--st-grau-rand); }
  .mk-zeile.mk-offen .mk-balken{ background:var(--red); }
  .mk-zeile.mk-auto  .mk-balken{ background:var(--st-beige-punkt); }
  .mk-zeile.mk-ok    .mk-balken{ background:var(--st-gruen-punkt); opacity:0.55; }
  .mk-zeile-text{ flex:1; min-width:0; }
  .mk-zeile-text strong{ display:block; font-size:0.93rem; }
  .mk-zeile-text > span{ display:block; font-size:0.83rem; color:var(--muted); margin-top:1px; }
  .mk-zeile-tun{ margin-top:3px; display:flex; gap:10px; flex-wrap:wrap; }
  .mk-zeile-tun .linkbtn{ padding:2px 0; font-size:0.82rem; }
  /* Die Aktion der Zeile ist ein flacher Knopf. „zurücknehmen" bleibt ein roter Verweis. */
  body .mk-zeile-tun .linkbtn:not(.del){
    display:inline-flex; align-items:center; min-height:40px; margin:4px 0 0; padding:0 14px;
    border-radius:999px; background:var(--green-soft); font-size:0.84rem;
  }
  body .mk-zeile-tun .linkbtn:not(.del):hover{ background:color-mix(in srgb, var(--green) 14%, var(--karte)); }
  .mk-zeile-lage{
    flex:none; font-size:0.87rem; font-weight:700; text-align:right;
    font-variant-numeric:tabular-nums; padding-top:1px;
  }
  .mk-zeile.mk-offen .mk-zeile-lage{ color:var(--red); }
  .mk-zeile.mk-auto  .mk-zeile-lage{ color:var(--st-beige-text); }
  .mk-zeile.mk-ok    .mk-zeile-lage{ color:var(--muted); font-weight:400; }
  .mk-zeile.mk-kommt .mk-zeile-lage{ color:var(--muted); font-weight:400; }
  /* Bis zum 10.10.2026 rutschte der Betrag unter 520 px unter die Zeile --
     jeder Monat wurde dadurch eine Zeile höher, und die Zahl stand nicht
     mehr dort, wo man sie in einem Kontoauszug sucht. Er bleibt rechts:
     neben „1.050,00 €" bleiben dem Text bei 375 px rund 190 px. */

  .mk-chip{
    display:inline-block; font-size:0.72rem; padding:1px 7px; border-radius:999px;
    background:var(--st-beige-flaeche); color:var(--st-beige-text); border:1px solid var(--st-beige-rand);
  }

  /* ---------- Die Leiste im Reiter Mietverhaeltnis ----------
     Begruendung im Markup. Zwei Spalten am Rechner, untereinander auf dem
     Handy -- dort wird die Leiste eine waagerechte Reihe, damit nichts
     hinter einem Menue verschwindet. */
  .lease-split{ display:grid; grid-template-columns:minmax(0,240px) minmax(0,1fr); gap:20px; align-items:start; }
  .lsb{ display:flex; flex-direction:column; gap:3px; position:sticky; top:14px; }
  .lsb-gruppe{
    margin:12px 0 3px; padding:0 10px; font-size:0.7rem; font-weight:700;
    letter-spacing:0.07em; text-transform:uppercase; color:var(--muted);
  }
  .lsb-gruppe:first-child{ margin-top:0; }
  /* Die Gruppen im Zählerbuch (094): je Einheit und der Hauszähler. Eine
     eigene Klasse -- .lsb-gruppe ist im Handy-Block verborgen, weil die
     Leiste dort umbricht; im Zählerbuch muss die Einheit dastehen. */
  .zb-gruppe{
    margin:16px 0 4px; font-size:0.7rem; font-weight:700;
    letter-spacing:0.07em; text-transform:uppercase; color:var(--muted);
  }
  .zb-verlauf .zahl{ text-align:right; }
  .lsb-eintrag{
    display:flex; align-items:center; gap:9px; width:100%; text-align:left;
    border:1px solid transparent; background:none; border-radius:10px;
    padding:8px 10px; color:var(--ink); min-height:46px;
  }
  .lsb-eintrag:hover{ background:var(--st-grau-flaeche); }
  .lsb-eintrag.an{ background:var(--green-soft); border-color:var(--st-gruen-rand); }
  .lsb-strich{ flex:none; width:4px; align-self:stretch; border-radius:2px; background:var(--st-grau-rand); }
  .lsb-eintrag.ls-gruen .lsb-strich{ background:var(--st-gruen-punkt); }
  .lsb-eintrag.ls-beige .lsb-strich{ background:var(--st-beige-punkt); }
  .lsb-eintrag.ls-rot   .lsb-strich{ background:var(--red); }
  /* Symbol UND Wort. Das Symbol beschleunigt das Wiedererkennen, es
     ersetzt die Beschriftung nicht -- die Zielgruppe ist auch 60+. */
  .lsb-symbol{ flex:none; width:18px; height:18px; color:var(--muted); }
  .lsb-symbol svg{ width:18px; height:18px; display:block; }
  .lsb-eintrag.an .lsb-symbol{ color:var(--green); }
  .lsb-text{ flex:1; min-width:0; }
  .lsb-text strong{ display:block; font-size:0.9rem; font-weight:600; }
  .lsb-text > span{
    display:block; font-size:0.79rem; color:var(--muted);
    overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
  }
  .lsb-eintrag.ls-rot .lsb-text > span{ color:var(--red); font-weight:600; }
  .lsb-eintrag.ls-beige .lsb-text > span{ color:var(--st-beige-text); }
  .lsb-titel{ font-size:1.05rem; margin:0 0 10px; }
  .lease-inhalt{ min-width:0; }
  @media (max-width:820px){
    .lease-split{ grid-template-columns:1fr; gap:14px; }
    /* Die Schalter brechen um (seit dem 08.10.2026). Bis dahin eine Reihe zum
       Wischen ohne Rollbalken -- gemessen bei 375 px: „Nebenkosten" begann
       genau am rechten Rand (353 px) und war damit ganz unsichtbar, ohne
       angeschnittenen Schalter als Hinweis; im Reiter Steuer ebenso „Anlage V"
       und „15-%-Grenze". Derselbe Befund wie am 18.08.2026 an der
       Reiterleiste: was weggescrollt ist, findet niemand. */
    .lsb{
      flex-direction:row; flex-wrap:wrap; position:static; gap:7px;
    }
    .lsb-gruppe{ display:none; }
    /* Mehrere Einheiten (möglich seit dem 13.09.2026): die Schalter heißen je
       Einheit gleich. Ab zwei Einheiten nennt jede Zeile ihre Einheit; bei
       einer bleibt es bei den Schaltern allein. */
    .lsb:has(.lsb-gruppe ~ .lsb-gruppe ~ .lsb-gruppe) .lsb-gruppe{ display:block; flex:1 0 100%; margin:8px 0 0; padding:0 2px; }
    .lsb:has(.lsb-gruppe ~ .lsb-gruppe ~ .lsb-gruppe) .lsb-gruppe:first-child{ margin-top:0; }
    /* 44 px: die Schalter sind auf dem Handy die Navigation des Reiters (bis zum 08.10.2026 38 px). */
    .lsb-eintrag{ flex:none; width:auto; min-height:44px; padding:7px 12px; border:1px solid var(--line); border-radius:999px; }
    .lsb-strich{ display:none; }
    .lsb-text > span{ display:none; }
  }

  /* ---------- Mietausfall & Leerstand ----------
     Drei Kacheln nebeneinander statt einer Summe: Leerstand und
     Zahlungsausfall sind zwei verschiedene Probleme und duerfen nie
     zusammengezaehlt werden. Farben aus der Skala -- beige fuer den
     Leerstand (eine Vermietungsfrage), rot fuer den Ausfall (fehlendes
     Geld ist eine Warnung, keine Bearbeitungsstufe). */
  .af-kacheln{
    display:grid; grid-template-columns:repeat(auto-fit, minmax(180px, 1fr));
    gap:10px; margin-top:14px;
  }
  .af-kachel{
    background:var(--st-grau-flaeche); border:1px solid transparent;
    border-radius:12px; padding:12px 14px;
  }
  .af-kachel.beige{ background:var(--st-beige-flaeche); border-color:var(--st-beige-rand); }
  .af-kachel.rot{ background:var(--rot-flaeche); border-color:var(--rot-rand); }
  .af-kachel > span{ display:block; font-size:0.82rem; color:var(--muted); }
  .af-kachel > strong{
    display:block; font-size:1.42rem; margin-top:2px;
    font-variant-numeric:tabular-nums; line-height:1.2;
  }
  .af-kachel.rot > strong{ color:var(--red); }
  .af-kachel.beige > strong{ color:var(--st-beige-text); }
  .af-kachel > em{ display:block; font-style:normal; font-size:0.78rem; color:var(--muted); margin-top:3px; }
  /* Die Grenze steht im Modul selbst und nicht in einem Hilfetext: sie ist
     der Unterschied zwischen einer Rechnung und einer Steuerauskunft. */
  .af-grenze{
    margin-top:16px; padding:12px 14px; border-radius:10px;
    background:var(--st-beige-flaeche); border:1px solid var(--st-beige-rand);
    font-size:0.86rem;
  }
  .af-grenze p{ margin:6px 0 0; }

  /* ---------- Nachmietersuche: Kalender, Kosten, Rueckwaertsplan ----------
     Dreimal wurde hier ein Fortschrittsbalken verworfen. Er beantwortet
     "wie viel Prozent vorbei" -- gefragt ist "wie viele Wochenenden
     bleiben mir". Deshalb Kalendertage mit Wochentag statt einer Bahn. */
  .nms{ margin-top:14px; border:1px solid var(--line); border-radius:12px; padding:14px 16px; background:var(--karte); }
  .nms-kopf{ display:flex; gap:20px; flex-wrap:wrap; align-items:center; }
  .nms-zahl{ flex:none; text-align:center; min-width:64px; }
  .nms-zahl strong{ display:block; font-size:2.6rem; line-height:1; font-variant-numeric:tabular-nums; }
  .nms-zahl span{ font-size:0.78rem; color:var(--muted); }
  .nms-kosten{ flex:1; min-width:210px; border-left:1px solid var(--line); padding-left:18px; }
  .nms-kosten p{ margin:0; font-size:0.88rem; color:var(--muted); }
  .nms-kosten p + p{ margin-top:3px; }
  .nms-kosten strong{ color:var(--red); }

  .nms-kal{ display:flex; gap:3px; flex-wrap:wrap; margin-top:14px; }
  .nms-tag{
    width:32px; text-align:center; border-radius:7px; padding:3px 0 4px;
    background:var(--st-grau-flaeche); border:1px solid transparent;
  }
  .nms-wt{ display:block; font-size:0.62rem; color:var(--muted); }
  .nms-nr{ display:block; font-size:0.82rem; font-weight:600; font-variant-numeric:tabular-nums; }
  /* Wochenende hebt sich ab, weil dort besichtigt wird -- das ist der
     ganze Grund fuer diese Darstellung. */
  .nms-tag.we{ background:var(--st-gruen-flaeche); border-color:var(--st-gruen-rand); }
  .nms-tag.we .nms-wt, .nms-tag.we .nms-nr{ color:var(--green); }
  .nms-tag.heute{ background:var(--gruen-fill); border-color:var(--gruen-fill); }
  .nms-tag.heute .nms-wt, .nms-tag.heute .nms-nr{ color:#fff; }
  .nms-tag.ziel{ background:var(--rot-flaeche); border-color:var(--rot-rand); }
  .nms-tag.ziel .nms-wt, .nms-tag.ziel .nms-nr{ color:var(--red); }
  .nms-legende{ margin:8px 0 0; font-size:0.8rem; color:var(--muted); }

  .nms-plan{ list-style:none; margin:16px 0 0; padding:0; }
  .nms-plan li{ display:flex; align-items:flex-start; gap:11px; padding:0 0 12px; position:relative; }
  .nms-plan li:not(:last-child)::before{
    content:''; position:absolute; left:74px; top:16px; bottom:0; width:2px; background:var(--line);
  }
  .nms-datum{
    flex:none; width:64px; text-align:right; font-size:0.76rem; color:var(--muted);
    font-variant-numeric:tabular-nums; padding-top:2px;
  }
  .nms-punkt{
    flex:none; width:11px; height:11px; margin-top:4px; border-radius:999px;
    border:2px solid var(--line); background:var(--karte); position:relative; z-index:1;
  }
  .nms-plan li.vorbei .nms-punkt{ background:var(--red); border-color:var(--red); }
  .nms-plan li.vorbei .nms-datum{ color:var(--red); font-weight:600; }
  .nms-plan li.heute .nms-punkt{ background:var(--gruen-fill); border-color:var(--gruen-fill); }
  .nms-was{ flex:1; min-width:0; }
  .nms-was strong{ display:block; font-size:0.9rem; }
  .nms-was span{ font-size:0.79rem; color:var(--muted); }

  .nms-haken{ margin-top:8px; padding-top:12px; border-top:1px solid var(--line); }
  .nms-haken strong{ display:block; font-size:0.87rem; margin-bottom:6px; }
  .nms-haken label{ display:flex; align-items:center; gap:8px; padding:4px 0; font-size:0.88rem; cursor:pointer; }
  .nms-haken input{ width:auto; margin:0; }
  .nms-haken p{ margin:6px 0 0; font-size:0.78rem; color:var(--muted); }
  @media (max-width:520px){
    .nms-kosten{ border-left:0; padding-left:0; }
    .nms-plan li:not(:last-child)::before{ left:74px; }
  }

  /* ---------- Vermietung: was an dieser Einheit als Naechstes ansteht ----------
     Bewusst kein Fortschrittsbalken ueber drei Takte. Der waere zynisch,
     solange noch jemand in der Wohnung wohnt ("Vertrag endet" als Schritt
     eins von drei), und drei Schritte sind zu grob, um wirklich zu fuehren.
     Stattdessen ein Satz, der den Stand nennt, und darunter genau die
     Handlungen, die jetzt dran sind. Ist die Einheit ruhig vermietet,
     schrumpft der Kasten auf eine Zeile, statt einen leeren Ablauf zu
     zeigen. Farben aus derselben Skala wie ueberall: grau, beige, gruen. */
  .verm-karte{
    display:flex; align-items:center; gap:14px; flex-wrap:wrap;
    background:var(--karte); border:1px solid var(--line); border-left:4px solid var(--line);
    border-radius:10px; padding:12px 15px; margin-top:14px;
  }
  .verm-karte.st-gruen{ background:var(--st-gruen-flaeche); border-color:var(--st-gruen-rand); border-left-color:var(--st-gruen-punkt); }
  .verm-karte.st-beige{ background:var(--st-beige-flaeche); border-color:var(--st-beige-rand); border-left-color:var(--st-beige-punkt); }
  .verm-karte.st-grau { background:var(--st-grau-flaeche);  border-color:var(--st-grau-rand);  border-left-color:var(--st-grau-punkt); }
  .verm-text{ flex:1; min-width:200px; }
  .verm-text strong{ display:block; font-size:0.95rem; }
  .verm-text span{ font-size:0.85rem; color:var(--muted); }
  .verm-karte.st-gruen .verm-text strong{ color:var(--st-gruen-text); }
  .verm-karte.st-beige .verm-text strong{ color:var(--st-beige-text); }
  .verm-tun{ display:flex; gap:8px; flex-wrap:wrap; }
  @media (max-width:520px){ .verm-tun{ width:100%; } .verm-tun .btn{ flex:1; } }

  /* ---------- Wohnfläche als Kopfzeile ----------
     Vorher eine eigene Karte mit Überschrift, Absatz, einem Feld und
     einem Knopf -- viel Fläche für eine Zahl. */
  .flaeche-zeile{
    display:flex; align-items:center; gap:12px; flex-wrap:wrap;
    background:var(--karte); border:1px solid var(--line); border-radius:12px;
    padding:12px 16px;
    /* Abstand nach unten (13.09.2026): „zwischen Wohnfläche und dem
       unteren Bereich ist kein bisschen Platz" -- darunter beginnt die
       Leiste, und im Bereich „Vertrag & Mietkonto" klebte der Satz am
       Rahmen. Die Zeile ist die Kopfzeile des Reiters; der Abstand
       gehört an sie und nicht an das, was zufällig darunter folgt. */
    margin:0 0 18px;
  }
  .fz-tun{ flex:none; display:flex; gap:8px; flex-wrap:wrap; }
  .fz-symbol{ flex:none; color:var(--green); display:flex; }
  .fz-symbol svg{ width:19px; height:19px; }
  .fz-text{ flex:1; min-width:150px; display:flex; align-items:center; gap:6px; }
  .fz-form{ display:flex; align-items:center; gap:8px; flex:none; }
  .fz-form input{
    width:110px; padding:8px 10px; border:1px solid var(--line); border-radius:8px;
    font:inherit; text-align:right; font-variant-numeric:tabular-nums;
  }
  .fz-einheit{ color:var(--muted); font-size:0.9rem; }
  /* ⚠️ Auf dem Handy brach diese Zeile zusammen: Titel, das kleine i
     und die Unterzeile standen alle drei in EINER Flex-Reihe, und der
     Ändern-Knopf wurde herausgedrückt. Am 01.09.2026 vom Handy
     gemeldet: „neben Wohnfläche ist alles falsch positioniert".

     Der Block steht bewusst NACH den Grundregeln — eine Media Query
     erhöht die Spezifität nicht, und `syntax-pruefen.mjs` prüft das
     seit dem 29.08. mit. Deshalb auch das `body` davor. */
  @media (max-width:767px){
    body .flaeche-zeile{ align-items:flex-start; }
    body .fz-text{ flex-wrap:wrap; min-width:0; }
    body .fz-unter{ flex:1 0 100%; margin-top:2px; }
    body .fz-tun{ width:100%; }
    body .fz-tun > .btn{ flex:1 1 auto; justify-content:center; }
  }

  /* ---------- Funktionskarte ----------
     Ein Aufklapper, der aussieht wie ein Angebot und nicht wie eine
     Überschrift. Grund: der Kündigungs-Assistent und das Inserat waren
     nacheinander „aufgeräumt" worden -- und dabei jedes Mal versteckt.
     Ein Verweis in einer Textzeile und ein zugeklappter Kasten ganz unten
     sind faktisch kein Zugang; niemand vermutet dort eine Funktion.

     Deshalb: Symbol, Titel, ein Satz was sie tut, und ein Winkel, der
     sagt „hier geht noch etwas auf". Zugeklappt bleibt sie trotzdem --
     sie soll auffindbar sein, nicht dauerhaft Platz belegen. */
  .funktion-klapp{
    border:1px solid var(--line); border-radius:12px; background:var(--karte);
    margin-top:18px; overflow:hidden;
  }
  .funktion-klapp > summary{
    display:flex; align-items:center; gap:12px; cursor:pointer; list-style:none;
    padding:14px 16px; min-height:56px;
  }
  .funktion-klapp > summary::-webkit-details-marker{ display:none; }
  .funktion-klapp > summary:hover{ background:var(--tab); }
  .fk-symbol{
    flex:none; width:38px; height:38px; border-radius:10px;
    background:var(--green-soft); color:var(--green);
    display:flex; align-items:center; justify-content:center;
  }
  .fk-symbol svg{ width:19px; height:19px; }
  .fk-text{ flex:1; min-width:0; }
  .fk-text strong{ display:block; font-size:0.98rem; }
  .fk-text span{ display:block; font-size:0.84rem; color:var(--muted); margin-top:1px; }
  .funktion-klapp > summary::after{
    content:'⌄'; flex:none; color:var(--muted); font-size:1rem; transition:transform .18s ease;
  }
  .funktion-klapp[open] > summary::after{ transform:rotate(180deg); }
  .funktion-klapp[open] > summary{ border-bottom:1px solid var(--line); }
  .fk-inhalt{ padding:16px; }
  @media (prefers-reduced-motion: reduce){
    .funktion-klapp > summary::after{ transition:none; }
  }

  /* ---------- Vertragskarte im Mietverhältnis (13.08.2026) ----------
     Vorher: Zeitraum als Überschrift, alles Weitere als grauer Fliesstext.
     Zahlen, die man vergleichen will, gehören untereinander -- „Kaltmiete
     1.000,00 € · Nebenkosten 500,00 € · Warmmiete 1.500,00 €" in einem
     Satz zwingt zum Lesen statt zum Sehen. */
  .vertrag-karte{ margin-top:14px; }
  /* Ein beendeter Vertrag war bis zum 08.10.2026 auf 72 % abgeblendet -- und
     mit ihm alles darin: die Frist des § 548, die Kautionsabrechnung, die
     offenen Monate, jeder Verweis. Gemessen 3,0:1 für den grauen Text (nötig
     4,5:1). Dass er beendet ist, sagt die Karte im Kopf; abgeblendet wird
     Text nicht mehr, auch nicht in den Regeln für `em` weiter unten. */
  /* Das Zahnrad soll den Namen nicht überstrahlen, aber gefunden werden.
     Bis zum 18.08.2026 war es graues Symbol auf weissem Grund bei 60 %
     Deckkraft -- gemeldet als "geht ein wenig unter, man erkennt es nicht
     sofort". Zu Recht: ohne Fläche und ohne Rand steht es nicht als
     Schaltfläche da, sondern als Verzierung.

     Jetzt eine eigene kleine Fläche im Zetaro-Grün, sehr blass, mit
     grünem Symbol -- erkennbar als "hier kann man etwas tun", ohne die
     Aufmerksamkeit vom Titel zu ziehen. Beim Überfahren füllt sie sich.
     Die Klickfläche bleibt über ::after auf 40 Pixel vergrössert, ohne
     dass das Symbol wächst. */
  .vk-zahnrad{
    border:1px solid var(--st-gruen-rand); background:var(--st-gruen-flaeche);
    padding:5px; border-radius:8px; color:var(--green);
    display:inline-flex; align-items:center; position:relative; opacity:1;
    transition:background 0.12s ease, border-color 0.12s ease;
  }
  .vk-zahnrad::after{ content:''; position:absolute; inset:-10px; }
  .vk-zahnrad:hover, .vk-zahnrad:focus-visible{
    background:var(--gruen-fill); border-color:var(--gruen-fill); color:#fff;
  }
  @media (prefers-reduced-motion: reduce){ .vk-zahnrad{ transition:none; } }
  .vk-zeit{ font-size:0.85rem; color:var(--muted); margin-top:2px; font-variant-numeric:tabular-nums; }
  /* Wege zu einer Aufgabe, in der Farbe der Verweise -- wie im Profil und
     im Mietkonto. Beide öffnen eine Maske im Vordergrund. */
  /* ---------- Die Vertragskarte in drei Baendern ----------
     Was ist vereinbart -- wer wohnt hier -- ist das Geld da. Jedes Band
     traegt seine Handlung oben rechts in seiner eigenen Zeile, nicht
     irgendwo im Fliesstext. Die Ueberschrift ist die Laufzeit und nicht
     mehr der Mietername: die Karte ist ein Vertrag, kein Mensch. */
  .vk-band{ padding:14px 0; border-top:1px solid var(--line); }
  .vk-band:first-of-type{ padding-top:0; border-top:0; }
  .vk-vertrag{ border-left:4px solid var(--st-grau-rand); padding-left:12px; margin-left:-12px; border-radius:0; }
  .vk-vertrag.laeuft{ border-left-color:var(--st-gruen-punkt); }
  .vk-vertrag.beendet{ border-left-color:var(--st-grau-rand); }
  .vk-bandkopf{
    display:flex; align-items:flex-start; justify-content:space-between;
    gap:12px; flex-wrap:wrap; margin-bottom:8px;
  }
  .vk-label{
    margin:0; font-size:0.7rem; font-weight:700; letter-spacing:0.07em;
    text-transform:uppercase; color:var(--muted);
  }
  .vk-titel{ margin:1px 0 0; font-size:1.02rem; font-weight:600; font-variant-numeric:tabular-nums; }
  /* Das Verhaeltnis Kalt zu Nebenkosten -- kein Diagramm ueber die Zeit,
     sondern eine Aufteilung. Bei 500 auf 1.000 sieht man sofort, dass die
     Nebenkostenabrechnung an diesem Vertrag Gewicht hat. */
  .vk-anteil{ display:flex; height:8px; border-radius:4px; overflow:hidden; margin:2px 0 8px; }
  .vk-kalt{ background:var(--gruen-fill); }
  .vk-nk{ background:var(--gruen-fill); opacity:0.38; }
  .vk-fakten{ display:flex; gap:16px; flex-wrap:wrap; font-size:0.85rem; color:var(--muted); }
  .vk-fakten strong{ color:var(--ink); font-variant-numeric:tabular-nums; }
  .vk-fakten em{ font-style:normal; }
  .vk-fakten .pkt{
    display:inline-block; width:8px; height:8px; border-radius:2px;
    margin-right:5px; vertical-align:1px; background:var(--gruen-fill);
  }
  .vk-fakten .pkt.nk{ opacity:0.38; }
  .vk-warnung{
    margin:9px 0 0; padding:9px 11px; border-radius:8px; font-size:0.83rem;
    background:var(--st-beige-flaeche); border:1px solid var(--st-beige-rand);
    color:var(--st-beige-text);
  }
  .vk-notiz{ margin:8px 0 0; font-size:0.85rem; color:var(--muted); }
  .vk-konto{ padding-bottom:0; }
  /* Ziel eines Sprungs aus „Was jetzt ansteht" (Migration 082): kurz
     hinterlegt, damit man sieht, wo man gelandet ist. */
  .vk-band.hervor{ background:var(--st-gruen-flaeche); border-radius:8px; transition:background .4s ease; }

  /* ---------- Die Mieter in der Vertragskarte ----------
     Sie stehen sichtbar da und nicht hinter einem Knopf: sie sind die
     Antwort auf die Frage, mit der man auf einen Vertrag schaut, und ihre
     Erreichbarkeit entscheidet, ob der Mieterkanal ueberhaupt etwas
     melden kann. */
  .mieter-zeile{
    display:flex; align-items:center; gap:10px;
    padding:8px 0; border-top:1px solid var(--line);
  }
  .mieter-zeile:first-of-type{ border-top:0; }
  /* Initialen statt eines Symbols: bei drei Namen untereinander ist der
     Anfangsbuchstabe der schnellste Anker, und er ist fuer jede Person
     ein anderer -- ein Personensymbol waere dreimal dasselbe Bild. */
  .mz-kreis{
    flex:none; width:34px; height:34px; border-radius:50%;
    display:grid; place-items:center; font-size:0.76rem; font-weight:700;
    letter-spacing:0.02em; text-transform:uppercase;
    background:var(--st-gruen-flaeche); color:var(--st-gruen-text);
    border:1px solid var(--st-gruen-rand);
  }
  .mieter-zeile.r-bewohner .mz-kreis,
  .mieter-zeile.r-untermieter .mz-kreis{
    background:var(--st-grau-flaeche); color:var(--st-grau-text); border-color:var(--st-grau-rand);
  }
  .mz-text{ flex:1; min-width:0; }
  .mz-kopf{ display:flex; align-items:center; gap:7px; flex-wrap:wrap; }
  .mz-text strong{ font-size:0.92rem; }
  .mz-text > span{ display:block; font-size:0.83rem; color:var(--muted); overflow-wrap:break-word; }
  .mz-text em{ font-style:normal; }
  .mz-hinweis{ display:block; font-size:0.78rem; color:var(--st-beige-text); margin-top:2px; }
  .mz-erlaubt{ display:block; font-size:0.78rem; color:var(--st-gruen-text); margin-top:2px; }
  /* Die Rolle ist eine Einordnung, keine Bearbeitungsstufe. Deshalb
     traegt nur die Mietpartei -- die, an die geschrieben werden muss --
     die gruene Marke; die beiden anderen bleiben grau. Rot kaeme hier
     nicht in Frage, ein Bewohner ist kein Fehler. */
  .mz-rolle{
    flex:none; font-size:0.72rem; font-weight:600; letter-spacing:0.01em;
    padding:2px 8px; border-radius:999px; white-space:nowrap;
    background:var(--st-grau-flaeche); color:var(--st-grau-text);
    border:1px solid var(--st-grau-rand);
  }
  .mz-rolle.r-mietpartei{
    background:var(--st-gruen-flaeche); color:var(--st-gruen-text); border-color:var(--st-gruen-rand);
  }
  .mz-tun{ flex:none; display:flex; align-items:center; gap:10px; }
  .chip.grau{ background:var(--tab); color:var(--muted); }
  .vk-aktionen{
    display:flex; gap:8px; flex-wrap:wrap; align-items:center;
    margin-top:14px; padding-top:12px; border-top:1px solid var(--line);
  }

  /* ---------- Belegflug ----------
     Das wandernde Blatt. Bewusst dieselbe Anmutung wie das Papier auf dem
     Login-Bildschirm (`.filing .paper`) -- dort ist es das Versprechen,
     hier die Einlösung. `pointer-events:none`, damit es einen Klick
     unterwegs niemals abfängt. */
  .beleg-flug{
    position:fixed; z-index:1200; pointer-events:none;
    max-width:220px; padding:9px 12px; border-radius:7px;
    background:var(--karte); color:var(--ink);
    box-shadow:0 8px 20px rgba(26,26,26,0.20);
    font-size:0.78rem; font-weight:600; line-height:1.25;
    overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
  }
  .beleg-flug small{
    display:block; font-weight:400; color:var(--muted); margin-top:2px;
    overflow:hidden; text-overflow:ellipsis;
  }

  /* Das Ziel leuchtet kurz auf: ohne das landet das Blatt in einer Liste,
     in der man die neue Zeile trotzdem sucht. */
  @keyframes frisch-auf{
    0%   { background:var(--green-soft); }
    100% { background:transparent; }
  }
  .frisch{ animation:frisch-auf 1.6s ease-out; }
  .frisch > td{ animation:frisch-auf 1.6s ease-out; }

  /* Das Papierkorb-Abzeichen bestätigt, dass etwas angekommen ist --
     der Beleg ist eingeschränkt, nicht weg. */
  @keyframes abzeichen-puls{
    0%   { transform:scale(1); }
    35%  { transform:scale(1.35); }
    100% { transform:scale(1); }
  }
  .puls{ animation:abzeichen-puls .5s ease-out; }

  @media (prefers-reduced-motion: reduce){
    .beleg-flug{ display:none; }
    .frisch, .frisch > td, .puls{ animation:none; }
  }

  /* ---------- Eingangsstempel ----------
     Das Empfangsprotokoll im Posteingang. Links der Tagesstempel, rechts
     was daraus wurde -- in der Reihenfolge, in der man Post durchsieht.
     Der Stempel ist bewusst kantig und nicht rund: er zitiert den
     Posteingangsstempel auf Papier, nicht einen Statuspunkt. */
  .eingang-liste{ list-style:none; margin:12px 0 0; padding:0; display:grid; gap:2px; }
  .eingang-liste[hidden]{ display:none; }
  .eingang{
    display:flex; gap:12px; align-items:flex-start;
    padding:10px 0; border-top:1px solid var(--line);
  }
  .eingang:first-child{ border-top:0; }
  .ei-stempel{
    flex:none; width:42px; padding:4px 0; text-align:center;
    border:1.5px solid var(--line); border-radius:3px;
    font-variant-numeric:tabular-nums; line-height:1.1; color:var(--muted);
    /* Leicht schief aufgesetzt, wie von Hand gestempelt. Zwei Grad --
       genug, dass man es spürt, zu wenig, dass es unruhig wirkt. */
    transform:rotate(-2deg);
  }
  .ei-stempel .ei-tag{ display:block; font-size:1rem; font-weight:800; color:var(--ink); }
  .ei-stempel .ei-monat{ display:block; font-size:0.62rem; text-transform:uppercase; letter-spacing:0.08em; }
  .eingang.ok .ei-stempel{ border-color:var(--green); color:var(--green); }
  .eingang.ok .ei-stempel .ei-tag{ color:var(--green); }
  .eingang.fehler .ei-stempel{ border-color:var(--red); color:var(--red); }
  .eingang.fehler .ei-stempel .ei-tag{ color:var(--red); }
  .ei-inhalt{ flex:1; min-width:0; display:grid; gap:1px; font-size:0.86rem; }
  .ei-kopf{ display:flex; justify-content:space-between; gap:10px; align-items:baseline; }
  .ei-kopf strong{ font-weight:600; overflow-wrap:break-word; min-width:0; }
  .ei-uhr{ flex:none; font-size:0.76rem; color:var(--muted); font-variant-numeric:tabular-nums; }
  .ei-betreff{ color:var(--muted); overflow-wrap:break-word; }
  .ei-ergebnis{ font-weight:600; font-size:0.82rem; }
  .eingang.ok .ei-ergebnis{ color:var(--green); }
  .eingang.fehler .ei-ergebnis{ color:var(--red); }
  .eingang.leer .ei-ergebnis{ color:var(--muted); }
  .ei-notiz{ font-size:0.8rem; color:var(--muted); }
  @media (prefers-reduced-motion: reduce){ .ei-stempel{ transform:none; } }

  /* ---------- Zeitleiste ----------
     Dieselben Stempel wie der Posteingang: gestempelte Post, kein
     Diagrammpunkt. Die Farbe des Stempels ist der Stand aus der Skala
     (grau, beige, grün); rot nur für eine Warnung. Ein künftiges Ereignis
     trägt einen gestrichelten Stempel. */
  .zl-leiste{ display:flex; justify-content:space-between; align-items:center; gap:10px; flex-wrap:wrap; }
  .zl-liste{ list-style:none; margin:12px 0 0; padding:0; display:grid; }
  .zl-jahr{ margin:14px 0 0; padding:0 0 4px; font-size:0.72rem; font-weight:800; letter-spacing:0.08em; color:var(--muted); }
  .zl-jahr:first-child{ margin-top:0; }
  .zl-jahr + .eingang, .zl-heute + .eingang{ border-top:0; }
  .zl-heute{ margin:8px 0 4px; padding-top:4px; border-top:2px solid var(--green); font-size:0.74rem; font-weight:700; color:var(--green); }
  .zl-eintrag.ton-gruen .ei-stempel{ border-color:var(--st-gruen-rand); }
  .zl-eintrag.ton-gruen .ei-stempel .ei-tag{ color:var(--st-gruen-text); }
  .zl-eintrag.ton-beige .ei-stempel{ border-color:var(--st-beige-rand); }
  .zl-eintrag.ton-beige .ei-stempel .ei-tag{ color:var(--st-beige-text); }
  .zl-eintrag.ton-rot .ei-stempel{ border-color:var(--red); color:var(--red); }
  .zl-eintrag.ton-rot .ei-stempel .ei-tag{ color:var(--red); }
  .zl-eintrag.kuenftig .ei-stempel{ border-style:dashed; }
  .zl-eintrag.zl-protokoll strong{ font-weight:500; }

  /* ---------- Fristschiene ----------
     Die Strecke zwischen Anfang und Ablauf, mit einer Marke für heute.
     Kein Ring und kein Balken von null: eine Gewährleistung beginnt an
     einem Tag, der in der Akte steht, und den soll man sehen.

     Die Optik folgt dem Aktenmotiv -- eine schmale Bahn wie die Kante
     eines Aktendeckels, die Marke ein aufgesetzter Reiter. */
  .frist-schiene{
    display:flex; align-items:center; gap:8px;
    font-size:0.72rem; color:var(--muted); font-variant-numeric:tabular-nums;
    margin-top:2px;
  }
  .frist-schiene .fs-rand{ flex:none; letter-spacing:0.02em; }
  .frist-schiene .fs-bahn{
    position:relative; flex:1; min-width:60px; height:8px;
    background:var(--line); border-radius:2px; overflow:visible;
  }
  .frist-schiene .fs-gelaufen{
    position:absolute; left:0; top:0; bottom:0;
    border-radius:2px 0 0 2px; background:var(--muted); opacity:0.35;
  }
  /* Die Marke sitzt auf der Bahn wie ein Registerreiter auf der Akte:
     oben breiter als unten, mit einem Fuß, der in die Bahn eintaucht. */
  .frist-schiene .fs-marke{
    position:absolute; top:-5px; bottom:-5px; width:3px; margin-left:-1.5px;
    border-radius:2px; background:var(--ink);
  }
  .frist-schiene .fs-marke::after{
    content:''; position:absolute; left:50%; top:-4px; width:9px; height:6px;
    margin-left:-4.5px; border-radius:2px 2px 0 0; background:inherit;
  }
  .frist-schiene.warn .fs-gelaufen{ background:var(--red); opacity:0.30; }
  .frist-schiene.warn .fs-marke{ background:var(--red); }
  .frist-schiene.ok .fs-gelaufen{ background:var(--gruen-fill); opacity:0.30; }
  .frist-schiene.ok .fs-marke{ background:var(--gruen-fill); }
  .frist-schiene.done{ opacity:0.55; }

  /* ---------- Suchfeld in der Kopfzeile ----------
     Auf breiten Schirmen steht das Feld offen da — sichtbar heißt benutzt.
     Auf dem Handy ist oben rechts kein Platz für Lupe, Feld und Kontoname
     nebeneinander; dort bleibt nur die Lupe stehen und klappt das Feld über
     die ganze Breite auf. */
  .kopf-suche{
    display:flex; align-items:center; gap:6px; margin-left:auto; margin-right:12px;
    border:1px solid var(--line); border-radius:10px; background:var(--karte);
    padding:0 8px 0 6px; height:38px; transition:border-color .12s, box-shadow .12s;
  }
  .kopf-suche:focus-within{ border-color:var(--green); box-shadow:0 0 0 3px var(--green-soft); }
  .kopf-suche-lupe{
    display:flex; align-items:center; justify-content:center; flex:none;
    width:26px; height:26px; padding:0; border:0; background:none;
    color:var(--muted); cursor:pointer;
  }
  .kopf-suche-lupe svg{ width:17px; height:17px; }
  .kopf-suche:focus-within .kopf-suche-lupe{ color:var(--green); }
  .kopf-suche input{
    width:190px; border:0; outline:none; background:none; font:inherit;
    font-size:0.9rem; color:var(--ink); padding:0; min-width:0;
  }
  .kopf-suche input::-webkit-search-cancel-button{ cursor:pointer; }
  .kopf-suche-kbd{
    flex:none; font:inherit; font-size:0.72rem; color:var(--muted);
    border:1px solid var(--line); border-radius:5px; padding:1px 5px; background:var(--paper);
  }
  .kopf-suche:focus-within .kopf-suche-kbd{ visibility:hidden; }
  @media (max-width: 720px){
    .kopf-suche{ margin-right:8px; padding:0; border-color:transparent; background:none; }
    .kopf-suche input, .kopf-suche-kbd{ display:none; }
    .kopf-suche.offen{
      position:absolute; left:14px; right:14px; top:62px; z-index:40;
      padding:0 10px 0 8px; border-color:var(--line); background:var(--karte);
      box-shadow:0 6px 20px rgba(0,0,0,.08);
    }
    .kopf-suche.offen input{ display:block; width:100%; }
    header{ position:relative; }
  }

  /* ---------- Objektübergreifende Suche ---------- */
  .such-liste{ display:flex; flex-direction:column; gap:8px; margin-top:12px; }
  .such-treffer{
    display:flex; flex-direction:column; gap:3px; text-align:left; width:100%;
    border:1px solid var(--line); border-radius:10px; padding:11px 14px;
    background:var(--karte); cursor:pointer; font:inherit; color:var(--ink);
  }
  .such-treffer:hover{ border-color:var(--green); background:var(--green-soft); }
  .such-treffer strong{ font-size:0.95rem; word-break:break-word; }
  .such-treffer span{ font-size:0.84rem; color:var(--muted); }
  .such-treffer .such-objekt{ color:var(--green); font-weight:600; }
  .such-treffer .such-auszug{ white-space:pre-wrap; word-break:break-word; }

  /* ---------- Handwerker-Rückkanal ----------
     Auf der Karte steht nur die Zusammenfassung. Der Gesprächsfaden samt
     Antwortfeld gehört in den Dialog: 230 px Kartenbreite sind für eine
     dichte Eingabemaske das Falsche (siehe ROADMAP, Gestaltungsregeln). */
  .case-card .cc-hw{ font-size:0.85rem; border-top:1px solid var(--line); padding-top:8px; margin-top:2px; }
  .case-card .cc-hw ul{ list-style:none; margin:6px 0 0; padding:0; }
  .case-card .cc-hw li{ margin-bottom:5px; line-height:1.45; word-break:break-word; }
  .hw-state{ display:inline-block; border-radius:999px; padding:1px 9px; font-size:0.76rem; font-weight:600;
             background:#f0efec; color:var(--muted); }
  .hw-state.termin{ background:var(--green-soft); color:var(--green); }
  .hw-state.erledigt{ background:var(--gruen-fill); color:#fff; }
  .hw-state.abgelehnt{ background:var(--rot-flaeche); color:var(--red); }
  .hw-neu{ display:inline-block; background:var(--rot-fill); color:#fff; border-radius:999px;
           padding:1px 8px; font-size:0.72rem; font-weight:700; }

  .rk-box{
    background:var(--karte); border-radius:14px; width:min(640px, 100%); max-height:min(90vh, 100%);
    display:flex; flex-direction:column; overflow:hidden; box-shadow:0 18px 50px rgba(0,0,0,0.28);
  }
  .rk-body{ padding:18px 20px; overflow:auto; }
  .rk-thread{ list-style:none; margin:0 0 14px; padding:0; }
  .rk-thread li{ border:1px solid var(--line); border-radius:10px; padding:9px 13px; margin-bottom:8px;
                 font-size:0.9rem; white-space:pre-wrap; word-break:break-word; }
  .rk-thread li.mine{ background:var(--green-soft); border-color:var(--st-gruen-rand); }
  .rk-thread .who{ display:block; font-size:0.76rem; color:var(--muted); margin-bottom:3px; white-space:normal; }
  .rk-link{ background:var(--green-soft); color:var(--green); padding:7px 11px; border-radius:8px;
            font-size:0.78rem; word-break:break-all; display:block; margin-bottom:8px; }

  /* Fotos aus dem Mieterkanal */
  .foto-strip{ display:flex; gap:8px; flex-wrap:wrap; margin-top:6px; }
  .foto-strip button{ border:1px solid var(--line); border-radius:8px; padding:0; background:none; cursor:pointer;
                      width:64px; height:64px; overflow:hidden; }
  .foto-strip img{ width:100%; height:100%; object-fit:cover; display:block; }

  /* ---------- Handwerker-Anfrage: mehrere Empfänger ---------- */
  .rq-contacts{ display:grid; grid-template-columns:repeat(auto-fill, minmax(240px,1fr)); gap:8px; margin-top:6px; }
  .rq-contact{
    display:flex; align-items:flex-start; gap:9px; padding:9px 11px; line-height:1.4;
    border:1px solid var(--line); border-radius:8px; background:var(--karte); cursor:pointer;
  }
  /* Die Liste steht in einem .field -- ohne diese beiden Regeln zieht
     `.field input{width:100%}` die Ankreuzfelder auf volle Breite und
     schiebt den Namen aus dem Kaestchen heraus. */
  .rq-contact input[type="checkbox"]{ width:auto; flex:none; padding:0; margin:3px 0 0; }
  .rq-contact span{ display:inline; margin:0; font-size:0.9rem; color:var(--ink); }
  .rq-contact > span{ display:block; }
  .rq-contact:has(input:checked){ border-color:var(--green); background:var(--green-soft); }

  /* ---------- Steuer: Gesamtsumme prominent ---------- */
  .tax-total{ background:var(--green-soft); border:1px solid var(--st-gruen-rand); border-radius:12px; padding:20px 22px; margin:14px 0 18px; }
  .tax-total .tt-label{ display:block; font-size:0.78rem; text-transform:uppercase; letter-spacing:0.05em; color:var(--green); margin-bottom:4px; }
  .tax-total .tt-value{ display:block; font-size:clamp(1.8rem, 4vw, 2.3rem); font-weight:800; color:var(--ink); letter-spacing:-0.01em; }
  .tax-total .tt-meta{ display:block; font-size:0.85rem; color:var(--muted); margin-top:4px; }

  /* Anlage V. Die Ergebniszeile benutzt dieselben Marken wie die
     Steueruebersicht (.tt-label/.tt-value) -- eine zweite Gestalt fuer
     dieselbe Aussage waere genau die Doppelung, die auseinanderlaeuft. */
  .av-ergebnis{ background:var(--green-soft); border:1px solid var(--st-gruen-rand);
                border-radius:12px; padding:16px 18px; }
  .av-ergebnis .tt-label{ display:block; font-size:0.78rem; text-transform:uppercase;
                          letter-spacing:0.05em; color:var(--green); margin-bottom:4px; }
  .av-ergebnis .tt-value{ display:block; font-size:clamp(1.5rem, 3.4vw, 1.9rem);
                          font-weight:800; letter-spacing:-0.01em;
                          font-variant-numeric:tabular-nums; }
  .av-tabelle{ width:100%; border-collapse:collapse; }
  .av-tabelle th{ font-size:0.78rem; text-transform:uppercase; letter-spacing:0.05em;
                  color:var(--muted); text-align:left; padding:6px 8px;
                  border-bottom:1px solid var(--line); white-space:nowrap; }
  .av-tabelle td{ padding:8px; border-bottom:1px solid var(--line); }
  .av-tabelle tr.av-summe td{ font-weight:700; border-bottom:none;
                              border-top:2px solid var(--line); }
  /* Grau, nicht rot: ein noch nicht eingeordneter Beleg ist kein Fehler,
     sondern eine offene Frage -- dieselbe Lesart wie in der Farbskala. */
  .av-tabelle tr.av-offen td{ color:var(--muted); font-style:italic; }

  /* ---------- Mieterkanal: Erklärung ---------- */
  .tenant-explain{ display:grid; grid-template-columns:repeat(auto-fit, minmax(190px,1fr)); gap:12px; margin:0 0 18px; }
  .tenant-explain .te-step{ display:flex; gap:10px; align-items:flex-start; font-size:0.88rem; color:var(--muted); }
  .tenant-explain .te-num{
    flex:none; width:22px; height:22px; border-radius:999px; background:var(--green-soft); color:var(--green);
    font-weight:700; font-size:0.78rem; display:flex; align-items:center; justify-content:center;
  }

  /* ---------- Signature: Objektkarten als Aktenreiter ---------- */
  .folders{ display:grid; grid-template-columns:repeat(auto-fill, minmax(240px,1fr)); gap:18px; margin-top:20px; }
  /* Eigentümer-Akten (Migration 069): die Objekte nach Eigentümer gruppiert. */
  .eig-leiste{ display:flex; align-items:center; justify-content:space-between; gap:12px; flex-wrap:wrap; margin:4px 0 0; }
  .eig-gruppe{ margin-top:26px; }
  .eig-kopf{ display:flex; align-items:baseline; justify-content:space-between; gap:6px 14px; flex-wrap:wrap; padding-bottom:8px; border-bottom:1px solid var(--line); }
  .eig-kopf h2{ margin:0; font-size:1.05rem; }
  .eig-kopf .cc-meta{ margin:0; flex:1 1 auto; }
  .eig-gruppe .folders{ margin-top:14px; }
  .eig-zuordnen{ align-items:flex-end; margin:0 0 6px; }
  .folder{
    position:relative; background:var(--karte); border:1px solid var(--line); border-radius:0 12px 12px 12px;
    padding:0 0 16px; text-align:left; transition:transform .12s ease, box-shadow .12s ease;
  }
  .folder::before{ /* der Aktenreiter */
    content:""; position:absolute; top:-12px; left:-1px; width:44%; height:13px;
    background:var(--tab); border:1px solid var(--line); border-bottom:0; border-radius:8px 8px 0 0;
  }
  .folder:hover{ transform:translateY(-2px); box-shadow:0 6px 18px rgba(26,26,26,0.07); }
  .folder-photo{
    width:100%; aspect-ratio:16/10; background:var(--tab); overflow:hidden; border-radius:0 12px 0 0;
    display:flex; align-items:center; justify-content:center; color:var(--green);
  }
  .folder-photo img{ width:100%; height:100%; object-fit:cover; display:block; }
  .folder-photo svg{ width:32%; height:32%; opacity:0.55; }
  .folder-body{ padding:14px 18px 0; }
  .folder h3{ margin:0 0 2px; font-size:1.02rem; }
  .folder .addr{ font-size:0.85rem; color:var(--muted); min-height:1.2em; margin:0 0 10px; }
  .folder .meta{ font-size:0.8rem; color:var(--muted); }
  .folder.new{
    border-style:dashed; display:flex; align-items:center; justify-content:center;
    color:var(--green); font-weight:600; min-height:120px; background:transparent; padding:40px 18px;
  }
  .empty{
    border:1px dashed var(--line); border-radius:12px; padding:34px 22px; text-align:center; color:var(--muted); margin-top:20px;
  }

  /* ---------- Objekt-Detail: Foto ---------- */
  .prop-head{ display:flex; gap:18px; align-items:flex-start; flex-wrap:wrap; }
  .prop-photo{
    width:88px; height:88px; border-radius:12px; overflow:hidden; flex:none;
    background:var(--tab); display:flex; align-items:center; justify-content:center; color:var(--green);
  }
  .prop-photo img{ width:100%; height:100%; object-fit:cover; display:block; }
  .prop-photo svg{ width:44%; height:44%; opacity:0.55; }

  /* ---------- Formulare / Detail ---------- */
  .panel{ background:var(--karte); border:1px solid var(--line); border-radius:12px; padding:22px; margin-top:20px; }
  .row{ display:flex; gap:12px; flex-wrap:wrap; align-items:end; }
  .row .field{ flex:1; min-width:170px; margin-bottom:0; }
  /* Auf schmalen Geräten je Zeile ein Feld. Zwei Auswahlfelder
     nebeneinander mit langem Text („Bauwerksleistung — Dach, Heizung,
     Bad … (5 Jahre)") drängen sich sonst auf 170 Pixel zusammen, und
     man liest weder das eine noch das andere. */
  @media (max-width: 460px){
    .row{ gap:0; }
    .row .field{ min-width:100%; margin-bottom:14px; }
    .row .field:last-child{ margin-bottom:0; }
  }
  .backlink{ font-size:0.9rem; text-decoration:none; display:inline-block; margin-bottom:14px; }
  /* Die sechs Reiter einer Objekt-Akte brachen auf dem Handy in drei Zeilen
     um: die Leiste wuchs auf ein Drittel des Schirms, und der Inhalt darunter
     rutschte aus dem Bild. Jetzt dasselbe Muster wie die Hauptnavigation --
     eine Zeile, die seitwaerts scrollt. Damit bleibt die Leiste immer gleich
     hoch, egal wie viele Reiter dazukommen. */
  .ptabs-wrap{ position:relative; margin-top:18px; }
  .ptabs{
    display:flex; gap:4px; border:1px solid var(--line); background:var(--karte);
    border-radius:10px; padding:4px;
    overflow-x:auto; -webkit-overflow-scrolling:touch;
    scrollbar-width:none;
    /* Ohne diese beiden schiebt die Leiste die Seite auf, statt selbst
       zu scrollen — dann wandert beim Wischen alles mit. */
    min-width:0; max-width:100%;
    /* Beim Wischen an einem Reiter einrasten, statt irgendwo zwischen
       zwei Beschriftungen stehenzubleiben. */
    scroll-snap-type:x proximity;
    overscroll-behavior-x:contain;
  }
  .ptabs button{ scroll-snap-align:start; }
  .ptabs::-webkit-scrollbar{ display:none; }
  /* ---------- Ab Zeigergeräte-Breite bricht die Leiste um ----------
     Am 18.08.2026 gemeldet: "Steuer und Papierkorb sind oben nicht mehr
     sichtbar." Die Leiste scrollte seitwärts, und am Zeigergerät gibt es
     dafür keine Geste und keinen Hinweis -- der Verlaufsschleier rechts
     reicht dafür nicht. Eine weggescrollte Schaltfläche zählt als
     verdeckt, und verdeckte wird etwa halb so oft gefunden wie sichtbare.
     Genau diese Überlegung hat schon die Handy-Navigation nach unten
     geschoben; hier gilt sie ebenso.

     Deshalb: umbrechen statt scrollen, sobald mehr als eine Handybreite
     da ist. Nichts liegt mehr außerhalb des Bildes, und es braucht keine
     zusätzliche Bedienidee (Pfeile, "Mehr"-Menü) -- die wäre wieder eine
     Stelle, an der sich etwas versteckt.

     Auf dem Handy bleibt es beim Wischen: dort ist die Geste vertraut,
     und drei Reihen Reiter kosten zu viel Höhe über der eigentlichen
     Akte. */
  @media (min-width:768px){
    .ptabs{
      flex-wrap:wrap; overflow-x:visible;
      scroll-snap-type:none; row-gap:2px;
    }
    /* Der Schleier zeigte "hier geht es weiter". Wenn nichts mehr
       weitergeht, ist er eine Behauptung. */
    .ptabs-wrap::after{ display:none; }
  }
  .ptabs button{
    border:0; background:transparent; border-radius:8px; padding:9px 14px; font-weight:600; color:var(--muted);
    min-height:44px; display:flex; align-items:center;
    white-space:nowrap; flex:none;
  }
  .ptabs button.active{ background:var(--gruen-fill); color:#fff; }
  /* Der Papierkorb als Symbol, abgesetzt am rechten Ende. margin-left:auto
     schiebt ihn dorthin, solange Platz ist; wird die Leiste schmaler und
     scrollt, steht er einfach hinter dem letzten Reiter — beides ist
     richtig. Der senkrechte Strich trennt ihn von den Arbeitsreitern. */
  .ptabs button.pt-symbol{
    margin-left:auto; padding:9px 12px; color:var(--muted);
    border-left:1px solid var(--line); border-radius:0 8px 8px 0;
  }
  .ptabs button.pt-symbol:hover{ color:var(--ink); }
  .ptabs button.pt-symbol.active{ background:var(--gruen-fill); color:#fff; border-left-color:transparent; }
  /* Wie viele Belege eingeschränkt im Papierkorb liegen -- sichtbar, ohne
     den Reiter zu öffnen. `position:relative` steht am Knopf, damit die
     Zahl an seiner Ecke klebt. */
  .ptabs button.pt-symbol{ position:relative; }
  .ptabs .pt-zahl{
    position:absolute; top:2px; right:2px; min-width:16px; height:16px;
    padding:0 4px; border-radius:999px; background:var(--muted); color:var(--auf-tinte);
    font-size:0.66rem; font-weight:700; line-height:16px; text-align:center;
    font-variant-numeric:tabular-nums;
  }
  .ptabs .pt-zahl[hidden]{ display:none; }
  .ptabs button.pt-symbol.active .pt-zahl{ background:var(--karte); color:var(--green); }
  /* An den Textreitern steht die Zahl daneben, nicht in der Ecke -- dort
     wäre sie über dem Wort. `warn` für alles, was Geld oder einen Mieter
     betrifft: Rückstand und neue Anliegen sind dringlicher als ein
     unzugeordneter Beleg. */
  .ptabs button:not(.pt-symbol){ display:inline-flex; align-items:center; gap:7px; }
  .ptabs button:not(.pt-symbol) .pt-zahl{
    position:static; background:var(--line); color:var(--ink);
    min-width:auto; height:auto; padding:1px 7px; line-height:1.5;
  }
  .ptabs button:not(.pt-symbol) .pt-zahl.warn{ background:#f6d9d5; color:#8a2f22; }
  /* Am gewählten Reiter: weißes Feld, die Schrift in der Farbe ihrer Aussage --
     grün für eine Zahl, rot für fehlendes Geld. Vorher weiß auf einem Viertel
     Weiß über Grün: 3,64:1 bei 10,5 px (gemessen am 08.10.2026). */
  .ptabs button:not(.pt-symbol).active .pt-zahl{ background:var(--karte); color:var(--green); }
  .ptabs button:not(.pt-symbol).active .pt-zahl.warn{ background:var(--karte); color:#8a2f22; }
  /* Ein weicher Rand rechts, solange noch etwas kommt. Ohne dieses Zeichen
     sieht eine abgeschnittene Leiste einfach nach dem Ende aus. */
  .ptabs-wrap::after{
    content:''; position:absolute; right:1px; top:1px; bottom:1px; width:36px;
    border-radius:0 9px 9px 0; pointer-events:none;
    background:linear-gradient(to right, var(--karte-klar), var(--karte) 72%);
    opacity:0; transition:opacity .15s ease;
  }
  .ptabs-wrap.mehr-rechts::after{ opacity:1; }
  @media (prefers-reduced-motion: reduce){ .ptabs-wrap::after{ transition:none; } }
  .ptab-sec{ display:none; }
  .ptab-sec.active{ display:block; }
  table{ width:100%; border-collapse:collapse; margin-top:8px; }
  th{ text-align:left; font-size:0.78rem; text-transform:uppercase; letter-spacing:0.05em; color:var(--muted); padding:8px 10px; border-bottom:1px solid var(--line); }
  td{ padding:10px; border-bottom:1px solid var(--line); font-size:1rem; vertical-align:middle; }
  /* Rechtsbündig, und die Beschriftung eines Knopfes bricht nicht mitten
     im Wort. MEHRERE Knöpfe duerfen dagegen untereinander -- sonst wird
     die Zelle so breit, dass die ganze Tabelle aus ihrer Karte laeuft.
     Genau das ist am 22.08.2026 passiert, als die Kostenpositionen ein
     zweites "Aendern" bekamen: `nowrap` galt fuer die ganze Zelle, also
     auch fuer den Abstand zwischen den Knoepfen.

     ⚠️ ABER KEIN display:flex AN DER ZELLE SELBST (13.09.2026). Die
     Loesung von damals setzte die Zelle auf flex -- und eine Zelle mit
     flex ist keine Tabellenzelle mehr: sie waechst nicht mit der Zeile,
     ihr unterer Rand sitzt auf eigener Hoehe. Beanstandet an der
     Belegliste: „ab dem Button Ansehen ist der Strich drunter falsch
     versetzt". Umbrechen koennen die Knoepfe als inline-block von selbst.
     tools/syntax-pruefen.mjs misst seitdem, dass keine Regel an einer
     Zelle wieder flex oder grid setzt. */
  td.actions{ text-align:right; }
  td.actions > *{ white-space:nowrap; display:inline-block; margin:2px 0 2px 10px; }
  td.actions > :first-child{ margin-left:0; }

  /* ---------- E-Rechnungs-Ansicht ---------- */
  .sheet{
    background:var(--karte); border:1px solid var(--line); border-radius:12px;
    padding:30px 32px; max-width:780px; margin-top:20px;
  }
  .sheet .badge{
    display:inline-block; font-size:0.72rem; font-weight:700; letter-spacing:0.05em; text-transform:uppercase;
    background:var(--green-soft); color:var(--green); border-radius:999px; padding:3px 12px; margin-bottom:16px;
  }
  .inv-head{ display:flex; justify-content:space-between; gap:24px; flex-wrap:wrap; }
  .inv-party{ font-size:0.92rem; min-width:200px; }
  .inv-party .role{ font-size:0.72rem; text-transform:uppercase; letter-spacing:0.06em; color:var(--muted); margin-bottom:3px; }
  .inv-party .pname{ font-weight:700; }
  .inv-meta{ display:flex; gap:26px; flex-wrap:wrap; margin:20px 0 6px; padding:12px 0; border-top:1px solid var(--line); border-bottom:1px solid var(--line); }
  .inv-meta div{ font-size:0.9rem; }
  .inv-meta .k{ font-size:0.72rem; text-transform:uppercase; letter-spacing:0.06em; color:var(--muted); display:block; }
  .inv-totals{ margin-left:auto; margin-top:14px; max-width:300px; font-size:0.94rem; }
  .inv-totals div{ display:flex; justify-content:space-between; padding:4px 0; }
  .inv-totals .grand{ border-top:2px solid var(--ink); margin-top:6px; padding-top:8px; font-weight:800; font-size:1.05rem; }
  .inv-pay{ margin-top:18px; background:var(--green-soft); border-radius:9px; padding:12px 16px; font-size:0.9rem; }
  .pay-block{
    margin-top:18px; border:1px solid var(--line); border-radius:12px; padding:16px 18px;
    display:flex; gap:20px; align-items:center; justify-content:space-between; flex-wrap:wrap;
  }
  .pay-block > div:first-child{ flex:1; min-width:220px; }
  .pay-qr{ display:flex; flex-direction:column; align-items:center; gap:4px; font-size:0.75rem; color:var(--muted); }
  .pay-qr canvas{ border:1px solid var(--line); border-radius:8px; }
  .inv-note{ margin-top:16px; font-size:0.8rem; color:var(--muted); }
  /* ---------- Umgebungsbalken ----------
     Nur ausserhalb der Produktion sichtbar. Bewusst kraeftig und quer
     ueber die volle Breite: ein dezenter Hinweis wird nach dem dritten Mal
     nicht mehr gelesen, und dann legt jemand Testdaten in der echten
     Datenbank an -- oder haelt echte Daten fuer Testdaten und loescht sie. */
  .umgebung-balken{
    padding:8px 16px; text-align:center; font-size:0.85rem; font-weight:700;
    background:#3b3a36; color:#fff; letter-spacing:0.01em;
  }
  .umgebung-balken.warnung{ background:var(--rot-fill); }
  .umgebung-balken code{
    background:rgba(255,255,255,0.18); border-radius:5px; padding:1px 6px; font-weight:600;
  }

  .linkbtn{ border:0; background:none; color:var(--green); font-weight:600; padding:4px 6px; }
  .linkbtn.del{ color:var(--red); }
  /* Symbol und Beschriftung sitzen auf einer Linie. Der Text bleibt immer
     dabei -- ein blosses Symbol muss man raten, und die Zielgruppe ist
     ausdrücklich auch 60+. Das Symbol beschleunigt das Wiedererkennen,
     es ersetzt die Beschriftung nicht. */
  .linkbtn:has(svg), .btn:has(svg){
    display:inline-flex; align-items:center; gap:6px;
  }
  .btn:has(svg){ justify-content:center; }
  /* Größe MUSS hier stehen. Die Symbole aus ICONS tragen nur ein viewBox
     und keine width/height -- ohne Regel nimmt der Browser die Ersatzgröße
     für ersetzte Elemente (300 × 150) und zeichnet ein riesiges Bild.
     Genau so am 13.08.2026 am Knopf „Steuerübersicht" passiert. In
     `.panel-head svg` stand die Größe schon; für Knöpfe fehlte sie. */
  .linkbtn svg, .btn svg{ flex:none; width:16px; height:16px; color:inherit; }
  @media (prefers-reduced-motion: reduce){ .folder{ transition:none; } }

  /* ---------- Toasts ---------- */
  #toastHost{ position:fixed; right:18px; bottom:18px; display:flex; flex-direction:column; gap:8px; z-index:1000; max-width:340px; }
  /* Über der unteren Navigationsleiste, sonst verdeckt sie die Meldung --
     und gerade die Fehlermeldung ist die, die gelesen werden muss. */
  @media (max-width:767px){
    #toastHost{ right:12px; left:12px; max-width:none; bottom:calc(74px + env(safe-area-inset-bottom)); }
  }
  .toast{
    background:var(--ink); color:var(--auf-tinte); border-radius:8px; padding:12px 16px; font-size:0.9rem;
    box-shadow:0 8px 20px rgba(0,0,0,0.18); opacity:0; transform:translateY(8px); transition:opacity .2s ease, transform .2s ease;
  }
  /* Der Art.-18-Hinweis im Papierkorb. Beige aus der Skala: eine
     laufende Aufbewahrungsfrist ist kein Fehler, sondern ein Zustand. */
  .hinweis-art18{
    margin:12px 0 0; padding:11px 14px; border-radius:9px; font-size:0.86rem; line-height:1.55;
    background:var(--st-beige-flaeche); border:1px solid var(--st-beige-rand); color:var(--st-beige-text);
  }
  .toast.show{ opacity:1; transform:translateY(0); }
  .toast.err{ background:var(--rot-fill); color:#fff; }
  /* Text, Zaehler und Kreuz nebeneinander. min-width:0 am Text, sonst
     schrumpft er nicht unter seine Inhaltsbreite und die Meldung
     schiebt sich aus dem Bild. */
  .toast{ display:flex; align-items:flex-start; gap:10px; max-width:min(420px, calc(100vw - 32px)); }
  .toast-text{ flex:1; min-width:0; }
  /* Ohne Abblenden: der Zaehler stand auf der roten Meldung bei 3,9:1 (08.10.2026). */
  .toast-mal{ font-variant-numeric:tabular-nums; font-size:0.82rem; padding-top:1px; }
  .toast-zu{
    background:none; border:0; color:inherit; font-size:1.15rem; line-height:1;
    cursor:pointer; padding:0 1px; opacity:0.8; flex-shrink:0;
  }
  .toast-zu:hover{ opacity:1; }
  .toast-zu:focus-visible{ outline:2px solid currentColor; outline-offset:2px; border-radius:3px; }
  @media (prefers-reduced-motion: reduce){ .toast{ transition:none; } }

  /* ---------- Geführte Tour ---------- */
  .tour-overlay{ position:fixed; inset:0; background:rgba(26,26,26,0.45); z-index:1500; }
  .tour-highlight{ position:relative; z-index:1600 !important; outline:3px solid #ffd98e; outline-offset:3px; border-radius:8px; background:var(--karte); }
  .tour-bubble{
    position:fixed; z-index:1700; width:min(320px, calc(100vw - 24px));
    background:var(--karte); border:1px solid var(--line); border-radius:12px; padding:16px 18px;
    box-shadow:0 12px 32px rgba(0,0,0,0.25);
  }
  .tour-bubble .tb-step{ font-size:0.78rem; color:var(--muted); margin-bottom:4px; }
  .tour-bubble .tb-title{ font-weight:700; margin-bottom:4px; }
  .tour-bubble .tb-text{ font-size:0.92rem; margin-bottom:12px; }
  .tour-bubble .tb-actions{ display:flex; gap:8px; justify-content:flex-end; }

  /* ---------- Verfahrensdoku: Druckansicht ---------- */
  .vdoc-sheet{ font-family:Georgia, "Times New Roman", serif; line-height:1.6; }
  .vdoc-sheet h2{ font-size:1.05rem; margin-top:26px; }
  @media print{
    header, .topnav, .no-print, #toastHost{ display:none !important; }
    main{ max-width:none; padding:0; }
    .vdoc-sheet{ border:0; padding:0; }
    body{ background:#fff; }
  }

  /* ---------- Skeleton-Loader ---------- */
  @keyframes skeleton-pulse{ 0%,100%{ opacity:1; } 50%{ opacity:0.45; } }
  .skeleton{ background:var(--line); animation:skeleton-pulse 1.3s ease-in-out infinite; }
  .skel-card{ min-height:140px; border-radius:12px; border:1px solid var(--line); }
  .skel-line{ height:14px; border-radius:6px; margin:10px 0; }
  @media (prefers-reduced-motion: reduce){ .skeleton{ animation:none; opacity:0.5; } }
  /* ---------- 16px gegen den iOS-Zoom ----------

     ⚠️ Am 01.09.2026 vom iPhone gemeldet: „Die App startet immer noch
     zu nah." Auf dem Bild fehlte die Kopfleiste und alles war groesser
     — die Seite war hineingezoomt.

     Ursache: Safari zoomt beim Antippen eines Eingabefeldes hinein,
     sobald dessen Schrift KLEINER ALS 16px ist — und zoomt danach
     nicht wieder heraus. Die Felder hier erben ihre Groesse
     (`font:inherit`), und in Kaesten mit 0.9rem sind das 14,4px.
     Einmal ein Feld angetippt, und die App bleibt vergroessert; beim
     naechsten Start sieht es aus, als starte sie so.

     Am Schreibtisch faellt das nie auf: dort gibt es kein Tippen und
     keinen automatischen Zoom.

     ⚠️ Der Block steht am ENDE des Stilblocks und traegt `body` vor
     jedem Selektor. Eine Media Query erhoeht die Spezifitaet nicht,
     und `.field input{ font:inherit }` (Klasse plus zwei Typen) muss
     geschlagen werden — `body input` allein reichte nicht.

     Bewusst KEIN `maximum-scale=1` im viewport-Tag: das verbietet auch
     das absichtliche Aufziehen mit zwei Fingern, und wer schlecht
     sieht, braucht es. */
  @media (max-width: 767px){
    /* ⚠️ Hier stand eine Aufzaehlung von Selektoren, und sie war beim
       ersten Nachmessen schon unvollstaendig: das Suchfeld in der
       Kopfzeile stand weiter auf 14,4px -- ausgerechnet das Feld, das
       auf dem Handy am haeufigsten angetippt wird.

       Eine Liste von Selektoren laeuft genau so auseinander wie jede
       andere gepflegte Liste in diesem Projekt. Deshalb `!important`:
       generisch geht es nicht, denn `.field input` (Klasse plus zwei
       Typen) schlaegt jeden Selektor aus reinen Typen, und ein
       Wettruesten der Spezifitaet waere dieselbe Liste in Tarnung.

       Es ist eines von fuenf `!important` im Projekt (das fuenfte seit
       dem 10.10.2026: `.nur-handy`), und wie die anderen garantiert es
       eine EIGENSCHAFT und kein Aussehen: [hidden] bleibt verborgen, der
       Ausdruck laesst Navigation weg, und hier zoomt nichts ungewollt.
       */
    input, select, textarea{ font-size:16px !important; }
  }

  /* =====================================================================
     Glas-Stil (28.09.2026)

     Gewünscht vom Inhaber mit zwei Bildschirmvideos einer iOS-App
     („Bedienerfreundlichkeit und Layout super — kannst du das bei mir
     auch so aufbauen?"). Übernommen sind die BAUFORMEN, nicht das
     Aussehen einer fremden Marke -- und die Bauformen sind Apples eigene
     (iOS 26, „Liquid Glass"): eine schwebende Leiste unten, ein runder
     Schnellknopf daneben, ein rundes Kontobild oben rechts, ein großer
     Gruß, Karten mit großem Radius auf grauem Grund, Masken als Blatt
     von unten. Farben und Schrift bleiben Zetaros.

     ⚠️ Der Block steht am ENDE des Stilblocks: bei gleicher Spezifität
     gewinnt die spätere Regel. Oben stehen die Grundregeln, darunter die
     Handy-Abfrage -- nie umgekehrt, sonst überschreibt eine spätere
     Grundregel die Handy-Regel (syntax-pruefen.mjs wacht darüber). In der
     Handy-Abfrage trägt jede Regel `body` davor, die Regel vom 29.08.2026.

     Der Grund der App ist ein warmes Hellgrau statt Creme: auf Creme
     verschwammen weiße Karte und Seitengrund, und genau der Abstand
     zwischen beiden macht die Ruhe des Vorbilds aus. `body.app-an`
     setzt die Anmeldung; die Anmeldemaske behält ihr Aussehen.
     ===================================================================== */
  :root{
    --grund:#f2f0ea;
    --glas:rgba(255,255,255,0.74);
    --glas-rand:rgba(255,255,255,0.72);
    --glas-dicht:rgba(255,255,255,0.94); --glas-knopf:rgba(255,255,255,0.9);
    --grund-glas:rgba(242,240,234,0.8); --grund-klar:rgba(242,240,234,0);
    --glas-schatten:0 12px 32px rgba(26,26,26,0.14), 0 2px 6px rgba(26,26,26,0.06);
    --r-karte:20px;
    --karte-schatten:0 1px 2px rgba(26,26,26,0.05), 0 8px 24px rgba(26,26,26,0.05);
  }
  body.app-an{ background:var(--grund); }

  /* Karten: großer Radius und ein weicher Schatten statt des Randes. */
  body.app-an .panel, body.app-an .setup, body.app-an .tile{
    border-color:transparent; border-radius:var(--r-karte); box-shadow:var(--karte-schatten);
  }
  body.app-an .avv-bar{ border-radius:var(--r-karte); }
  /* Knöpfe als Pillen, Felder weicher. */
  body.app-an .btn{ border-radius:999px; }
  body.app-an .field input, body.app-an .field select, body.app-an .field textarea{ border-radius:12px; }
  body.app-an main h1{ font-size:1.6rem; font-weight:800; letter-spacing:-0.02em; line-height:1.2; }

  /* Objektkarten: der Aktenreiter bleibt -- er ist Zetaros Zeichen --,
     aber weiß wie die Karte, sonst verschwindet er auf dem grauen Grund. */
  body.app-an .folder{
    border-color:transparent; border-radius:0 var(--r-karte) var(--r-karte) var(--r-karte);
    box-shadow:var(--karte-schatten);
  }
  body.app-an .folder::before{ background:var(--karte); border-color:transparent; box-shadow:0 -2px 5px rgba(26,26,26,0.03); }
  body.app-an .folder-photo{ border-radius:0 var(--r-karte) 0 0; }
  body.app-an .folder.new{ border:2px dashed #d3cdbf; border-radius:var(--r-karte); box-shadow:none; background:transparent; }
  body.app-an .folder.new::before{ display:none; }

  /* ---------- Das Kontobild ----------
     Die Anfangsbuchstaben statt eines Fotos: ein Profilbild wäre eine
     neue Datenart (Verzeichnis nach Art. 30, Löschklasse), und die
     Buchstaben erfüllen denselben Zweck -- man erkennt sein Konto. */
  .konto-avatar{
    display:inline-flex; align-items:center; justify-content:center; flex:none;
    width:30px; height:30px; border-radius:50%;
    background:var(--gruen-fill); color:#fff; font-weight:700; font-size:0.8rem; letter-spacing:0.02em;
  }
  body.app-an .btn.account-trigger{ border-radius:999px; padding:5px 12px 5px 5px; }
  body.app-an .btn.bereich-trigger{ border-radius:999px; padding:8px 12px; min-height:42px; }
  body.app-an .account-dropdown{
    border-radius:18px; border-color:rgba(26,26,26,0.06); background:var(--glas-dicht);
    -webkit-backdrop-filter:saturate(180%) blur(20px); backdrop-filter:saturate(180%) blur(20px);
    box-shadow:0 18px 50px rgba(26,26,26,0.18);
  }
  body.app-an .account-dropdown button{ border-radius:12px; }

  /* ---------- Der Schnellknopf „Beleg ablegen" ----------
     Rechts neben der schwebenden Leiste, wie im Vorbild der runde Knopf
     neben den Reitern. Er öffnet schnellBeleg(): Foto oder Datei, Objekt,
     Art -- drei Griffe, und der Zettel ist abgelegt. Nur auf dem Handy:
     am Schreibtisch liegt das Hochladen in der Akte ohnehin offen da. */
  .schnell-knopf{
    position:fixed; right:12px; bottom:calc(10px + env(safe-area-inset-bottom)); z-index:41;
    width:66px; height:66px; border-radius:50%; padding:0;
    display:flex; align-items:center; justify-content:center;
    border:1px solid var(--glas-rand); background:var(--glas); color:var(--green);
    -webkit-backdrop-filter:saturate(180%) blur(24px); backdrop-filter:saturate(180%) blur(24px);
    box-shadow:var(--glas-schatten); -webkit-tap-highlight-color:transparent;
    transition:transform .12s ease;
  }
  .schnell-knopf svg{ width:27px; height:27px; }
  .schnell-knopf:active{ transform:scale(0.93); }
  @media (min-width:768px){ .schnell-knopf{ display:none; } }

  /* ---------- Startseite: was ansteht (10.10.2026) ----------
     Vier Karten unter dem Gruß, jede mit EINER Zahl. Am Schreibtisch in
     einer Reihe, am Handy zwei nebeneinander. Die Zahl trägt die Farbe, nicht
     die Fläche: rot nur für fehlendes Geld, beige für „hier liegt Arbeit",
     grün für „in Ordnung" -- die Skala des Projekts. */
  .lage{ display:grid; grid-template-columns:repeat(auto-fit, minmax(150px, 1fr)); gap:12px; margin-top:18px; }
  .lage:empty{ display:none; }
  .lage-karte{
    display:flex; flex-direction:column; align-items:flex-start; gap:1px; min-width:0; min-height:88px;
    padding:12px 14px 13px; border:0; border-radius:16px; background:var(--karte); box-shadow:var(--karte-schatten);
    font:inherit; color:var(--ink); text-align:left;
  }
  button.lage-karte{ cursor:pointer; transition:transform .12s ease, box-shadow .12s ease; }
  button.lage-karte:hover{ transform:translateY(-1px); box-shadow:0 2px 4px rgba(26,26,26,0.06), 0 10px 26px rgba(26,26,26,0.08); }
  button.lage-karte:active{ transform:scale(0.98); }
  button.lage-karte:focus-visible{ outline:2px solid var(--green); outline-offset:2px; }
  .lage-label{ font-size:0.7rem; font-weight:700; letter-spacing:0.07em; text-transform:uppercase; color:var(--muted); }
  .lage-wert{ font-size:1.22rem; line-height:1.3; font-weight:800; letter-spacing:-0.01em; font-variant-numeric:tabular-nums; overflow-wrap:anywhere; }
  .lage-unter{ font-size:0.8rem; line-height:1.35; color:var(--muted); }
  .lage-karte.rot .lage-wert{ color:var(--red); }
  .lage-karte.beige .lage-wert{ color:var(--st-beige-text); }
  .lage-karte.gruen .lage-wert{ color:var(--green); }
  .lage-karte.laedt{ width:100%; }
  @media (prefers-reduced-motion: reduce){ button.lage-karte{ transition:none; } button.lage-karte:hover, button.lage-karte:active{ transform:none; } }

  /* Nur am Handy zu sehen. Als Regel für den SCHREIBTISCH und mit !important:
     der erste Anlauf versteckte die Klasse von Grund auf und blendete sie in
     der Handy-Abfrage ein -- `.btn.quiet` (zwei Klassen) und
     `td.actions > *` schlugen das, und „Beleg ablegen" stand am Schreibtisch
     neben dem Kasten, den es ersetzen soll (gemessen bei 1280 px). Es ist das
     fünfte !important im Projekt, und wie die anderen garantiert es eine
     Eigenschaft und kein Aussehen. */
  @media (min-width:768px){ .nur-handy{ display:none !important; } }

  /* ---------- Startseite: die Objekte als Karten zum Wischen ---------- */
  .start-objekte{ margin-top:20px; }
  .sk-kopf{ display:flex; align-items:baseline; justify-content:space-between; gap:12px; margin:0 0 10px; }
  .sk-kopf h2{ margin:0; font-size:1.15rem; letter-spacing:-0.01em; }
  .sk-bahn{
    display:flex; gap:12px; overflow-x:auto; scroll-snap-type:x mandatory;
    -webkit-overflow-scrolling:touch; scrollbar-width:none; padding:4px 2px 16px; margin:0 -2px;
  }
  .sk-bahn::-webkit-scrollbar{ display:none; }
  .sk-karte{
    position:relative; flex:0 0 min(300px, 84%); aspect-ratio:4 / 5; max-height:420px;
    scroll-snap-align:start; border:0; padding:0; border-radius:26px; overflow:hidden; cursor:pointer;
    background:linear-gradient(160deg, #1b8070 0%, #0d6e5f 52%, #0a574b 100%); color:#fff; text-align:left;
    box-shadow:0 12px 28px rgba(26,26,26,0.16); font:inherit;
  }
  .sk-karte img{ position:absolute; inset:0; width:100%; height:100%; object-fit:cover; display:block; }
  .sk-karte::after{
    content:''; position:absolute; left:0; right:0; bottom:0; height:58%; pointer-events:none;
    background:linear-gradient(to top, rgba(0,0,0,0.6), rgba(0,0,0,0));
  }
  .sk-symbol{ position:absolute; right:-8%; top:7%; width:64%; color:#fff; opacity:0.16; }
  .sk-symbol svg{ display:block; width:100%; height:auto; }
  .sk-text{ position:absolute; left:18px; right:18px; bottom:18px; z-index:1; display:flex; flex-direction:column; gap:3px; }
  .sk-art{ font-size:0.68rem; font-weight:700; letter-spacing:0.12em; text-transform:uppercase; opacity:0.85; }
  .sk-text strong{ font-size:1.3rem; line-height:1.2; }
  .sk-text em{ display:block; font-style:normal; font-size:0.86rem; opacity:0.9; }
  .sk-karte.neu{ background:var(--karte); color:var(--green); border:2px dashed #d3cdbf; box-shadow:none; }
  .sk-karte.neu::after{ display:none; }
  .sk-karte.neu .sk-text{ bottom:auto; top:50%; transform:translateY(-50%); align-items:center; text-align:center; }
  .sk-punkte{ display:flex; justify-content:center; gap:6px; }
  .sk-punkte i{ width:7px; height:7px; border-radius:4px; background:rgba(26,26,26,0.18); transition:width .2s ease, background .2s ease; }
  .sk-punkte i.an{ width:20px; background:var(--ink); }
  @media (prefers-reduced-motion: reduce){ .sk-punkte i{ transition:none; } .schnell-knopf{ transition:none; } }

  /* ---------- Das Blatt „Beleg ablegen" ---------- */
  .sb-datei{ display:block; cursor:pointer; }
  .sb-datei input{ position:absolute; width:1px; height:1px; opacity:0; pointer-events:none; }
  .sb-datei-feld{
    display:flex; flex-direction:column; align-items:center; gap:4px; text-align:center;
    padding:20px 16px; border:2px dashed #cfd9d6; border-radius:18px; background:var(--green-soft); color:var(--green);
  }
  .sb-datei-feld svg{ width:30px; height:30px; }
  .sb-datei-feld em{ font-style:normal; font-size:0.82rem; color:var(--muted); }
  .sb-datei input:focus-visible + .sb-datei-feld{ outline:2px solid var(--green); outline-offset:2px; }
  .sb-datei.gewaehlt .sb-datei-feld{ border-style:solid; background:var(--karte); }
  .sb-abschnitt{ margin:18px 4px 6px; font-size:0.74rem; font-weight:700; letter-spacing:0.08em; text-transform:uppercase; color:var(--muted); }
  .sb-liste{ background:var(--karte); border:1px solid var(--line); border-radius:16px; overflow:hidden; }
  .sb-zeile{ display:flex; align-items:center; gap:12px; padding:12px 14px; cursor:pointer; min-height:52px; }
  .sb-zeile + .sb-zeile{ border-top:1px solid var(--line); }
  .sb-zeile input{ position:absolute; opacity:0; pointer-events:none; }
  .sb-text{ flex:1; min-width:0; display:flex; flex-direction:column; }
  .sb-text strong{ font-weight:600; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .sb-text em{ font-style:normal; font-size:0.82rem; color:var(--muted); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .sb-haken{
    flex:none; width:24px; height:24px; border-radius:50%; border:2px solid #d6d1c6;
    display:flex; align-items:center; justify-content:center;
  }
  .sb-zeile input:checked ~ .sb-haken{ background:var(--ink); border-color:var(--ink); }
  .sb-zeile input:checked ~ .sb-haken::after{
    content:''; width:9px; height:5px; border:solid var(--auf-tinte); border-width:0 0 2px 2px; transform:translateY(-1px) rotate(-45deg);
  }
  .sb-zeile input:focus-visible ~ .sb-text strong{ text-decoration:underline; }
  .sb-arten{ display:flex; flex-wrap:wrap; gap:8px; }
  .sb-art{ position:relative; cursor:pointer; }
  .sb-art input{ position:absolute; opacity:0; pointer-events:none; }
  .sb-art span{
    display:inline-flex; align-items:center; min-height:40px; padding:0 14px; border-radius:999px;
    background:var(--karte); border:1px solid var(--line); font-weight:600; font-size:0.9rem;
  }
  .sb-art input:checked + span{ background:var(--ink); border-color:var(--ink); color:var(--auf-tinte); }
  .sb-art input:focus-visible + span{ outline:2px solid var(--green); outline-offset:2px; }

  @media (max-width:767px){
    /* Die Kopfzeile bleibt stehen und wird zu Glas: der Inhalt gleitet
       darunter durch, wie im Vorbild. */
    body.app-an header{
      position:sticky; top:0; z-index:45;
      padding:10px 16px; padding-top:calc(10px + env(safe-area-inset-top));
      background:var(--grund-glas); border-bottom:1px solid rgba(26,26,26,0.05);
      -webkit-backdrop-filter:saturate(180%) blur(20px); backdrop-filter:saturate(180%) blur(20px);
    }
    /* Oben rechts nur das runde Kontobild. Der Name bleibt für
       Vorlesehilfen im Knopf, er wird nur nicht gezeigt. */
    body .btn.account-trigger{ padding:0; border:0; background:none; box-shadow:none; }
    body .account-trigger .konto-avatar{ width:40px; height:40px; font-size:0.95rem; box-shadow:0 3px 10px rgba(13,110,95,0.28); }
    body .account-trigger #accountBtnName{
      position:absolute; width:1px; height:1px; overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap;
    }
    body .account-trigger .caret{ display:none; }
    /* Der Bereich bleibt auch auf dem Handy mit Namen stehen -- er soll
       sichtbar sein, nicht hinter einem Symbol versteckt. */
    body .bereich-menu{ margin-right:6px; position:static; }
    body.app-an .btn.bereich-trigger{ padding:6px 10px; min-height:44px; font-size:0.9rem; gap:5px; }
    body .bereich-trigger .caret{ display:none; }
    /* Das Menü hängt an der Kopfzeile, nicht am Knopf: am Knopf
       ausgerichtet liefe es bei 375 px links aus dem Bild. */
    body .account-dropdown.bereich-dropdown{
      right:16px; left:auto; top:calc(100% + 4px); min-width:0; width:min(320px, calc(100vw - 32px));
    }
    body.app-an main h1{ font-size:1.8rem; }

    /* ---------- Die schwebende Leiste ----------
       Eine Glaspille mit Abstand zu den Rändern statt eines Balkens über
       die ganze Breite. Rechts bleibt Platz für den Schnellknopf. */
    body .topnav{
      left:12px; right:calc(12px + 66px + 10px); bottom:calc(10px + env(safe-area-inset-bottom));
      padding:5px; gap:0; border:1px solid var(--glas-rand); border-radius:36px;
      background:var(--glas); box-shadow:var(--glas-schatten);
      -webkit-backdrop-filter:saturate(180%) blur(24px); backdrop-filter:saturate(180%) blur(24px);
    }
    body .topnav button{ border-radius:30px; min-height:54px; padding:5px 0 4px; gap:2px; font-size:0.64rem; }
    body .topnav button svg{ width:22px; height:22px; }
    body .topnav button.active{ background:rgba(13,110,95,0.12); color:var(--green); }

    /* Meldungen oben als Pille, wie im Vorbild -- unten stünden sie
       zwischen Leiste und Schnellknopf. */
    body #toastHost{ top:calc(10px + env(safe-area-inset-top)); bottom:auto; left:12px; right:12px; align-items:center; }
    body .toast{ width:100%; border-radius:20px; padding:12px 16px; transform:translateY(-10px); box-shadow:0 12px 30px rgba(0,0,0,0.22); }
    body .toast.show{ transform:none; }

    /* ---------- Masken als schwebendes Blatt ----------
       Mit Abstand zu den Rändern und rundum gerundet, oben ein Griff,
       das Kreuz links, der Titel in der Mitte -- die Form des Vorbilds.
       Die Fußleiste trägt die Handlung als große Pille. */
    body .bearbeiten-dialog, body .bearbeiten-dialog.breit{
      width:calc(100% - 16px); max-width:none; border-radius:28px;
      margin:auto 8px calc(8px + env(safe-area-inset-bottom)) 8px;
      max-height:calc(100dvh - 24px - env(safe-area-inset-top) - env(safe-area-inset-bottom));
      box-shadow:0 24px 60px rgba(26,26,26,0.3);
      animation:blatt-hoch .3s cubic-bezier(.2,.8,.2,1);
    }
    body .bearbeiten-dialog::before{
      content:''; flex:none; display:block; width:38px; height:5px; border-radius:3px;
      background:rgba(26,26,26,0.16); margin:8px auto 0;
    }
    body .bd-kopf{
      display:grid; grid-template-columns:40px 1fr 40px; align-items:center; gap:8px;
      padding:6px 14px 8px; border-bottom:0;
    }
    body .bd-kopf > .hinweis-zu{
      grid-column:1; grid-row:1; width:36px; height:36px; border:0;
      background:rgba(26,26,26,0.07); color:var(--ink); font-size:1.4rem;
    }
    body .bd-kopf > h3{ grid-column:2; grid-row:1; text-align:center; font-size:1.02rem; line-height:1.25; }
    body .bd-inhalt{ padding:8px 16px 16px; }
    body .bd-fuss{ background:transparent; border-top:0; padding:8px 16px 16px; border-radius:0; }
    body .bd-fuss .btn{ min-height:50px; font-size:1rem; }

    /* Die Schnellzugriffe als gruppierte Liste -- Symbol, Titel, Winkel;
       die Trennlinie beginnt nach dem Symbol, wie in den Einstellungen. */
    body .tiles{ display:block; background:var(--karte); border-radius:var(--r-karte); box-shadow:var(--karte-schatten); overflow:hidden; }
    body.app-an .tile{
      display:flex; align-items:center; width:100%; gap:12px; margin:0;
      border:0; border-radius:0; box-shadow:none; background:none; padding:0 0 0 14px;
    }
    body.app-an .tile:hover{ transform:none; box-shadow:none; }
    body .tile .ti-icon{ width:32px; height:32px; padding:6px; border-radius:9px; background:var(--green-soft); }
    body .tile .ti-body{ flex:1; min-width:0; position:relative; padding:11px 36px 11px 0; border-top:1px solid var(--line); }
    body .tile:first-child .ti-body{ border-top:0; }
    body .tile .ti-body::after{
      content:''; position:absolute; right:18px; top:50%; width:8px; height:8px;
      border:solid var(--muted); border-width:2px 2px 0 0; transform:translateY(-50%) rotate(45deg); opacity:0.45;
    }
    body .tile strong{ font-size:0.98rem; margin:0; }
    /* Zwei Zeilen statt einer abgeschnittenen (10.10.2026): „Zetaro-Adresse,
       Empfangsprotokoll und…" sagte nicht, was hinter der Zeile liegt. */
    body .tile em{
      font-size:0.8rem; line-height:1.35; overflow:hidden;
      display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical;
    }
  }
  /* Sehr schmale Handys (320 px, ROADMAP 20.11, gemessen am 20.10.2026):
     Marke, Lupe, Bereich und Konto brauchten 388 px -- das Kontobild lag
     39 px jenseits des Rands, abgeschnitten. Unter 375 px weicht der
     Schriftzug, das Zeichen bleibt (der Knopf trägt sein aria-label). */
  @media (max-width:374px){
    body.app-an #brandHome .wordmark{ display:none; }
    body .bereich-menu{ margin-right:2px; }
  }
  @media (max-width:720px){
    /* Die Lupe als runder Knopf neben dem Kontobild. Bis 720 px, wie die
       Regel, die das Feld dort zuklappt. */
    body .kopf-suche-lupe{
      width:40px; height:40px; border-radius:50%; background:var(--glas-knopf);
      box-shadow:0 1px 4px rgba(26,26,26,0.1); color:var(--ink);
    }
    body .kopf-suche.offen .kopf-suche-lupe{ width:26px; height:26px; background:none; box-shadow:none; }
  }
  @keyframes blatt-hoch{ from{ transform:translateY(105%); } to{ transform:none; } }
  @media (prefers-reduced-motion: reduce){ body .bearbeiten-dialog{ animation:none; } }

  /* ---------- Glas-Stil, zweite Runde (28.09.2026): Akte und Objektliste ----------
     Nach dem ersten Blick auf dem Handy: die Akte sah noch aus wie vorher
     (Textlink zurück, kleines Symbolfeld, kastenförmige Reiter). Jetzt wie
     im Vorbild: eine Zurück-Pille, ein großes Titelbild, Reiter mit
     Unterstrich -- und die Objektliste als Bildkarten wie auf der
     Startseite. Der Aktenreiter bleibt am Schreibtisch; auf dem Handy
     trägt das große Bild die Wiedererkennung. */
  body.app-an .backlink{
    display:inline-flex; align-items:center; gap:6px; min-height:40px; padding:0 16px;
    border-radius:999px; background:var(--karte); color:var(--ink); font-weight:600;
    box-shadow:0 1px 3px rgba(26,26,26,0.08), 0 4px 12px rgba(26,26,26,0.05);
  }
  body.app-an .search-input{ border-radius:12px; }
  /* Das Kontomenü deckend: die Kopfzeile ist Glas und damit Grenze für
     jeden Weichzeichner darin -- ein halbdurchsichtiges Menü zeigte die
     Seite darunter unscharf-scharf durch. */
  body.app-an .account-dropdown{ background:var(--karte); }

  @media (max-width:767px){
    /* Die Karten der Startseite laufen bis an den Bildschirmrand, wie im
       Vorbild -- im Rand des Hauptbereichs abgeschnitten sah die zweite
       Karte aus wie ein Fehler. Unten Platz für den Schatten: der
       Rollbereich schneidet ihn sonst an seiner Kante ab. */
    body .sk-bahn{ margin:0 -22px -10px; padding:6px 22px 30px; scroll-padding-left:22px; }
    body .sk-karte{ box-shadow:0 10px 22px rgba(26,26,26,0.14); }
    body.app-an .avv-bar{ margin:12px 16px 0; }

    /* Die Akte: das Symbolfeld wird zum großen Titelbild. */
    body.app-an .prop-head{ display:block; }
    body.app-an .prop-photo{
      position:relative; width:100%; height:auto; aspect-ratio:16 / 9; margin:0 0 16px;
      border-radius:24px; color:#fff; box-shadow:0 12px 26px rgba(26,26,26,0.14);
      background:linear-gradient(160deg, #1b8070 0%, #0d6e5f 52%, #0a574b 100%);
    }
    body.app-an .prop-photo > span{ position:absolute; right:-4%; top:6%; width:46%; opacity:0.18; }
    body.app-an .prop-photo > span svg{ display:block; width:100%; height:auto; opacity:1; }
    body.app-an .prop-photo img{ position:absolute; inset:0; }

    /* Reiter mit Unterstrich statt Kästen -- die Form der Segmente im Vorbild. */
    body.app-an .ptabs{
      gap:20px; padding:0; border:0; border-radius:0; background:transparent;
      box-shadow:inset 0 -1px 0 rgba(26,26,26,0.1);
    }
    body.app-an .ptabs button{
      padding:10px 0 11px; border-radius:0; background:none; color:var(--muted);
      border-bottom:2px solid transparent;
    }
    body.app-an .ptabs button.active{ background:none; color:var(--ink); border-bottom-color:var(--ink); }
    body.app-an .ptabs button.pt-symbol{ border-left:0; border-radius:0; padding:10px 2px 11px; }
    body.app-an .ptabs button.pt-symbol.active{ background:none; color:var(--ink); }
    body.app-an .ptabs button.pt-symbol.active .pt-zahl{ background:var(--muted); color:var(--auf-tinte); }
    body.app-an .ptabs button:not(.pt-symbol).active .pt-zahl{ background:var(--line); color:var(--ink); }
    body.app-an .ptabs button:not(.pt-symbol).active .pt-zahl.warn{ background:#f6d9d5; color:#8a2f22; }
    body.app-an .ptabs-wrap::after{ background:linear-gradient(to right, var(--grund-klar), var(--grund) 72%); border-radius:0; }

    /* Die Objektliste als Bildkarten wie auf der Startseite. */
    /* border:0 -- der durchsichtige Rand vom Schreibtisch zeigte sonst eine
       feine Linie: der Verlauf wiederholt sich unter dem Rand. */
    body.app-an .folder{
      position:relative; overflow:hidden; padding:0; border:0; border-radius:24px; color:#fff;
      background:linear-gradient(160deg, #1b8070 0%, #0d6e5f 52%, #0a574b 100%);
      box-shadow:0 10px 24px rgba(26,26,26,0.14);
    }
    body.app-an .folder::before{ display:none; }
    body.app-an .folder::after{
      content:''; position:absolute; left:0; right:0; bottom:0; height:62%; pointer-events:none;
      background:linear-gradient(to top, rgba(0,0,0,0.58), rgba(0,0,0,0));
    }
    body.app-an .folder-photo{ position:relative; aspect-ratio:16 / 9; border-radius:0; background:transparent; color:#fff; }
    body.app-an .folder-photo > span{ position:absolute; right:-4%; top:6%; width:44%; opacity:0.18; }
    body.app-an .folder-photo > span svg{ display:block; width:100%; height:auto; opacity:1; }
    body.app-an .folder-body{ position:absolute; left:0; right:0; bottom:0; z-index:1; padding:16px 18px; }
    body.app-an .folder h3{ color:#fff; font-size:1.2rem; line-height:1.2; }
    body.app-an .folder .addr{ color:rgba(255,255,255,0.9); min-height:0; margin:2px 0 4px; }
    body.app-an .folder .meta{ color:rgba(255,255,255,0.72); }
    body.app-an .folder.new{
      background:transparent; color:var(--green); box-shadow:none;
      border:2px dashed #d3cdbf; padding:32px 18px; min-height:0;
    }
    body.app-an .folder.new::after{ display:none; }
  }

  /* ---------- Glas-Stil, dritte Runde (28.09.2026): das Profil als Liste ----------
     Auf dem Handy ist das Profil eine gruppierte Liste wie im Vorbild:
     oben die Karte mit dem Kontobild, darunter die Bereiche als Zeilen,
     und jeder Bereich öffnet sich als eigene Seite mit „Zurück". Die
     Kästen selbst bleiben dieselben -- samt Verdrahtung, Zwei-Faktor und
     dem dreifach gesicherten Löschen. Umgeschaltet wird nur, WELCHER zu
     sehen ist (data-seite am Rahmen, profilSeiteZeigen()). Am Schreibtisch
     bleibt die Seite, wie sie war: Liste und Unterkopf gibt es dort nicht. */
  /* minmax(0,1fr) und min-width:0: sonst dehnt das längste Wort
     („Auftragsverarbeitungsvertrag") die Spalte über den Bildschirm, und
     der rechte Rand samt Pfeilen wird abgeschnitten -- gemessen 369 px
     Zeile in 331 px Platz. */
  .profil-menue{ display:grid; grid-template-columns:minmax(0, 1fr); gap:22px; margin-top:8px; }
  /* Die Rechtstext-Verweise im Kasten „Daten & Recht" -- vorher ein
     Inline-Stil, der jede Regel fürs Handy geschlagen hätte. */
  .recht-links{ display:flex; gap:14px; flex-wrap:wrap; font-size:0.92rem; }
  .profil-menue > *{ min-width:0; }
  .pm-karte{
    display:flex; align-items:center; gap:14px; width:100%; padding:14px 16px;
    border:0; border-radius:20px; background:var(--karte); box-shadow:var(--karte-schatten);
    font:inherit; color:var(--ink); text-align:left; cursor:pointer;
  }
  .pm-avatar{
    flex:none; display:inline-flex; align-items:center; justify-content:center;
    width:52px; height:52px; border-radius:50%; background:var(--gruen-fill); color:#fff;
    font-weight:700; font-size:1.1rem; letter-spacing:0.02em;
  }
  .pm-person{ flex:1; min-width:0; display:grid; gap:2px; }
  .pm-person strong{ font-size:1.05rem; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .pm-person em{ font-style:normal; font-size:0.86rem; color:var(--muted); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .pm-gruppe h2{ margin:0 0 8px 16px; font-size:0.84rem; font-weight:600; color:var(--muted); letter-spacing:0; }
  .pm-liste{ background:var(--karte); border-radius:20px; box-shadow:var(--karte-schatten); overflow:hidden; }
  .pm-zeile{
    position:relative; display:flex; align-items:center; gap:14px; width:100%; min-height:52px;
    padding:8px 16px; border:0; background:none; font:inherit; font-size:1rem; color:var(--ink);
    text-align:left; text-decoration:none; cursor:pointer;
  }
  /* Die Trennlinie beginnt erst beim Text, wie in iOS -- unter dem Symbol
     wäre sie eine Kante zu viel. */
  .pm-zeile + .pm-zeile::before{
    content:''; position:absolute; top:0; left:52px; right:0; height:1px; background:rgba(26,26,26,0.08);
  }
  .pm-zeile:active{ background:rgba(26,26,26,0.05); }
  .pm-zeile:focus-visible, .pm-karte:focus-visible{ outline:2px solid var(--green); outline-offset:-2px; }
  .pm-symbol{ flex:none; display:inline-flex; width:22px; height:22px; color:var(--ink); }
  .pm-symbol svg{ width:22px; height:22px; }
  /* Ein langes Wort bricht mit Trennstrich um (lang="de"), statt in den
     Wert rechts hineinzulaufen. */
  .pm-text{ flex:1; min-width:0; line-height:1.3; overflow-wrap:anywhere; -webkit-hyphens:auto; hyphens:auto; }
  .pm-wert{ flex:none; white-space:nowrap; font-size:0.92rem; color:var(--muted); }
  .pm-wert.offen, .pm-unter.offen{ color:var(--red); }
  .pm-wert.neu, .pm-unter.neu{ color:var(--st-beige-text); }
  .pm-unter{ display:block; margin-top:2px; font-size:0.84rem; color:var(--muted); }
  .pm-pfeil{ flex:none; display:inline-flex; width:14px; height:14px; color:#b7b2a8; }
  .pm-pfeil svg{ width:14px; height:14px; }
  .pm-zeile.gefahr, .pm-zeile.gefahr .pm-symbol{ color:var(--red); }
  .pm-fuss{
    display:block; min-height:44px; margin:-6px auto 0; padding:8px 14px; border:0; background:none;
    font:inherit; font-size:0.8rem; color:var(--muted); cursor:pointer;
  }
  .profil-unterkopf{ position:relative; display:flex; align-items:center; gap:14px; min-height:44px; margin:2px 0 14px; }
  .profil-zurueck{
    position:relative; z-index:1; display:inline-flex; align-items:center; gap:4px; min-height:40px;
    padding:0 16px 0 10px; border:0; border-radius:999px; background:var(--karte); color:var(--ink);
    font:inherit; font-weight:600; cursor:pointer;
    box-shadow:0 1px 3px rgba(26,26,26,0.08), 0 4px 12px rgba(26,26,26,0.05);
  }
  .profil-zurueck svg{ width:18px; height:18px; }
  /* body.app-an davor: die große Überschrift des Glas-Stils (1,6rem)
     gälte sonst auch für den kleinen Seitentitel. Neben der Pille statt
     in der Mitte: mittig blieben bei 375 px neben „Zurück" nur 123 px,
     und „Meine Angaben" wurde abgeschnitten. */
  body.app-an .profil-unterkopf h1{
    flex:1; min-width:0; margin:0; text-align:left;
    font-size:1.05rem; font-weight:700; letter-spacing:0; line-height:1.3;
    white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
  }
  body.app-an .profil-unterkopf h1:focus{ outline:none; }
  @media (min-width:768px){ .profil-menue, .profil-unterkopf{ display:none; } }

  @media (max-width:767px){
    /* Die Liste: kein Kasten, kein Unterkopf, keine lange Unterzeile. */
    body .profil-seiten[data-seite="menue"] .profile-grid,
    body .profil-seiten[data-seite="menue"] [data-profteil],
    body .profil-seiten[data-seite="menue"] .profil-unterkopf,
    body .profil-seiten[data-seite="menue"] .kopf .sub,
    body .profil-seiten[data-seite="menue"] .kopf h1 .chip{ display:none; }
    /* Eine Unterseite: nur ihr Kasten, ohne die eigene Kopfzeile -- den
       Titel trägt der Unterkopf. Die Spalten lösen sich auf, sonst
       bliebe der Abstand einer leeren Spalte stehen. */
    body .profil-seiten.unterseite .profil-menue,
    body .profil-seiten.unterseite > .kopf{ display:none; }
    body .profil-seiten.unterseite .profile-grid,
    body .profil-seiten.unterseite .profile-col{ display:contents; }
    body .profil-seiten.unterseite [data-profteil]{ margin-top:0; }
    body .profil-seiten.unterseite [data-profteil] > .panel-head,
    body .profil-seiten.unterseite [data-profteil] > div > .panel-head{ display:none; }
    body .profil-seiten[data-seite="angaben"] [data-profteil]:not([data-profteil="angaben"]),
    body .profil-seiten[data-seite="sicherheit"] [data-profteil]:not([data-profteil="sicherheit"]),
    body .profil-seiten[data-seite="post"] [data-profteil]:not([data-profteil="post"]),
    body .profil-seiten[data-seite="tarif"] [data-profteil]:not([data-profteil="tarif"]),
    body .profil-seiten[data-seite="verwaltung"] [data-profteil]:not([data-profteil="verwaltung"]),
    body .profil-seiten[data-seite="daten"] [data-profteil]:not([data-profteil="daten"]),
    body .profil-seiten[data-seite="darstellung"] [data-profteil]:not([data-profteil="darstellung"]){ display:none; }
    /* Tippziele: die Verweise in den Kästen waren 37 bzw. 23 px hoch
       (gemessen mit der Handy-Prüfung). Auf dem Daumen 44. */
    body.app-an .zugang-wege .linkbtn{ min-height:44px; }
    body .sk-kopf .linkbtn{ min-height:44px; }
    body .mfa-geraet-weg{ min-height:44px; }
    body .recht-links{ gap:0 18px; }
    body .recht-links a{ display:inline-flex; align-items:center; min-height:44px; }
  }

  /* ---------- Handy, Durchgang vom 10.10.2026 ----------
     Am Bildschirm bei 375 px durchgesehen. Vier Dinge standen im Weg:
     * die Dokumentenliste war eine Tabelle mit sechs Spalten in 285 px --
       „Ansehen" und „Papierkorb" lagen hinter dem seitlichen Rollen;
     * der Kasten „Dokument hochladen" nahm 350 px vor dem ersten Beleg;
     * im Mietkonto standen fünf Verweise untereinander, bevor die Antwort
       kam („… offen"), und der Betrag je Monat rutschte unter die Zeile;
     * die Beschreibungen der Schnellzugriffe waren abgeschnitten.
     Die Grundregeln stehen vor der Abfrage, jede Handy-Regel trägt `body`. */
  .panel-zeile{ display:flex; align-items:center; justify-content:space-between; gap:10px; flex-wrap:wrap; }
  /* Die Zahlen im Ergebnis der Abrechnung stehen rechts -- hier und nicht im Markup, damit
     die Karte am Handy die linke Spalte links ausrichten kann (ein Inline-Stil schlüge sie). */
  .nk-ergebnis td[data-z="tage"], .nk-ergebnis td[data-z="anteil"], .nk-ergebnis td[data-z="vz"], .nk-ergebnis td[data-z="saldo"]{ text-align:right; }

  @media (max-width:767px){
    body.app-an #upPanel{ display:none; }

    /* Tippziele der Verweise in Zeilen („anlegen", „Datei", „zur Übergabe",
       „erledigt"): gemessen 25 bis 33 px hoch. Mehr Innenabstand oben und
       unten, vom Außenabstand wieder abgezogen -- das Ziel wird rund 42 px
       hoch, die Zeile wächst dabei um höchstens vier. ROADMAP 20.9 nannte es
       eine Gestaltungsfrage, weil größere Ziele mehr Zeilenabstand bräuchten;
       so brauchen sie ihn nicht. Wo ein Verweis schon seine 44 px hat, bleibt
       der Außenabstand, wie er war. */
    body.app-an .linkbtn{ padding-top:11px; padding-bottom:11px; margin-top:-7px; margin-bottom:-7px; }
    body.app-an .zugang-wege .linkbtn, body.app-an .sk-kopf .linkbtn,
    body.app-an .mk-wege > .linkbtn{ margin-top:0; margin-bottom:0; }
    /* Mehrere Handlungen an einer Zeile („Ansehen · PDF · Datei · Senden"):
       jede mindestens 44 px breit -- „PDF" war 25 × 25 und stand 10 px neben
       „Datei". Der Rand rechts gleicht den Innenabstand der letzten aus. */
    body.app-an .nk-zeile .nk-tun{ gap:8px 2px; margin-right:-4px; }
    body.app-an .nk-tun .linkbtn{ gap:4px; min-width:44px; padding-left:4px; padding-right:4px; text-align:center; justify-content:center; }
    /* Wo Verweise in mehreren Reihen stehen, lägen ihre Ziele sonst 14 px
       übereinander: die Wege unter der Vertragskarte bekommen den Abstand,
       die Vorschläge im Fließtext einen kleineren Abzug. */
    body.app-an .vk-aktionen{ row-gap:14px; }
    body.app-an p:has(> [data-pflichtvorschlag]) .linkbtn{ margin-top:-3px; margin-bottom:-3px; }
    /* Aufklapper über die ganze Kartenbreite und „Maske leeren": 24 bis 25 px hoch. */
    body.app-an details.panel > summary, body.app-an .panel-klapp > summary{ padding-top:10px; padding-bottom:10px; margin-top:-10px; margin-bottom:-8px; }
    body.app-an .leeren-knopf{ padding-top:12px; padding-bottom:12px; margin-top:-12px; margin-bottom:-12px; }

    /* Ein Kartenkopf mit Überschrift (Rechnungen, Kunden): die Überschrift
       bekommt ihre eigene Zeile in der Größe der übrigen Kartenköpfe. Mit
       24 px brach „Ausgestellte Rechnungen" um, und bei „Kunden" stand das
       „i" allein unter dem Wort. */
    body.app-an .panel-head h2{ font-size:1.15rem; line-height:1.3; flex:1 1 100%; }

    /* Vorschau: der Dateiname bekommt seine eigene Zeile. Neben den beiden
       Knöpfen blieben ihm 32 px -- zu lesen war „E-…". */
    body .preview-head{ flex-wrap:wrap; row-gap:8px; }
    body .preview-head .preview-name{ flex:1 1 100%; }
    body .preview-head > span:last-child{ margin-left:auto; }

    /* Was ansteht: zwei Karten nebeneinander; eine einzelne letzte füllt die Zeile. */
    body .lage{ grid-template-columns:minmax(0, 1fr) minmax(0, 1fr); gap:10px; margin-top:14px; }
    body .lage-karte:last-child:nth-child(odd){ grid-column:1 / -1; min-height:0; }
    body .lage-wert{ font-size:1.14rem; }

    /* ----- Beleglisten als Karten -----
       Dokumente, Papierkorb, Posteingang. Die Zeile bleibt eine Zeile (tr):
       Suche, Filter und Blättern greifen weiter an ihr an. Nur die Anordnung
       ändert sich -- Name oben, darunter Art, Zuordnung, Datum und rechts die
       Größe, zuletzt die Handlungen in Daumengröße. Welche Zelle was ist,
       sagt data-z im Markup. Die Zellen bleiben Blöcke: flex oder grid an
       einer Zelle verbietet syntax-pruefen.mjs seit dem 13.09.2026 zu Recht. */
    body .panel table.beleg-karten{ display:block; min-width:0; width:100%; margin-top:4px; }
    body .beleg-karten thead{ display:none; }
    body .beleg-karten tbody{ display:block; }
    body .beleg-karten tr{
      display:grid; grid-template-columns:minmax(0, 1fr) auto; gap:9px 12px;
      padding:15px 0 9px; border-top:1px solid var(--line);
    }
    body .beleg-karten tbody tr:first-child{ border-top:0; }
    body .beleg-karten td{
      display:block; grid-column:1 / -1; min-width:0; max-width:none; padding:0; border:0;
      position:static; background:none; box-shadow:none; text-align:left;
    }
    body .beleg-karten td[data-z="name"]{ font-weight:600; line-height:1.35; overflow-wrap:anywhere; }
    body .beleg-karten td[data-z="name"] > div{ font-weight:400; }
    body .beleg-karten td.leer{ display:none; }
    body .beleg-karten td[data-z="vorgang"]::before, body .beleg-karten td[data-z="objekt"]::before{
      display:block; margin-bottom:3px; font-size:0.78rem; color:var(--muted);
    }
    body .beleg-karten td[data-z="vorgang"]::before{ content:'Vorgang'; }
    body .beleg-karten td[data-z="objekt"]::before{ content:'Ablegen in'; }
    body .beleg-karten td[data-z="datum"]{ grid-column:1; font-size:0.86rem; color:var(--muted); }
    body .beleg-karten td[data-vor]::before{ content:attr(data-vor) ' '; }
    body .beleg-karten td[data-z="groesse"]{ grid-column:2; font-size:0.86rem; color:var(--muted); text-align:right; }
    /* Die Papierkörbe der Vorgänge und des Mieterkanals nehmen dieselben Karten (06.11.2026):
       die Knöpfe lagen am Handy in der letzten Spalte außerhalb des Bildes. */
    body .beleg-karten td[data-z="nr"], body .beleg-karten td[data-z="eingang"]{ font-size:0.86rem; color:var(--muted); }
    body .beleg-karten .wahlfeld.zelle{ width:100%; max-width:none; padding:9px 10px; }
    body .beleg-karten .bk-zelle select{ flex:1 1 auto; }
    body .beleg-karten .bezahlt-feld{ margin-top:8px; }
    body .beleg-karten .bezahlt-feld .wahlfeld.zelle{ width:auto; min-width:170px; }
    body .beleg-karten td.actions > *{ margin:0 22px 0 0; min-height:44px; display:inline-flex; align-items:center; }
    body .beleg-karten td.actions > :last-child{ margin-right:0; }
    /* Verlauf eines Zählers (seit dem 20.10.2026): die Tabelle war am Handy
       514 px breit, „berichtigen" lag ganz außerhalb der Maske. Jetzt eine
       Zeile je Ablesung -- Tag und Stand oben, darunter Verbrauch, Anlass
       und die Handlung. Die Zellen bleiben Blöcke (syntax-pruefen.mjs). */
    body table.zb-verlauf{ display:block; width:100%; min-width:0; }
    body .zb-verlauf thead{ display:none; }
    body .zb-verlauf tbody{ display:block; }
    body .zb-verlauf tr{
      display:grid; grid-template-columns:minmax(0, 1fr) auto; gap:4px 12px;
      padding:12px 0; border-top:1px solid var(--line);
    }
    body .zb-verlauf tbody tr:first-child{ border-top:0; }
    body .zb-verlauf td{ display:block; min-width:0; padding:0; border:0; text-align:left; }
    body .zb-verlauf td[data-z="tag"], body .zb-verlauf td[data-z="stand"]{ font-weight:600; }
    body .zb-verlauf td[data-z="stand"]{ text-align:right; }
    body .zb-verlauf td[data-z="verbrauch"], body .zb-verlauf td[data-z="anlass"], body .zb-verlauf td.actions{ grid-column:1 / -1; }
    body .zb-verlauf td.zahl[data-z="verbrauch"]{ text-align:left; }
    body .zb-verlauf td[data-z="verbrauch"]::before{ content:'Verbrauch seit davor: '; color:var(--muted); }
    body .zb-verlauf td.actions > *{ min-height:44px; display:inline-flex; align-items:center; }
    /* Die Schreiben einer abgeschlossenen Abrechnung (seit dem 06.11.2026): die Tabelle war
       am Handy 628 px breit, „als zugestellt vermerken" -- die einzige Handlung des Schritts
       „Zustellen" -- und „Schreiben ansehen" lagen rechts außerhalb des Bildes. Jetzt eine
       Zeile je Mietpartei: Name und Saldo oben, darunter der Zugang, zuletzt die Handlungen.
       Angeheftete Spalten (Nadeln) gelten hier nicht. Die Zellen bleiben Blöcke. */
    body table.nk-schreiben{ display:block; width:100%; min-width:0; }
    body .nk-schreiben thead{ display:none; }
    body .nk-schreiben tbody{ display:block; }
    body .nk-schreiben tr{
      display:grid; grid-template-columns:minmax(0, 1fr) auto; gap:6px 12px;
      padding:12px 0; border-top:1px solid var(--line);
    }
    body .nk-schreiben tbody tr:first-child{ border-top:0; }
    body .nk-schreiben td{
      display:block; min-width:0; padding:0; border:0; text-align:left;
      position:static; left:auto; background:none; box-shadow:none;
    }
    body .nk-schreiben td[data-z="partei"]{ grid-column:1; grid-row:1; }
    body .nk-schreiben td[data-z="saldo"]{ grid-column:2; grid-row:1; text-align:right; }
    body .nk-schreiben td[data-z="zugang"], body .nk-schreiben td.actions{ grid-column:1 / -1; }
    body .nk-schreiben td[data-vor]::before{ content:attr(data-vor) ' '; color:var(--muted); }
    body .nk-schreiben td[data-z="zugang"] > button, body .nk-schreiben td.actions > *{ min-height:44px; display:inline-flex; align-items:center; }
    body .nk-schreiben td.actions > *{ margin:0 18px 0 0; }
    /* Dasselbe für die beiden Tabellen im Abrechnungsbildschirm (06.11.2026): Kosten-
       positionen 560 px in 261 px („Ändern", „Entfernen" außerhalb), Ergebnis 582 px in
       261 px (Feld für die Vorauszahlung und Saldo außerhalb -- gerade das, was im Schritt
       „Prüfen" zu prüfen ist). Je Position: Art und Betrag oben, darunter Verteilung,
       Beleg und die Knöpfe. Je Mietverhältnis: die Partei oben, darunter Tage, Anteil,
       Vorauszahlung und Saldo beschriftet, zwei mal zwei. Fuß wie eine Zeile. */
    body table.nk-posten, body table.nk-ergebnis{ display:block; width:100%; min-width:0; }
    body .nk-posten thead, body .nk-ergebnis thead{ display:none; }
    body .nk-posten tbody, body .nk-ergebnis tbody, body .nk-posten tfoot, body .nk-ergebnis tfoot{ display:block; }
    body .nk-posten tr, body .nk-ergebnis tr{
      display:grid; grid-template-columns:minmax(0, 1fr) minmax(0, 1fr); gap:6px 12px;
      padding:12px 0; border-top:1px solid var(--line);
    }
    body .nk-posten tbody tr:first-child, body .nk-ergebnis tbody tr:first-child{ border-top:0; }
    body .nk-posten tr{ grid-template-columns:minmax(0, 1fr) auto; }
    body .nk-posten td, body .nk-ergebnis td{
      display:block; min-width:0; padding:0; border:0; text-align:left;
      position:static; left:auto; background:none; box-shadow:none;
    }
    body .nk-posten td:empty, body .nk-ergebnis td:empty, body .nk-posten td.leer{ display:none; }
    body .nk-posten td[colspan], body .nk-ergebnis td[colspan]{ grid-column:auto; }
    body .nk-posten tbody td[colspan], body .nk-ergebnis tbody td[colspan]{ grid-column:1 / -1; }
    body .nk-posten td[data-z="betrag"], body .nk-posten tfoot td:nth-child(2){ text-align:right; }
    body .nk-posten td[data-z="verteilung"], body .nk-posten td[data-z="beleg"], body .nk-posten td.actions{ grid-column:1 / -1; }
    body .nk-posten td.actions > *{ min-height:44px; display:inline-flex; align-items:center; margin:0 18px 0 0; }
    body .nk-ergebnis td[data-z="partei"]{ grid-column:1 / -1; grid-row:1; }
    body .nk-ergebnis tfoot td:first-child{ grid-column:1; }
    body .nk-ergebnis tfoot td:nth-child(2){ grid-column:2; text-align:right; }
    body .nk-ergebnis td[data-vor]::before{ content:attr(data-vor); display:block; margin-bottom:2px; font-size:0.78rem; font-weight:400; color:var(--muted); }
    body .nk-ergebnis td[data-z="vz"] input{ width:100%; max-width:140px; min-height:40px; }
    body .nk-ergebnis td[data-z="tage"], body .nk-ergebnis td[data-z="vz"]{ text-align:left; }
    /* Zugeklappt: Name, Art, Datum und die Wege zum Ansehen. Kostenart,
       Vorgang, Zahlungsdatum und der Papierkorb liegen hinter „Angaben"
       (belegKartenVerdrahten). Der Bescheid behält seine Frist immer. */
    body .beleg-karten.klappbar tr:not(.auf) td[data-z="vorgang"],
    body .beleg-karten.klappbar tr:not(.auf) .bk-zelle,
    body .beleg-karten.klappbar tr:not(.auf) .bk-vorschlag,
    body .beleg-karten.klappbar tr:not(.auf) .bescheid-datum.gesetzt,
    body .beleg-karten.klappbar tr:not(.auf) .bezahlt-feld,
    body .beleg-karten.klappbar tr:not(.auf) td.actions > .del{ display:none; }
    body .beleg-karten.klappbar tr.auf{ background:var(--st-grau-flaeche); margin:0 -10px; padding-left:10px; padding-right:10px; border-radius:12px; border-top-color:transparent; }
    body .beleg-karten.klappbar tr.auf + tr{ border-top-color:transparent; }

    /* ----- Mietkonto -----
       Erst die Antwort, dann die Wege: am Schreibtisch stehen die Wege neben
       der Überschrift und die Antwort darunter; am Handy rutschten sie
       darunter und schoben die Antwort 220 px tiefer. Der Kopf des Bandes
       löst sich deshalb auf (display:contents) und die Reihenfolge setzt
       `order`. Die Wege als Tippflächen in zwei Spalten. */
    body .mk-block{ display:flex; flex-direction:column; }
    body .mk-block > *{ order:4; }
    body .mk-block > .vk-bandkopf{ display:contents; }
    body .mk-block > .vk-bandkopf > .vk-label{ order:0; margin-bottom:2px; }
    body .mk-block > .mk-gross{ order:1; margin-top:4px; font-size:1.3rem; }
    body .mk-block > .mk-lage{ order:2; margin-bottom:12px; }
    body .mk-block > .vk-bandkopf > .mk-wege{
      order:3; display:grid; grid-template-columns:minmax(0, 1fr) minmax(0, 1fr); gap:8px; margin:0 0 16px;
    }
    body .mk-wege > .linkbtn{
      display:flex; align-items:center; justify-content:center; min-height:44px; padding:6px 8px;
      border:1px solid var(--line); border-radius:12px; background:var(--karte);
      font-size:0.88rem; line-height:1.25; text-align:center;
    }
    body .mk-wege > .info-anker{ align-self:center; justify-self:start; margin-left:6px; }
    /* Das Mietkonto: zwei Knöpfe, darunter drei ruhige Wege, das Symbol über dem Wort.
       So passen sie in eine Zeile, und das Verb bleibt für Vorlesehilfen stehen. */
    body .mk-block > .vk-bandkopf > .mk-aktionen{ display:flex; flex-wrap:wrap; gap:6px 8px; }
    body .mk-aktionen > .btn{ flex:1 1 auto; padding:8px; font-size:0.9rem; }
    body .mk-nebenwege{ display:flex; flex:1 0 100%; align-items:center; gap:2px; }
    body.app-an .mk-nebenwege > .linkbtn{
      flex:1 1 0; flex-direction:column; justify-content:center; gap:3px; min-width:0; min-height:50px;
      margin:0; padding:4px 2px; font-size:0.8rem; line-height:1.2; text-align:center;
    }
    /* 360 px ist die häufigste Android-Breite: dort bleibt alles in zwei Zeilen. */
    @media (max-width:374px){
      body .mk-aktionen > .btn{ padding:8px 6px; font-size:0.84rem; }
      body .mk-nebenwege{ gap:0; }
      body.app-an .nk-zeile .nk-tun{ gap:8px 0; }
      body.app-an .mk-nebenwege > .linkbtn{ padding:4px 1px; font-size:0.78rem; }
    }
    @media (max-width:359px){
      body .mk-nebenwege{ flex-wrap:wrap; }
      body.app-an .mk-nebenwege > .linkbtn{ flex:1 1 40%; }
      /* Bei 320 px blieben dem Namen neben dem Saldo 116 px: der Saldo rückt darunter. */
      body .nk-schreiben td[data-z="partei"], body .nk-schreiben td[data-z="saldo"]{ grid-column:1 / -1; grid-row:auto; text-align:left; }
      body .nk-posten td[data-z="art"], body .nk-posten td[data-z="betrag"]{ grid-column:1 / -1; text-align:left; }
    }
    /* Die Monate immer zwei mal sechs: bei 360 px brachen sie sonst auf drei Zeilen um. */
    body .mk-kacheln{ display:grid; grid-template-columns:repeat(6, minmax(0, 1fr)); }
    body .mk-kacheln .mk-kachel{ width:auto; }
    .nur-breit{ position:absolute; width:1px; height:1px; overflow:hidden; clip-path:inset(50%); white-space:nowrap; }

    body .mk-zeile-tun .linkbtn{ min-height:36px; display:inline-flex; align-items:center; }

    /* ----- Objektbilder: gewählt am 14.10.2026 -----
       Aus drei Vorschlägen vom 13.10.2026 hat der Inhaber gewählt:
       Startseite „mittel" -- kleine Karten, das Bild oben, der Text darunter
       auf Weiß; Objektliste und Akte „klein" -- eine Liste mit Vorschaubild
       wie das Profil, in der Akte das Bild neben dem Namen. Die großen
       Bildkarten darüber (28.09.2026) bleiben die Grundform; diese Regeln
       stehen danach und haben dieselbe Stärke wie zur Zeit des Schalters
       (darum .folders und .prop-head im Selektor). Am Schreibtisch gilt
       nichts davon. */

    /* Startseite */
    body.app-an .sk-bahn{ gap:10px; padding-bottom:22px; }
    body.app-an .sk-karte{
      flex:0 0 152px; aspect-ratio:auto; max-height:none; border-radius:18px; background:var(--karte); color:var(--ink);
      display:grid; grid-template-columns:minmax(0, 1fr); grid-template-rows:94px auto; box-shadow:var(--karte-schatten);
    }
    body.app-an .sk-karte::before{
      content:''; grid-row:1; grid-column:1; background:linear-gradient(160deg, #1b8070 0%, #0d6e5f 52%, #0a574b 100%);
    }
    body.app-an .sk-karte img{ position:static; grid-row:1; grid-column:1; width:100%; height:94px; z-index:1; }
    body.app-an .sk-karte::after{ display:none; }
    body.app-an .sk-symbol{
      position:static; grid-row:1; grid-column:1; justify-self:end; align-self:start;
      width:58px; margin:10px 8px 0 0; opacity:0.22;
    }
    body.app-an .sk-text{ position:static; grid-row:2; padding:9px 12px 12px; gap:1px; }
    body.app-an .sk-art{ font-size:0.62rem; color:var(--muted); opacity:1; }
    body.app-an .sk-text strong{
      font-size:0.95rem; line-height:1.25; display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; overflow:hidden;
    }
    body.app-an .sk-text em{ font-size:0.78rem; color:var(--muted); opacity:1; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
    body.app-an .sk-punkte{ display:none; }

    /* Objektliste */
    body.app-an .folders{ gap:10px; }
    body.app-an .folders .folder{
      display:grid; grid-template-columns:56px minmax(0, 1fr); align-items:center; gap:12px; padding:10px 14px;
      background:var(--karte); color:var(--ink); border-radius:18px; box-shadow:var(--karte-schatten); text-align:left;
    }
    body.app-an .folders .folder::after{ display:none; }
    body.app-an .folders .folder-photo{
      width:56px; height:56px; aspect-ratio:auto; border-radius:14px; overflow:hidden;
      display:flex; align-items:center; justify-content:center;
      background:linear-gradient(160deg, #1b8070 0%, #0d6e5f 52%, #0a574b 100%);
    }
    body.app-an .folders .folder-photo img{ width:100%; height:100%; object-fit:cover; display:block; }
    body.app-an .folders .folder-photo > span{ position:static; width:30px; opacity:1; }
    body.app-an .folders .folder-body{ position:static; padding:0; min-width:0; }
    body.app-an .folders .folder h3{ color:var(--ink); font-size:1rem; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
    body.app-an .folders .folder .addr{
      color:var(--muted); font-size:0.82rem; margin:1px 0 0; white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
    }
    body.app-an .folders .folder .meta{ display:none; }
    body.app-an .folders .folder.new{ display:block; text-align:center; padding:18px; }

    /* Akte */
    body.app-an .prop-head{ display:flex; flex-wrap:nowrap; gap:14px; align-items:center; }
    body.app-an .prop-head .prop-photo{
      flex:none; width:68px; height:68px; aspect-ratio:auto; margin:0; border-radius:18px;
      box-shadow:0 6px 14px rgba(26,26,26,0.12);
    }
    body.app-an .prop-head .prop-photo > span{ position:static; display:block; width:34px; margin:17px; opacity:1; }
    body.app-an .prop-head h1{ font-size:1.35rem; }
  }

  /* =====================================================================
     DUNKLE DARSTELLUNG „Tinte" (03.11.2026, vom Inhaber gewaehlt aus zwei
     Fassungen): warm, die Creme umgekehrt. Gesetzt ueber data-dunkel am
     Wurzelelement -- das Skript im Kopf und darstellungAnwenden() entscheiden
     nach der Wahl im Profil (Hell, Dunkel, Wie Geraet). Nur fuer den
     Bildschirm: gedruckt wird hell, und ein Schriftstueck bleibt Papier.
     Gemessen (WCAG 1.4.3): Text auf Karte 14:1, Nebentext 6,8:1, Gruen als
     Schrift 7,9:1, Weiss auf --gruen-fill 4,84:1. tools/dunkel-pruefen.mjs
     rechnet jedes Paar nach.
     WER EINE FARBE BRAUCHT, nimmt eine Variable. Eine feste Farbe im Stil
     bleibt im Dunkeln hell; dunkel-pruefen.mjs weist sie ab.
     ===================================================================== */
  @media screen{
    :root[data-dunkel]{
      color-scheme:dark;
      --paper:#181715; --ink:#eeece6; --muted:#a8a59c; --line:#34312c;
      --green:#5cc4ad; --green-soft:#183330; --red:#ff8a73; --tab:#26241f;
      --karte:#1f1e1b; --karte-klar:rgba(31,30,27,0); --gruen-fill:#13806d; --rot-flaeche:#3a1d17; --rot-rand:#6e3326;
      --auf-tinte:#131211; --rot-fill:#b3402a;
      --st-grau-flaeche:#26241f;  --st-grau-rand:#45413a;  --st-grau-text:#a8a59c;  --st-grau-punkt:#7d796f;
      --st-beige-flaeche:#3a2f17; --st-beige-rand:#6b5524; --st-beige-text:#e3bf6a; --st-beige-punkt:#d99a22;
      --st-gruen-flaeche:#183330; --st-gruen-rand:#2b5a52; --st-gruen-text:#5cc4ad; --st-gruen-punkt:#3fae98;
      --grund:#131211; --glas:rgba(31,30,27,0.78); --glas-rand:rgba(255,255,255,0.08);
      --glas-dicht:rgba(31,30,27,0.96); --glas-knopf:rgba(31,30,27,0.92);
      --grund-glas:rgba(19,18,17,0.82); --grund-klar:rgba(19,18,17,0);
      --glas-schatten:0 12px 32px rgba(0,0,0,0.5), 0 2px 6px rgba(0,0,0,0.3);
      --karte-schatten:0 1px 2px rgba(0,0,0,0.35), 0 8px 24px rgba(0,0,0,0.22);
    }
    /* Was fest im Code stand und im Dunkeln eine eigene Farbe braucht. */
    :root[data-dunkel] .nk-meldung{ background:var(--rot-flaeche); border-color:var(--rot-rand); color:var(--red); }
    :root[data-dunkel] .nk-blocker-kopf{ color:var(--red); }
    :root[data-dunkel] .hw-state{ background:var(--st-grau-flaeche); }
    :root[data-dunkel] .ptabs button:not(.pt-symbol) .pt-zahl.warn,
    :root[data-dunkel] body.app-an .ptabs button:not(.pt-symbol).active .pt-zahl.warn{ background:var(--rot-flaeche); color:var(--red); }
    :root[data-dunkel] .ptabs button:not(.pt-symbol).active .pt-zahl.warn{ background:var(--karte); color:var(--red); }
    :root[data-dunkel] .sk-karte.neu, :root[data-dunkel] body.app-an .folder.new{ border-color:var(--st-grau-rand); }
    :root[data-dunkel] .sb-datei-feld{ border-color:var(--st-gruen-rand); }
    :root[data-dunkel] .sb-haken{ border-color:var(--st-grau-rand); }
    :root[data-dunkel] .filing .folder-back, :root[data-dunkel] .filing .folder-back::before{ background:var(--st-grau-rand); }
    :root[data-dunkel] .btn.dienst.gmail{ color:#ff8a80; }
    :root[data-dunkel] .btn.dienst.outlook{ color:#6cb4ff; }
    :root[data-dunkel] .btn.dienst.yahoo{ color:#b896ff; }
    :root[data-dunkel] .btn.dienst.kleinanzeigen{ color:#8fd16a; }
    :root[data-dunkel] .btn.dienst.is24{ color:#ff9a5c; }
    :root[data-dunkel] .btn.dienst.immowelt{ color:#78a9ff; }
    /* Ein Schriftstück bleibt Papier: es soll aussehen wie gedruckt. */
    :root[data-dunkel] .sheet{
      color-scheme:light;
      --paper:#fbfaf8; --ink:#1a1a1a; --muted:#6b6b66; --line:#e4e1da;
      --green:#0d6e5f; --green-soft:#e7f1ee; --red:#b3402a; --tab:#f1eee7;
      --karte:#fff; --karte-klar:rgba(255,255,255,0); --gruen-fill:#0d6e5f; --rot-flaeche:#fdecea; --rot-rand:#e8b3a7;
      --auf-tinte:#fff; --rot-fill:#b3402a;
      --st-grau-flaeche:#f1eee7;  --st-grau-rand:#d9d2c0;  --st-grau-text:#6b6b66;  --st-grau-punkt:#b4b0a6;
      --st-beige-flaeche:#faeeda; --st-beige-rand:#e8d3a8; --st-beige-text:#80651c; --st-beige-punkt:#c98a12;
      --st-gruen-flaeche:#e7f1ee; --st-gruen-rand:#bcd8d0; --st-gruen-text:#0d6e5f; --st-gruen-punkt:#0d6e5f;
      background:#fff; color:#1a1a1a;
    }
  }
