/* =====================================================================
   IR — Bausteine für alle Ebenen (CI-Ebene, 15.09.2026)

   Formen, die Frontend, Backend und Seiten ohne Menü gemeinsam brauchen
   und die nicht in verwaltung/assets/app.css (Backend-Hülle) gehören.
   Setzt tokens.css voraus (verwaltung/assets/app.css importiert beides;
   Frontend-Seiten verlinken /css/tokens.css und /css/bausteine.css).
   Nur var(--…) — Werte stehen in tokens.css. Neue Form? Hier bauen, nie in
   einer Seite (Hook Abschnitt 4, Selbsttest W1f).
   ===================================================================== */

/* ---- Dialog (Overlay) — Auftrag Thomas 15.09.2026: Tickerwerte klickbar,
   Verlauf als Diagramm im Overlay. Markup:
     <dialog class="blatt-dialog" aria-labelledby="d-titel">
       <div class="blatt-dialog-kopf"><h2 id="d-titel">3-Monats-Euribor</h2>
         <form method="dialog"><button class="schliessen" aria-label="Schließen">×</button></form></div>
       <div class="blatt-dialog-inhalt">… Diagramm-Baustein …</div>
     </dialog>
   Öffnen: dialog.showModal(); Escape und Klick auf den Grund schließen (JS:
   dialog.addEventListener('click', e => { if (e.target === dialog) dialog.close(); })).
   Breite min(800px, Viewport − 32px), Karte, Radius wie die Karten, Grund
   abgedunkelt aus --ink, Eintritt 200 ms — bei reduced-motion ohne Bewegung. ---- */
dialog.blatt-dialog{border:0;padding:0;margin:auto;background:var(--card);color:var(--ink);
  border-radius:18px;box-shadow:var(--shadow);width:min(800px,100% - 32px);max-height:calc(100dvh - 32px);
  overflow:auto;font-family:var(--sans)}
dialog.blatt-dialog::backdrop{background:rgb(0 0 0 / .55);backdrop-filter:blur(2px)}   /* immer abdunkeln — mit var(--ink) wurde der Grund im Dunkelmodus hell (gemessen 19.09.2026) */
dialog.blatt-dialog[open]{animation:blatt-dialog-ein .2s ease}
@keyframes blatt-dialog-ein{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}
@media(prefers-reduced-motion:reduce){dialog.blatt-dialog[open]{animation:none}}
.blatt-dialog-kopf{display:flex;align-items:flex-start;gap:1rem;padding:1.1rem 1.2rem .5rem}
.blatt-dialog-kopf h2{font-family:var(--display);font-size:1.15rem;font-weight:800;letter-spacing:-.01em;margin:0;line-height:1.25}
.blatt-dialog-kopf .eyebrow{font-size:.7rem;font-weight:700;letter-spacing:.09em;text-transform:uppercase;color:var(--ir-red);margin:0 0 .25rem}
.blatt-dialog-kopf form{margin-left:auto;flex:none}
.blatt-dialog .schliessen{width:2.1rem;height:2.1rem;border-radius:999px;border:1px solid var(--rule);background:var(--card);
  color:var(--ink-2);font:inherit;font-size:1.25rem;line-height:1;cursor:pointer;display:grid;place-content:center}
.blatt-dialog .schliessen:hover{border-color:var(--ir-red);color:var(--ir-red)}
.blatt-dialog-inhalt{padding:0 1.2rem 1.2rem}
@media(max-width:560px){dialog.blatt-dialog{border-radius:14px}.blatt-dialog-kopf{padding:.9rem 1rem .4rem}.blatt-dialog-inhalt{padding:0 1rem 1rem}}

/* ---- Posten-Knopf: ein Wert, der wie Text dasteht und sich klicken lässt (Tickerzeile → Verlauf
   im Dialog; Auftrag Thomas 15.09.2026). Markup: <button type="button" class="posten">…<span class="wert">2,04 %</span></button>
   Browser-Form weg, Schrift und Farbe vom Umfeld; Hover und Tastaturfokus in der Marke. ---- */
button.posten{background:none;border:0;padding:0;margin:0;font:inherit;color:inherit;cursor:pointer;text-align:inherit;
  border-radius:6px}
button.posten:hover .wert,button.posten:focus-visible .wert{color:var(--ir-red);text-decoration:underline;text-underline-offset:.15em}
button.posten:focus-visible{outline:2px solid var(--ir-red);outline-offset:3px}

/* ---- Claim-Zug: der Claim unter Signet/Wortmarke, EINE Form für Backend UND App (Thomas 09.09.: Signet · Wortmarke ·
   Claim in allen Kanälen ident; 18.09.: der Claim fehlte in der App-Ansicht am Handy). Rock Salt aus tokens.css,
   9,5 px, IR-Rot, ohne Umbruch. Markup: <span class="claim-zug">Wir bewegen Immobilien</span> direkt unter der Marke. ---- */
.claim-zug{display:block;font-family:var(--claim);font-size:9.5px;color:var(--ir-red);margin-top:3px;white-space:nowrap;line-height:1.3}

/* ---- Marke im Seitenkopf: Wortmarke als Link, Claim darunter — die ganze Form aus einer Quelle, damit eine Seite
   dafür nichts Eigenes braucht (Frontend 22.09.: der Link brauchte `text-decoration:none`, das ist eine Form und
   gehört hierher). Markup: <div class="ir-marke"><a href="/start/"><img src="/assets/ir-logo.png" alt="Immobilienring
   Österreich"></a><span class="claim-zug">Wir bewegen Immobilien</span></div> — Größen: Standard 30 px Logohöhe,
   class="klein" 24 px, class="gross" 42 px. Wer den Kopf über blatt_kopf()/seite_kopf() nimmt, braucht auch das nicht. ---- */
.ir-marke{display:inline-flex;flex-direction:column;align-items:flex-start;line-height:0;--logo-h:30px}
.ir-marke a{display:block;line-height:0;text-decoration:none;border:0}
.ir-marke img{display:block;height:var(--logo-h);width:auto}
.ir-marke.klein{--logo-h:24px}
.ir-marke.gross{--logo-h:42px}
/* Die Größe des Claims hängt an der Wortmarke, nicht an der Seite (Thomas 22.09.2026: „ist er auch überall in
   derselben Größe — Relation zum Logo?"). Gemessener Sollwert: der Claim ist genau so breit wie die Wortmarke.
   Bei der Wortmarke ir-logo.png (Seitenverhältnis 140:30) trifft das bei Schriftgröße = 0,317 × Logohöhe zu —
   9,5 px bei 30 px Logo, und es skaliert mit `.klein`/`.gross` von selbst mit. */
.ir-marke .claim-zug{margin-top:4px;font-size:calc(var(--logo-h) * .317)}

/* ---- IR-Meldung: Rückfrage, Hinweis, Eingabe (Dialog) und Kurzmeldung (Band) — Auftrag Thomas 19.09.2026:
   „aktuelle Statusmeldungen kommen aus dem Browser mit dessen Design … es sollen keine Meldungen mehr aus dem
   Browser kommen." Namensraum ir-meldung (App und Backend haben eigene .meldung/.meldung-zeile — Befund App 19.09.). Baut auf dialog.blatt-dialog auf; Markup und Aufruf erzeugt /ci/meldung.js (IR.frage,
   IR.hinweis, IR.eingabe, IR.meldung, data-frage im Markup) — hier nur die Form.
   Immer in der Mitte des Bildschirms (Thomas 19.09.: „nicht oben" wie die Browser-Meldung): Karte 440 px, Hauptknopf
   rechts (Markup: Hauptknopf zuerst, row-reverse). Handy ≤ 560 px: Karte mit 16 px Rand, Knöpfe untereinander,
   Hauptknopf oben, 48 px hoch (Daumen). Grund abgedunkelt wie blatt-dialog. ---- */
dialog.blatt-dialog.ir-meldung{width:min(440px,100% - 32px)}
.ir-meldung-kopf{display:flex;align-items:center;gap:.75rem;padding:1.25rem 1.3rem 0}
.ir-meldung-kopf .signet{height:30px;width:auto;flex:none}
.ir-meldung-kopf h2{font-family:var(--display);font-size:1.1rem;font-weight:800;letter-spacing:-.01em;margin:0;line-height:1.25}
.ir-meldung-text{margin:.7rem 0 0;padding:0 1.3rem;color:var(--ink-2);font-size:.95rem;line-height:1.5;white-space:pre-line;overflow-wrap:anywhere}
.ir-meldung-feldzeile{padding:.9rem 1.3rem 0}
.ir-meldung-feld{width:100%;box-sizing:border-box;font:inherit;font-size:1rem;color:var(--ink);background:var(--bg);
  border:1px solid var(--rule);border-radius:12px;padding:.65rem .8rem;min-height:44px}
textarea.ir-meldung-feld{min-height:5.5rem;resize:vertical}
.ir-meldung-feld:focus,.ir-meldung-feld:focus-visible{outline:2px solid var(--ir-red);outline-offset:1px;border-color:var(--ir-red);border-radius:12px}   /* Radius gegen die globale :focus-visible-Regel der Hüllen */
.ir-meldung-fuss{display:flex;flex-direction:row-reverse;justify-content:flex-start;gap:.6rem;flex-wrap:wrap;padding:1.2rem 1.3rem 1.3rem}
.ir-meldung-fuss .knopf{font:inherit;font-size:.9rem;font-weight:600;min-height:44px;padding:.55rem 1.2rem;border-radius:999px;cursor:pointer;
  border:1px solid var(--rule);background:var(--card);color:var(--ink);box-shadow:var(--shadow-sm)}
.ir-meldung-fuss .knopf:hover{border-color:var(--ink-3)}
.ir-meldung-fuss .knopf:focus-visible{outline:2px solid var(--ir-red);outline-offset:2px;border-radius:999px}
.ir-meldung-fuss .knopf.haupt{background:var(--ir-red);border-color:var(--ir-red);color:#fff}
.ir-meldung-fuss .knopf.haupt:hover{background:var(--ir-red-deep);border-color:var(--ir-red-deep)}
dialog.ir-meldung[data-art="fehler"] .ir-meldung-kopf h2{color:var(--ir-red)}
dialog.ir-meldung[data-art="ok"] .ir-meldung-kopf h2{color:var(--st-done)}
/* Danke (Thomas 21.09.2026, Befragung: „ein Danke-Popup … von IR CI designen"): Signet groß und mittig auf rosa Grund,
   Titel Montserrat mittig, Text mittig, ein Knopf über die volle Breite — die eine Form für jeden Dank nach einer Abgabe. */
dialog.ir-meldung[data-art="danke"] .ir-meldung-kopf{flex-direction:column;align-items:center;text-align:center;gap:.9rem;padding:1.9rem 1.3rem 0}
dialog.ir-meldung[data-art="danke"] .ir-meldung-kopf .signet{width:72px;height:72px;padding:15px;box-sizing:border-box;object-fit:contain;border-radius:50%;background:var(--ir-red-wash)}
dialog.ir-meldung[data-art="danke"] .ir-meldung-kopf h2{font-size:1.35rem;letter-spacing:-.02em}
dialog.ir-meldung[data-art="danke"] .ir-meldung-text{text-align:center;font-size:1rem;margin-top:.6rem}
dialog.ir-meldung[data-art="danke"] .ir-meldung-fuss{flex-direction:column}
dialog.ir-meldung[data-art="danke"] .ir-meldung-fuss .knopf{width:100%;min-height:48px;font-size:1rem}
@keyframes ir-meldung-hoch{from{opacity:0;transform:translateY(24px)}to{opacity:1;transform:none}}
@media(max-width:560px){
  dialog.blatt-dialog.ir-meldung{width:calc(100% - 32px);max-height:85dvh}   /* mittig auch am Handy (Thomas 19.09.: „in der Mitte des Bildschirms, nicht oben") */
  .ir-meldung-kopf{padding:1.1rem 1.1rem 0}.ir-meldung-text{padding:0 1.1rem}.ir-meldung-feldzeile{padding:.8rem 1.1rem 0}
  .ir-meldung-fuss{flex-direction:column;padding:1.1rem}
  .ir-meldung-fuss .knopf{width:100%;min-height:48px;font-size:1rem}
}
@media(prefers-reduced-motion:reduce){dialog.blatt-dialog.ir-meldung[open]{animation:none}.ir-meldung-zeile{animation:none}}
/* Band: Kurzmeldungen oben mittig, unter dem Seitenkopf (--meldung-oben setzt jede Hülle; Vorgabe 16 px). Klick = weg. */
.ir-meldung-band{position:fixed;left:50%;top:calc(var(--meldung-oben,16px) + env(safe-area-inset-top));transform:translateX(-50%);
  z-index:1000;display:flex;flex-direction:column;gap:8px;align-items:stretch;width:min(440px,100% - 32px);pointer-events:none}
.ir-meldung-zeile{pointer-events:auto;display:flex;flex-direction:column;gap:.15rem;background:var(--card);color:var(--ink);
  border-radius:14px;box-shadow:var(--shadow);padding:.75rem .95rem .75rem .85rem;border-left:4px solid var(--ink-3);
  font-size:.9rem;line-height:1.4;cursor:pointer;animation:ir-meldung-hoch .2s ease;white-space:pre-line}
.ir-meldung-zeile b{font-family:var(--display);font-weight:700}
.ir-meldung-zeile[data-art="ok"]{border-left-color:var(--st-done)}
.ir-meldung-zeile[data-art="warnung"]{border-left-color:var(--st-work)}
.ir-meldung-zeile[data-art="fehler"]{border-left-color:var(--ir-red)}

/* ---- Textfeld: ein Eingabefeld mit Auszeichnung (div[contenteditable].textfeld) — Auftrag Thomas 19.09.2026 über
   Backend („im Textfeld den selben Editor wie im Protokoll"): der Protokoll-Editor (B/I/U, A−/A/A+) wandert in
   web/backend/assets/texteditor.js und wird in Protokoll und Befragungs-Strecke genutzt. Sieht aus wie .feld input
   (mitglieder.css: 9 px 11 px, Rand 1 px, Radius 9 px, 14 px), nur aus Tokens; Fokusring wie überall in der Marke.
   Innen: <b> <i> <u>, Größe aus dem Editor als <font size="2"|"5"> und aus Protokoll::auszeichnen() als <small>/<big>
   (0,85 em / 1,25 em). Höhe (min-height) gibt die Seite als Layout vor; Platzhalter über data-platzhalter. ---- */
.textfeld{display:block;width:100%;box-sizing:border-box;padding:9px 11px;border:1px solid var(--rule);border-radius:9px;
  background:var(--card);color:var(--ink);font:inherit;font-size:14px;line-height:1.5;white-space:pre-wrap;overflow-wrap:anywhere;
  cursor:text}
.textfeld:focus,.textfeld:focus-visible{outline:2px solid var(--ir-red);outline-offset:1px;border-color:var(--ir-red);border-radius:9px}
.textfeld:empty::before{content:attr(data-platzhalter);color:var(--ink-3);pointer-events:none}
.textfeld[contenteditable="false"]{background:var(--bg);color:var(--ink-2);cursor:default}
.textfeld b,.textfeld strong{font-weight:700}
.textfeld i,.textfeld em{font-style:italic}
.textfeld u{text-decoration:underline;text-underline-offset:.12em}
.textfeld small,.textfeld font[size="2"],.textfeld font[size="1"]{font-size:.85em}
.textfeld big,.textfeld font[size="5"],.textfeld font[size="6"]{font-size:1.25em}
.textfeld font{color:inherit;font-family:inherit}

/* ---- Karte: EINE Form für alle Karten (Kanzleien, Befragungen, Vorgänge, Partner, Aufgaben …) — Auftrag Thomas
   19.09.2026 über Backend: „über das gesamte Backend eine Logik, damit immer alle Karten gleich aussehen … bei den
   Mitgliedskanzleien haben wir das schon erfolgreich gelöst." FREIGEGEBEN Thomas 19.09. 13:5x: „wir verwenden diese
   Karten; falls es Änderungen dazu gibt oder Varianten, dann nur zentral" — Varianten entstehen NUR hier (CI-Ebene),
   nie in einer Seite oder Ebenen-CSS; Musterblatt: web/ci/karten.php (Test). Vorbild ist die Kanzlei-Karte (mitglieder.css, Thomas
   08.09.: Name allein in der Kopfzeile, Stand darunter als Marke, Daten als beschriftete Zeilen, Knöpfe im Raster).
   Zonen, in dieser Reihenfolge, jede weglassbar:
     <article class="karte">                                  (.klein = dichter; .rot / .warn = Rand in der Farbe; .aus = ausgeschieden)
       <div class="karte-bild [dunkel]"><img …></div>   (große Bildvorschau, z. B. Logo-Fassungen)
       <div class="karte-logo"><img …>|<span class="initialen">RW</span> <span class="stand gold">Premium Pool</span></div>
       <div class="karte-kopf"><h3>Titel</h3><p class="karte-unter">Nebenzeile</p></div>   (.mit-portraet: rundes Porträt links)
       <div class="karte-marken"><span class="stand gut">aktiv</span> <span class="stand rot">Vorstand · Obmann</span></div>
       <dl class="karte-daten [breit]"><dt>Sitz</dt><dd>…</dd> …</dl>   (.breit: 130 px Beschriftung)
       <p class="karte-text">Freitext</p>  (.klein, .warn, .mono)
       <p class="karte-hinweis">Hinterlegter Hinweis, z. B. „Es fehlt noch: …"</p>  (.warn, .gut)
       <div class="karte-knoepfe"><a class="btn btn-primary">Hauptweg</a><a class="btn">…</a></div>
     </article>
   Stand-Marken: gut (grün) · arbeit (orange) · aus (grau) · rot (Marke) · gold (Premium) · info (blau); die alten Namen
   aktiv/ruhend/ausgeschieden/premium/vorstand/laeuft/entwurf/geschlossen zeigen auf dieselben Farben. Knöpfe: ein
   Hauptknopf (.btn-primary, erster, volle Breite), alle anderen neutral — keine Grün/Rot-Mischung. Raster
   .karten-liste: eine Spalte, volle Breite, Knöpfe als .karte-knoepfe.zeile (Ansuchen, Kündigungen …);
   .karten-raster: auto-fill ab 300 px je Karte — gemessen 390 px: 1 Spalte, 900 px: 2, 1 440 px (Blatt breit): 3;
   gleiche Höhe je Zeile, Knöpfe unten. Hell/dunkel über Tokens. ---- */
.karte{background:var(--card);border:1px solid var(--rule);border-radius:14px;padding:16px 18px;min-width:0}
.karte.klein{padding:14px 16px}
.karte.rot{border-color:color-mix(in srgb,var(--ir-red) 40%,var(--rule))}
.karte.warn{border-color:color-mix(in srgb,var(--st-work) 45%,var(--rule))}
.karte.aus{opacity:.72}
/* Zone 0 (Backend 19.09. 15:12, Logo-Karten): große Bildvorschau über dem Kopf — Kasten 120 px, Bild bis 96 px mittig;
   Logos liegen immer auf Weiß (Marken-Regel: Logos nur unkomprimiert, auf Weiß), auch im Dunkelmodus; .dunkel = dunkler
   Grund für Negativfassungen, die auf Weiß unsichtbar wären. Markup: <div class="karte-bild [dunkel]"><img …></div> vor dem Kopf. */
.karte-bild{height:120px;margin:-4px 0 12px;border-radius:10px;background:#FFFFFF;border:1px solid var(--rule);
  display:grid;place-content:center;padding:12px;overflow:hidden;box-sizing:border-box}
.karte-bild.dunkel{background:var(--dunkel-card);border-color:var(--dunkel-rule)}
.karte-bild img{max-width:100%;max-height:96px;width:auto;height:auto;display:block}
.karte-logo{height:64px;display:flex;align-items:center;justify-content:space-between;gap:10px;margin:0 0 12px;padding:0 2px;border-bottom:1px solid var(--rule)}
.karte-logo img{max-height:44px;max-width:62%;width:auto;height:auto;object-fit:contain;display:block;border-radius:6px}
.karte-logo .initialen{display:inline-flex;align-items:center;justify-content:center;width:52px;height:40px;border-radius:8px;
  background:var(--rule-2);color:var(--ink-3);font-size:14px;font-weight:700;letter-spacing:.04em}
.karte-kopf{margin:0 0 6px;min-height:2.7em}
.karte-kopf h3,.karte-kopf b{font-family:var(--sans);font-size:15px;font-weight:700;line-height:1.3;margin:0;color:var(--ink);letter-spacing:0}
.karte-unter{margin:2px 0 0;font-size:13px;color:var(--ink-3);line-height:1.4}
/* Variante 2 (Backend 19.09. 15:10, Mitarbeiter-Karten): Kopf mit rundem Porträt links (40 px, Bild oder Initialen — Form
   .portraet wie beim Vorstand), Name und Nebenzeile rechts, vertikal mittig. Markup:
   <div class="karte-kopf mit-portraet"><span class="portraet initialen">TL</span><div><h3>Name</h3><p class="karte-unter">…</p></div></div> */
.karte-kopf.mit-portraet{display:flex;align-items:center;gap:10px}
.karte-kopf.mit-portraet > div{min-width:0}
.karte-kopf .portraet{display:inline-flex;align-items:center;justify-content:center;flex:none;width:40px;height:40px;border-radius:50%;
  overflow:hidden;background:var(--card-2);border:1px solid var(--rule)}
/* Kopflastiger Ausschnitt wie beim Vorstand (22.09.2026); je Bild überschreibbar mit style="--fokus:50% 18%". */
.karte-kopf .portraet img{width:100%;height:100%;object-fit:cover;object-position:var(--fokus,50% 22%);display:block}
.karte-kopf .portraet.initialen{background:var(--ink);color:var(--bg);font-family:var(--display);font-weight:800;font-size:.85rem;letter-spacing:.02em}
.karte-marken{display:flex;flex-wrap:wrap;gap:6px;align-items:center;margin:0 0 10px}
.karte-marken > *{margin:0;height:22px;box-sizing:border-box;display:inline-flex;align-items:center;line-height:1}
.stand{font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.04em;padding:2px 9px;border-radius:20px;
  background:var(--st-done-wash);color:var(--st-done);white-space:nowrap}
.stand.gut,.stand.aktiv,.stand.laeuft{background:var(--st-done-wash);color:var(--st-done)}
.stand.arbeit,.stand.ruhend,.stand.entwurf,.stand.offen{background:var(--st-work-wash);color:var(--st-work)}
.stand.aus,.stand.ausgeschieden,.stand.geschlossen,.stand.beendet{background:var(--st-open-wash);color:var(--st-open)}
.stand.rot,.stand.vorstand,.stand.dringend{background:var(--ir-red-wash);color:var(--ir-red-deep)}
.stand.vorstand{text-transform:none;letter-spacing:0}   /* trägt Amt und Namen („Vorstand · Obmann“) — alle anderen Stände in Versalien (Befund Backend 20.09.: rot war die Ausnahme) */
.stand.gold,.stand.premium{background:var(--st-gold-wash);color:var(--st-gold);border:1px solid color-mix(in srgb,var(--st-gold) 45%,transparent);text-transform:none;letter-spacing:.01em;font-weight:700}
.stand.info,.stand.extern{background:var(--ext-wash);color:var(--ext)}
.karte-daten{display:grid;grid-template-columns:62px minmax(0,1fr);column-gap:12px;row-gap:6px;margin:2px 0 6px;font-size:13px;line-height:1.4}
.karte-daten.breit{grid-template-columns:130px minmax(0,1fr)}   /* lange Beschriftungen (Backend 19.09. 15:22: Mitgliedschaftsverlauf) */
.karte-daten.breit dt{overflow-wrap:anywhere}
.karte-daten dt{margin:0;padding-top:2px;color:var(--ink-3);font-size:10.5px;font-weight:700;letter-spacing:.07em;text-transform:uppercase}
.karte-daten dd{margin:0;color:var(--ink);overflow-wrap:anywhere}
.karte-daten dd a,.karte-text a{color:inherit;text-decoration:none;border-bottom:1px solid var(--rule)}
.karte-daten dd a:hover,.karte-text a:hover{color:var(--ir-red);border-bottom-color:var(--ir-red)}
.karte-daten dd .neben,.karte-text .neben{color:var(--ink-3)}
.karte-daten dd .warn{color:var(--ir-red-deep);font-weight:600}
.karte-text{margin:0 0 6px;font-size:13.5px;color:var(--ink-2);line-height:1.5}
.karte-text.klein{font-size:12.5px;color:var(--ink-3)}
.karte-text.warn{color:var(--ir-red-deep)}
.karte-text.mono{font-family:ui-monospace,Menlo,Consolas,monospace}

/* ---- „Was noch fehlt" (Thomas 22.09.2026 zur Reihenfolge der Kanzlei-Seite: zuletzt der Kasten „mit allem,
   was noch fehlt — korrespondierend mit den Zahlen oben"). Er steht UNTER dem Erklärkasten und nennt je Punkt
   die Station der Strecke, damit man weiß, wohin man klicken muss. Ton: Arbeit (Gelb), nicht Rot — Rot ist
   die Marke, und Fehlendes ist kein Fehler, sondern eine offene Aufgabe.
   Markup: <div class="fehlt-kasten"><b>Für eine Rechnung fehlt noch etwas</b>
             <ul class="fehlt-liste">
               <li><span class="schrittnr klein">1</span><span><b>Firmendaten</b> — UID-Nummer</span></li>
               <li><span class="schrittnr klein">5</span><span><b>Dokumente</b> — noch kein Dokument</span></li>
             </ul>
             <p>Ohne diese Angaben kann der Kassier keine Halbjahresrechnung ausstellen.</p></div>   ---- */
.fehlt-kasten{padding:14px 16px;margin:0 0 18px;border-radius:12px;font-size:13.5px;line-height:1.55;color:var(--ink-2);
  background:var(--st-work-wash);border:1px solid color-mix(in srgb,var(--st-work) 38%,transparent)}
.fehlt-kasten > b{display:flex;align-items:center;gap:9px;color:var(--ink);font-family:var(--display);font-size:14.5px;font-weight:800}
.fehlt-kasten > b::before{content:"!";flex:none;width:22px;height:22px;border-radius:7px;display:grid;place-items:center;
  background:var(--st-work);color:#fff;font:800 13px/1 var(--display)}
.fehlt-kasten > p{margin:8px 0 0}
.fehlt-liste{list-style:none;margin:10px 0 0;padding:0;display:grid;gap:7px}
.fehlt-liste li{display:grid;grid-template-columns:26px minmax(0,1fr);gap:10px;align-items:center}
.fehlt-liste li b{color:var(--ink)}
.fehlt-liste .schrittnr{background:var(--st-work);color:#fff}   /* die Nummer der Station, nicht die Marke */

/* ---- Achtungszeile an einer Karte (Backend 22.09.2026, Wunsch Thomas: eine Änderung zum Termin — „ACHTUNG:
   geänderter Treffpunkt" — soll oben stehen, nicht im Fließtext der Ortszeile). Gehört als ERSTES Element
   hinter die Kopfzone: rosa Fläche, rote Kante links, kurzer Satz. Für Dialoge bleibt die IR-Meldung
   zuständig; diese Zeile steht IN der Karte und unterbricht nichts. ---- */
.karte-achtung{margin:0 0 8px;padding:7px 10px 7px 11px;border-left:3px solid var(--ir-red);border-radius:0 8px 8px 0;
  background:var(--ir-red-wash);color:var(--ir-red-deep);font-size:12.5px;line-height:1.45;font-weight:600}
.karte-achtung b{font-weight:800;letter-spacing:.02em}

/* ---- Ge- und Verbotsliste (Backend 22.09.2026 zur Markenseite: vier rote und zwei graue Striche standen
   ohne Erklärung nebeneinander — „warum?"). Statt Farbe allein sagt jede Zeile, was gilt: Haken oder Kreuz,
   dazu die Zwischenüberschrift. Markup:
     <ul class="regel-liste"><li class="geht">Signet auf weißem Grund</li>
     <li class="geht-nicht">Signet auf Farbfläche</li></ul>   ---- */
.regel-liste{list-style:none;margin:8px 0 0;padding:0;display:grid;gap:7px}
.regel-liste li{display:grid;grid-template-columns:20px minmax(0,1fr);gap:9px;align-items:start;font-size:13px;line-height:1.5;color:var(--ink-2)}
.regel-liste li::before{content:"";width:20px;height:20px;border-radius:6px;display:grid;place-items:center;
  font:800 12px/1 var(--sans);color:#fff}
.regel-liste li.geht::before{content:"✓";background:var(--st-done)}
.regel-liste li.geht-nicht::before{content:"✕";background:var(--ir-red)}
.regel-liste li b{color:var(--ink)}
.karte-knoepfe{margin-top:auto;padding-top:14px;display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}
.karte-knoepfe .btn{width:100%;box-sizing:border-box;text-align:center;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;margin:0}
.karte-knoepfe .btn:first-child{grid-column:1 / -1}
.karte-knoepfe.zeile{display:flex;flex-wrap:wrap}.karte-knoepfe.zeile .btn{width:auto}   /* Knopfzeile statt Raster (breite Karten) */
.karten-raster{display:grid;grid-template-columns:repeat(auto-fill,minmax(300px,1fr));gap:12px;align-items:stretch}
/* ---- Karten einer Reihe auf gleicher Höhe LESEN (Thomas 22.09.2026: „warum ist das wieder nicht alles
   horizontal ausgerichtet?"). Gleich hoch waren die Karten schon; was nicht stimmte, waren die Zonen
   INNEN: trägt eine Karte zwei Marken und die Nachbarin vier, rutscht bei ihr alles darunter nach unten.
   Mit `.buendig` teilen sich alle Karten der Reihe DIESELBEN Zeilen (subgrid), also beginnen Marken,
   Daten, Hinweis und Knöpfe überall auf derselben Linie.
   Bedingung ans Markup: Jede Karte der Reihe bringt die Zonen in derselben Reihenfolge und in derselben
   ANZAHL — fehlt einer Karte eine Zone, steht dort ein leeres Element (z. B. <div class="karte-marken"></div>).
   Ohne diese Zusage bitte `.buendig` weglassen; dann gilt wie bisher: gleich hoch, aber je Karte gesetzt. ---- */
@supports(grid-template-rows:subgrid){
  .karten-raster.buendig > .karte{display:grid;grid-template-rows:subgrid;grid-row:span var(--zonen,5);align-content:stretch}
  .karten-raster.buendig > .karte > *{min-width:0}
  /* Die Knopfzone beginnt oben in ihrer Zeile: So steht der Hauptknopf („Bearbeiten") in allen Karten der
     Reihe auf derselben Linie, auch wenn eine Karte zwei weitere Knöpfe darunter hat. Bündig ist der ERSTE
     Knopf, nicht der letzte — ihn sucht das Auge. */
  .karten-raster.buendig > .karte .karte-knoepfe{margin-top:0;align-self:start}
}
.karten-raster > .karte{margin:0;display:flex;flex-direction:column}   /* gleiche Höhe je Zeile, Knöpfe unten */
/* Variante 1 (Backend 19.09. 14:50): gestapelte Liste breiter Karten — Ansuchen, Kündigungen, Ausschlüsse stehen
   untereinander mit viel Text; Knöpfe darin als Zeile (.karte-knoepfe.zeile), nicht als Raster. */
.karten-liste{display:grid;grid-template-columns:minmax(0,1fr);gap:10px}
.karten-liste > .karte{margin:0}
/* Zone 5b (Backend 19.09.: die alte .grund-Box „Es fehlt noch: …"): hinterlegter Hinweis zwischen Daten und Knöpfen —
   ruhig grau; .warn = Marke-Wash für Fehlendes/Fristen; .gut = grün für Erledigtes. */
.karte-hinweis{margin:4px 0 8px;padding:7px 10px;border-radius:8px;background:var(--rule-2);color:var(--ink-2);font-size:12.5px;line-height:1.45}
.karte-hinweis.warn{background:var(--ir-red-wash);color:var(--ir-red-deep)}
.karte-hinweis.gut{background:var(--st-done-wash);color:var(--st-done)}
@media(max-width:560px){.karte{padding:14px 16px}.karten-raster{grid-template-columns:1fr}}

/* ---- Claim, der sich schreibt: Buchstaben-Spans aus blatt.php claim_buchstaben() (--d = Startzeit je Buchstabe),
   Schreibbewegung per clip-path. Nutzer: App-Intro (.intro-claim, intro.css) und der Kopf der Startseite (.r2-claim,
   start.css) — Thomas 21.09.2026: „wie beim Start der App". Klasse .claim-schreibt auf dem Elternelement genügt;
   ohne Bewegungswunsch steht der Claim sofort da. ---- */
.claim-schreibt span{display:inline-block;animation:introBuchstabe .14s ease-out both;animation-delay:var(--d,0s)}
/* Der Wortzwischenraum hängt am Claim, NICHT an der Bewegung (Befund Backend 22.09.: in der Seitenleiste stand
   „WirbewegenImmobilien.", sobald claim.js den Claim nach dem ersten Mal ruhig gestellt und `.claim-schreibt`
   entfernt hatte — dann griff die alte Regel `.claim-schreibt .lz` nicht mehr und der Abstand verschwand). */
.lz{display:inline-block;width:.55em;animation:none}
.claim-schreibt .lz{display:inline-block;width:.55em;animation:none}
@keyframes introBuchstabe{from{clip-path:inset(-45% 108% -45% -8%)}to{clip-path:inset(-45% -12% -45% -8%)}}
@media(prefers-reduced-motion:reduce){.claim-schreibt span{animation:none}}

/* ---- Ungültige Eingabe (App 22.09.2026: Betragsfelder sind Textfelder, Unlesbares wird nicht gespeichert): Rand und
   Fokusring in der Marke, Grund leicht rosa — Markup: class="ungueltig" + aria-invalid="true" am Feld; Text dazu in .form-error. ---- */
input.ungueltig,textarea.ungueltig,select.ungueltig,input[aria-invalid="true"],textarea[aria-invalid="true"],select[aria-invalid="true"]{
  border-color:var(--ir-red);outline-color:var(--ir-red);background:color-mix(in srgb,var(--ir-red-wash) 45%,var(--card))}
input[aria-invalid="true"]:focus-visible,textarea[aria-invalid="true"]:focus-visible,input.ungueltig:focus-visible,textarea.ungueltig:focus-visible{outline:2px solid var(--ir-red);outline-offset:1px}

/* ---- Zeigefähnchen (Tooltip): der kleine Kasten, der beim Überfahren einer Fläche Zahl und Herkunft nennt.
   Angelegt 22.09.2026 für die Bundesländer der Preiskarte (Thomas: „ich will, dass man bei den Bundesländern
   ein Mouseover hat"), bewusst allgemein — Diagramme und Ampeln brauchen dasselbe.
   Markup: <div class="ir-tip" role="status" hidden><b class="ir-tip-titel">Salzburg</b>
           <span class="ir-tip-wert">6.346 <small>EUR/m²</small></span>
           <span class="ir-tip-zeile">Median aus 2.458 Angeboten</span></div>
   Die Seite setzt nur `hidden`, `left`, `top` und den Text — Lage ist Layout, Form steht hier. Das Fähnchen
   nimmt keine Mausereignisse an und färbt sich aus den Token DES ORTES: in einem dunklen Container
   (Preiskarte) sind --card-2/--rule/--ink-3 dort dunkel, also passt es sich von selbst an.
   `.ir-tip-leer` = keine belastbare Zahl; dann bleibt der Wert weg und nur die Zeile erklärt, warum. ---- */
.ir-tip{position:absolute;z-index:5;max-width:220px;padding:10px 12px;pointer-events:none;
  background:var(--card-2);border:1px solid var(--rule);border-radius:10px;box-shadow:var(--shadow);
  display:flex;flex-direction:column;gap:2px;opacity:1;transition:opacity .12s ease-out}
.ir-tip[hidden]{display:none}
.ir-tip-titel{font-family:var(--display);font-size:12.5px;font-weight:700;color:var(--ink);letter-spacing:-.01em}
.ir-tip-wert{font-size:18px;font-weight:700;color:var(--ink);line-height:1.2;white-space:nowrap;font-variant-numeric:tabular-nums}
.ir-tip-wert small{font-size:11px;font-weight:600;color:var(--ink-2);margin-left:3px}
.ir-tip-zeile{font-size:11px;line-height:1.45;color:var(--ink-3)}
.ir-tip-leer .ir-tip-wert{display:none}
@media(prefers-reduced-motion:reduce){.ir-tip{transition:none}}

/* ---- Kleiner Zeilenknopf: quadratisch, 28 px, für die Werkzeuge in einer Zeile (↑ ↓ Auge, Zahnrad, Papierkorb).
   Eine Form für alle Ebenen — der Baukasten nennt ihn `.bk-knopf`, sonst heißt er `.btn-klein` (22.09.2026).
   Zustände: `.rot` = löschen (füllt beim Überfahren), `[aria-pressed="false"]` = ausgeschaltet/ausgeblendet
   (grau hinterlegt), `[disabled]` = hier nicht möglich (matt, kein Zeiger). ---- */
.btn-klein,.bk-knopf{width:28px;height:28px;flex:none;display:grid;place-items:center;padding:0;border:1px solid var(--rule);border-radius:8px;
  background:var(--card);color:var(--ink-2);font:600 13px/1 var(--sans);cursor:pointer;transition:background .12s,border-color .12s,color .12s}
.btn-klein:hover,.bk-knopf:hover{border-color:var(--ir-red);background:var(--ir-red-wash);color:var(--ir-red-deep)}
.btn-klein:focus-visible,.bk-knopf:focus-visible{outline:2px solid var(--ir-red);outline-offset:1px}
.btn-klein.rot:hover,.bk-knopf.rot:hover{background:var(--ir-red);border-color:var(--ir-red);color:#fff}
.btn-klein[aria-pressed="false"],.bk-knopf[aria-pressed="false"]{color:var(--ink-3);background:var(--rule-2)}
.btn-klein[disabled],.bk-knopf[disabled]{opacity:.45;cursor:default;background:var(--card);border-color:var(--rule);color:var(--ink-3)}
.btn-klein[disabled]:hover,.bk-knopf[disabled]:hover{border-color:var(--rule);background:var(--card);color:var(--ink-3)}

/* ---- Verschiebemodus: eine Liste, deren Zeilen ihre Reihenfolge ändern (Menü-Editor 22.09.2026; kommt auch
   bei Fragenreihenfolge, Vorgangs-Abschnitten und Baukasten-Containern vor, deshalb hier zentral).
   Markup: <ul class="zieh-liste"><li class="zieh-zeile"><span class="zieh-griff" aria-label="… verschieben"></span>…</li></ul>
   Zustände: `.ist-gehoben` = aufgenommen, `.ist-ziel` = darüber würde abgelegt, `.zieh-stelle` = die Ablegestelle
   zwischen zwei Zeilen, `.zieh-leer` = leere Gruppe, `.zeile-aus` = ausgeblendeter Eintrag (matt, NICHT rot —
   Rot ist die Marke, keine Wertung). Ziehen ist nie der einzige Weg: je Zeile gehören zwei Knöpfe hinauf/hinunter
   dazu (Tastatur, Telefon) — die Form dafür ist `.btn` bzw. `.bk-knopf`. ---- */
.zieh-liste{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:6px}
.zieh-zeile{display:flex;align-items:center;gap:10px;padding:8px 10px;background:var(--card);border:1px solid var(--rule);border-radius:9px}
.zieh-zeile > .wachsen{flex:1;min-width:0}
.zieh-zeile.ist-gehoben{opacity:.9;transform:rotate(-.4deg) scale(1.01);box-shadow:var(--shadow);border-color:var(--ir-red)}
.zieh-zeile.ist-ziel{border-color:var(--ir-red);background:var(--ir-red-wash)}
.zieh-zeile.zeile-aus,.zeile-aus{opacity:.55}
.zieh-griff{flex:none;width:28px;height:28px;display:grid;place-items:center;border-radius:7px;cursor:grab;color:var(--ink-3);
  background:radial-gradient(currentColor 1.1px,transparent 1.2px) 0 0/7px 7px;background-position:center;background-size:7px 7px}
.zieh-griff:active{cursor:grabbing}
.zieh-griff:hover{color:var(--ir-red);background-color:var(--ir-red-wash)}
.zieh-griff:focus-visible{outline:2px solid var(--ir-red);outline-offset:1px}
.zieh-stelle{height:3px;border-radius:3px;background:var(--ir-red);margin:1px 0}
.zieh-leer{padding:14px;border:1px dashed var(--rule);border-radius:9px;color:var(--ink-3);font-size:12.5px;text-align:center}
.zieh-liste.ist-aktiv{user-select:none}
@media(prefers-reduced-motion:reduce){.zieh-zeile.ist-gehoben{transform:none}}

/* ---- Feldgitter: mehrere Eingabefelder nebeneinander, am Telefon untereinander. Verallgemeinerung von
   `.feld-paar` (mitglieder.css, zwei feste Spalten) — die Felder selbst bleiben `.feld`. Ein Feld mit
   class="breit" nimmt die ganze Zeile. Markup: <div class="gitter-feld"><label class="feld breit">…</label>…</div>
   Angelegt 22.09.2026, weil Backend die Klasse auf /verwaltung/frontend.php schon verwendete, ohne dass es
   eine Form dazu gab (gemessen: die Felder standen untereinander statt im Gitter). ---- */
.gitter-feld{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:12px;align-items:start;margin-bottom:13px}
.gitter-feld > .breit{grid-column:1/-1}
/* Halbe Zeile (Thomas 22.09.2026: „dieses Feld über die halbe Breite" — die Rechtsform „Gesellschaft mit
   beschränkter Haftung" wurde in einer Standardspalte abgeschnitten). Für Felder, die mehr Text tragen als
   eine Spalte fasst, aber keine ganze Zeile brauchen: zwei Spalten statt einer. */
.gitter-feld > .halb{grid-column:span 2}
.gitter-feld > .feld{margin-bottom:0}
/* Eingabefelder einer Zeile beginnen auf derselben Linie (Thomas 22.09.2026: „bei Land stimmt die horizontale
   Ausrichtung nicht", „hier auch" — bei E-Mail). Ursache: Ein Feld mit Hilfetext („Ländercode, z. B. AT")
   trägt eine höhere Beschriftung und schob seine Eingabe nach unten. Mit subgrid teilen sich alle Felder der
   Zeile dieselben zwei Zeilen — Beschriftung oben, Eingabe unten —, egal wie lang der Hilfetext ist.
   Bedingung: `.feld` hat genau zwei Kinder (Beschriftung samt Hilfe, dann Eingabe) — so baut es gemein.js. */
@supports(grid-template-rows:subgrid){
  .gitter-feld > .feld{display:grid;grid-template-rows:subgrid;grid-row:span 3;align-content:start}
  .gitter-feld > .feld > span{align-self:start}
  .gitter-feld > .feld > input,.gitter-feld > .feld > select,.gitter-feld > .feld > textarea{align-self:start}
  /* Dritte Zeile: der Hilfetext UNTER der Eingabe. Felder ohne Hilfe bekommen ein leeres Element an seine
     Stelle, damit die Zeilen der Nachbarn nicht verrutschen — ohne dass die Seite dafür etwas liefern muss. */
  .gitter-feld > .feld:not(:has(> .feld-hilfe))::after{content:"";display:block}
}

/* ---- Hilfetexte, zentral (Auftrag Thomas 22.09.2026: „entwickle eine eigene zentrale Logik auch für die
   Hilfstexte, dass diese das Layout nicht zerschießen").
   DIE REGEL: Ein Hilfetext erklärt ein Feld — er steht UNTER der Eingabe, nie zwischen Beschriftung und
   Eingabe. Zwei Gründe: Die Eingaben einer Zeile bleiben dadurch auf gleicher Höhe, egal wie lang der Text
   ist, und man liest zuerst, was einzugeben ist, dann die Erläuterung.
   MARKUP: <label class="feld"><span>Beschriftung</span><input><i class="feld-hilfe">Ländercode, z. B. AT</i></label>
   Die alte Bauweise (Hilfe im <span> der Beschriftung) bleibt lesbar — sie wird nur nicht mehr gebaut.
   Der Text bricht um, statt die Spalte zu sprengen; drei Zeilen sind das Maß, mehr gehört in den
   Ablaufkasten „So läuft …". Für einen Hinweis, der einen Fehler meldet, gilt `.form-error`, nicht dies. ---- */
.feld-hilfe{display:block;font-style:normal;font-size:11.5px;line-height:1.45;color:var(--ink-3);margin-top:4px;
  max-width:60ch;overflow-wrap:anywhere;text-wrap:pretty}
.feld > .feld-hilfe{margin-top:5px}
.feld > span > .feld-hilfe{margin-top:3px}   /* Altbestand: Hilfe noch in der Beschriftung */
.feld-hilfe b,.feld-hilfe strong{color:var(--ink-2);font-weight:600}
.feld-hilfe.warn{color:var(--ir-red-deep)}   /* nur, wenn die Angabe fehlt oder nicht passt */
/* Ein Auswahlfeld darf seinen längsten Eintrag nicht verstecken: Es wächst nie über seine Spalte hinaus,
   aber der Text bleibt vollständig lesbar, sobald die Spalte reicht. */
.feld select{text-overflow:ellipsis}
@media(max-width:560px){.gitter-feld{grid-template-columns:1fr}.gitter-feld > .halb{grid-column:auto}}

/* ---- Schrittnummer (Thomas 22.09.2026: „diese Nummern sehen viel besser aus; können wir die auch für die
   Strecken/Vorgänge im Backend verwenden?"). Vorbild: die vier Nummern auf /start/mitglied-werden.php —
   gerundetes Quadrat statt Kreis, Marke als Grund, Montserrat 800. Hier zentral, damit sie in Frontend,
   Backend und App dieselbe Form hat; die Zustände decken den Vorgangs-Ablauf ab.
   Markup: <span class="schrittnr">1</span> · offen: class="schrittnr ruht" · erledigt: class="schrittnr fertig"
   Größen: Standard 34 px · class="klein" 26 px (Listen, Zeilen) · class="gross" 42 px (Einstieg, Blattkopf). ---- */
.schrittnr{display:inline-grid;place-items:center;flex:none;width:34px;height:34px;border-radius:10px;
  background:var(--ir-red);color:#fff;font:800 15px/1 var(--display);font-variant-numeric:tabular-nums;letter-spacing:0}
.schrittnr.ruht{background:var(--rule-2);color:var(--ink-3)}            /* noch nicht dran — Rot ist die Marke, nie eine Wertung */
.schrittnr.fertig{background:var(--st-done-wash);color:var(--st-done)}  /* erledigt */
.schrittnr.klein{width:26px;height:26px;border-radius:8px;font-size:12.5px}
.schrittnr.gross{width:42px;height:42px;border-radius:12px;font-size:18px}
h1>.schrittnr,h2>.schrittnr,h3>.schrittnr,h4>.schrittnr,.sec-head .schrittnr{margin-right:10px;vertical-align:middle}
