/* Grundlage beider Layouts. Papier-Neutral mit tiefem Petrol als Akzent;
   semantische Farben (Warnung, Sperre) sind davon getrennt. */
:root {
    --grund:#f6f5f1; --flaeche:#fff; --flaeche-2:#fbfaf7;
    --tinte:#17191f; --tinte-2:#545b68; --tinte-3:#7c8494;
    --rand:#dcd9d1; --rand-weich:#e9e6df;
    --akzent:#1f5a5e; --akzent-weich:#e3edec;
    --warn:#97281f; --hinweis:#8a5b10; --gut:#2f6140;
}

@media (prefers-color-scheme: dark) {
    :root:not([data-thema="hell"]) {
        --grund:#14161a; --flaeche:#1b1e24; --flaeche-2:#21252c;
        --tinte:#e8e6e1; --tinte-2:#a7adb8; --tinte-3:#7a828f;
        --rand:#2c313a; --rand-weich:#242932;
        --akzent:#5fb3b0; --akzent-weich:#1b2e30;
        --warn:#e0776e; --hinweis:#d7a445; --gut:#74c08d;
    }
}

* { box-sizing:border-box; }

body {
    margin:0; background:var(--grund); color:var(--tinte);
    font:16px/1.6 -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Noto Sans",sans-serif;
    -webkit-font-smoothing:antialiased;
}

a { color:var(--akzent); text-underline-offset:2px; }
a:focus-visible, button:focus-visible, input:focus-visible {
    outline:2px solid var(--akzent); outline-offset:1px;
}

.kopf {
    display:flex; align-items:center; gap:1rem;
    padding:.8rem 1.5rem; background:var(--flaeche);
    border-bottom:1px solid var(--rand);
}
.kopf .marke { font-weight:650; letter-spacing:-.01em; }
.kopf .mandant { color:var(--tinte-2); font-size:.9rem; }
.kopf nav { margin-left:auto; display:flex; gap:1rem; font-size:.9rem; }

main { max-width:70rem; margin:0 auto; padding:1.5rem; }

/* Das Impersonate-Banner ist Teil des Sicherheitsmechanismus, nicht Zierde -
   es muss auffallen und darf nicht wegscrollen. */
.impersonate-banner {
    position:sticky; top:0; z-index:50;
    padding:.7rem 1.5rem; font-size:.9rem;
    color:#fff; background:var(--warn);
}
.impersonate-banner a { color:#fff; }

table { border-collapse:collapse; width:100%; font-size:.92rem; }
th { text-align:left; font-size:.78rem; letter-spacing:.05em; text-transform:uppercase;
     color:var(--tinte-2); padding:.6rem .7rem; border-bottom:1px solid var(--rand); }
td { padding:.6rem .7rem; border-bottom:1px solid var(--rand-weich); vertical-align:top; }

/* --------------------------------------------------------------------
   Fristenuebersicht (AP-E02)

   Die Marke "gesetzlich" ist der einzige Farbeinsatz, der eine RECHTSFOLGE
   traegt: Ein so gekennzeichneter Termin laesst sich nicht verschieben. Sie
   steht deshalb in der Warnfarbe und nicht in der Akzentfarbe - und sie
   traegt zusaetzlich Text, weil eine Farbe allein fuer farbenblinde Leser
   keine Aussage ist (WCAG 1.4.1).
   -------------------------------------------------------------------- */
.kennzahlen { display:flex; flex-wrap:wrap; gap:1.5rem; margin:1rem 0 1.5rem; }
.kennzahlen p { margin:0; font-size:.95rem; }

.filterleiste { display:flex; gap:1rem; margin:0 0 1rem; font-size:.9rem; }
.filterleiste .aktiv { font-weight:650; text-decoration:none; }

.marke-gesetzlich {
    display:inline-block; margin-left:.4rem; padding:.05rem .4rem;
    font-size:.72rem; letter-spacing:.04em; text-transform:uppercase;
    color:var(--warn); border:1px solid var(--warn); border-radius:3px;
}

tr.ueberfaellig td { background:color-mix(in srgb, var(--warn) 7%, transparent); }

.knopf-klein { font-size:.82rem; padding:.25rem .6rem; }

.formular-schmal { max-width:26rem; display:grid; gap:.35rem; margin:1rem 0 2rem; }
.formular-schmal small { color:var(--tinte-2); font-size:.82rem; margin-bottom:.5rem; }

/* Nur fuer Lesegeraete: eine Spaltenueberschrift, die sichtbar leer bleibt,
   waere fuer einen Screenreader eine Spalte ohne Namen. */
.nur-lesegeraet {
    position:absolute; width:1px; height:1px; overflow:hidden;
    clip-path:inset(50%); white-space:nowrap;
}

/* --------------------------------------------------------------------
   Rueckmeldungen (Flash)

   Drei Kategorien, nicht zwei. "Fehler" und "Erfolg" reichen nicht fuer den
   Fall, den AP-F16 haeufig erzeugt: Es ist etwas ABSICHTLICH stehen
   geblieben. Das ist kein Fehlschlag - es ist die Regel, die greift. Wer es
   rot faerbt, erzieht zum Wegklicken.
   -------------------------------------------------------------------- */
p.fehler, p.erfolg, p.hinweis {
    margin:0 0 1rem; padding:.6rem .8rem; border-radius:4px;
    border-left:3px solid currentColor; font-size:.95rem;
}
p.fehler  { color:var(--warn);    background:color-mix(in srgb, var(--warn) 7%, transparent); }
p.erfolg  { color:var(--gut);     background:color-mix(in srgb, var(--gut) 7%, transparent); }
p.hinweis { color:var(--hinweis); background:color-mix(in srgb, var(--hinweis) 8%, transparent); }

/* --------------------------------------------------------------------
   Bausteinbibliothek (AP-G01)

   Der Diff ist die eigentliche Vorkehrung gegen das Durchwinken am
   Folgetag. Er traegt deshalb ZUSAETZLICH zur Farbe ein Zeichen (+ / −):
   Eine Farbe allein ist fuer farbenblinde Leser keine Aussage (WCAG 1.4.1),
   und ausgerechnet hier haengt an ihr, ob jemand einen geaenderten
   Rechtssatz bemerkt.
   -------------------------------------------------------------------- */
blockquote.wortlaut {
    margin:0 0 1rem; padding:.8rem 1rem; background:var(--flaeche-2);
    border-left:3px solid var(--akzent); border-radius:0 4px 4px 0;
}

ul.diff { list-style:none; padding:0; margin:0 0 1.5rem; font-family:ui-monospace,SFMono-Regular,Menlo,monospace; font-size:.9rem; }
ul.diff li { padding:.25rem .5rem; border-left:3px solid transparent; white-space:pre-wrap; }
ul.diff .diff--gleich { color:var(--tinte-3); }
ul.diff .diff--hinzu { color:var(--gut); border-left-color:var(--gut);
    background:color-mix(in srgb, var(--gut) 8%, transparent); }
ul.diff .diff--weg { color:var(--warn); border-left-color:var(--warn);
    background:color-mix(in srgb, var(--warn) 8%, transparent);
    text-decoration:line-through; text-decoration-thickness:1px; }

/* Die Ampel der Datenschutzerklaerung (AP-G05). Farbe UND Zeichen: Eine
   Farbe allein ist fuer farbenblinde Leser keine Aussage (WCAG 1.4.1). */
tr.ampel--rot td:first-child { color:var(--warn); font-weight:650; }
tr.ampel--gelb td:first-child { color:var(--hinweis); font-weight:650; }
tr.ampel--gruen td:first-child { color:var(--gut); }


/* ==========================================================================
   AB HIER: DER TEIL, DER BIS AP-H02 GEFEHLT HAT

   Die 137 Zeilen darueber lagen seit AP-A21 im Repository und waren in KEINER
   Vorlage eingebunden - kein <link rel="stylesheet">, kein Import in app.js.
   Jede Maske erschien als nacktes HTML. Aufgefallen ist es, als der
   Auftraggeber das System zum ersten Mal im Browser geoeffnet hat.

   Die Vorlagen benutzen rund 180 Klassen; abgedeckt waren 23. Was folgt, ist
   der Rest - nach Vorlagenfamilie geordnet, mit einem Grundteil vorweg, der
   fuer alle gilt.

   REGELN, DIE HIER GELTEN:
   - Nur die Custom Properties oben. Ein festes Hex bleibt im Dunkelmodus
     hell stehen.
   - Kein @import, kein url() auf einen fremden Host, kein Webfont. Die CSP
     lautet style-src 'self'; font-src 'self', und die Zusage nach aussen
     nennt genau drei Ziele.
   - Farbe traegt nie allein eine Aussage (WCAG 1.4.1). Wo eine Vorlage den
     begleitenden Text nicht liefert, steht das im Kommentar - zu beheben ist
     es dann in der VORLAGE, nicht hier.
   ========================================================================== */

/* ==========================================================================
   Was die Content-Security-Policy erzwingt

   107 Vorlagen trugen `style="..."` - fast durchweg Spaltenbreiten. Die CSP
   dieses Systems lautet style-src 'self'; damit faellt auch das ATTRIBUT, denn
   style-src-attr hat keine eigene Angabe und faellt auf style-src zurueck.
   Der Browser verwirft es ohne Meldung: Die Tabelle steht, die Breiten sind
   weg, und kein Test schlaegt an.

   Diese Klassen sind deshalb kein Utility-Framework, sondern die Uebersetzung
   von genau dem, was vorher in den Attributen stand. Die Liste ist GESCHLOSSEN
   - sie enthaelt die 19 Prozentwerte, die tatsaechlich vorkommen. Wer eine
   neue Breite braucht, traegt sie hier ein, und dann sieht man beim Lesen
   dieser Datei, wie viele es geworden sind.
   ========================================================================== */

/* Spaltenbreiten fuer Tabellenkoepfe.

   ".breite-14" und nicht ".spalte-14": ".spalte" ist bereits die Spalte des
   zweispaltigen Pruefbildschirms (AP-F15). Zwei Dinge, die gleich anfangen und
   Verschiedenes meinen, verwechselt frueher oder spaeter jemand. */
.breite-10 { width:10%; }
.breite-11 { width:11%; }
.breite-12 { width:12%; }
.breite-14 { width:14%; }
.breite-15 { width:15%; }
.breite-16 { width:16%; }
.breite-17 { width:17%; }
.breite-18 { width:18%; }
.breite-20 { width:20%; }
.breite-22 { width:22%; }
.breite-24 { width:24%; }
.breite-26 { width:26%; }
.breite-30 { width:30%; }
.breite-32 { width:32%; }
.breite-34 { width:34%; }
.breite-40 { width:40%; }
.breite-46 { width:46%; }
.breite-50 { width:50%; }
.breite-55 { width:55%; }

/* Zahlenspalten. Rechtsbuendig, damit Stellen untereinander stehen -
   bei Fristen und Betraegen ist das kein Geschmack, sondern Lesbarkeit. */
.rechts { text-align:right; }

/* --------------------------------------------------------------------------
   Der Fortschrittsbalken der Stammdatenerfassung (AP-D09)

   Der Anteil ist eine Zahl aus den Daten und muesste als Inline-Breite gesetzt
   werden - genau das laesst die CSP nicht durch. Die Vorlage rundet deshalb
   auf 5er-Stufen ab und setzt eine Klasse.

   Die Rundung ist ehrlich nach UNTEN: Ein Balken, der 3 Prozent auf 5
   aufrundet, behauptet mehr Fortschritt als da ist. Die genaue Zahl steht
   ohnehin im Text darueber und im aria-label - die Farbe traegt hier keine
   Aussage allein (WCAG 1.4.1).
   -------------------------------------------------------------------------- */
.fortschrittsbalken {
    position:relative; height:.6rem; margin:.5rem 0 0;
    background:var(--rand-weich); border-radius:3px; overflow:hidden;
}
.fortschrittsbalken span { position:absolute; top:0; left:0; height:100%; }
.balken-begonnen { background:var(--hinweis); opacity:.55; }
/* Der bestaetigte Teil liegt OBEN: Er ist die Teilmenge des begonnenen. */
.balken-bestaetigt { background:var(--akzent); z-index:1; }

/* Die 5er-Stufen. Geschlossene Liste, 0 bis 100. */
.anteil-0 { width:0%; }
.anteil-5 { width:5%; }
.anteil-10 { width:10%; }
.anteil-15 { width:15%; }
.anteil-20 { width:20%; }
.anteil-25 { width:25%; }
.anteil-30 { width:30%; }
.anteil-35 { width:35%; }
.anteil-40 { width:40%; }
.anteil-45 { width:45%; }
.anteil-50 { width:50%; }
.anteil-55 { width:55%; }
.anteil-60 { width:60%; }
.anteil-65 { width:65%; }
.anteil-70 { width:70%; }
.anteil-75 { width:75%; }
.anteil-80 { width:80%; }
.anteil-85 { width:85%; }
.anteil-90 { width:90%; }
.anteil-95 { width:95%; }
.anteil-100 { width:100%; }

/* --------------------------------------------------------------------------
   Einrueckung der Unterauftragskette (AP-E07)

   Vorher `padding-left:{{ (u.tiefe - 1) * 6 }}mm` - Millimeter in einer
   Bildschirmtabelle, uebernommen aus der PDF-Vorlage. Sechs Stufen reichen:
   Eine Unterauftragskette, die tiefer als sechs geht, ist kein Darstellungs-,
   sondern ein Vertragsproblem.
   -------------------------------------------------------------------------- */
.tiefe-1 { padding-left:.7rem; }
.tiefe-2 { padding-left:2.1rem; }
.tiefe-3 { padding-left:3.5rem; }
.tiefe-4 { padding-left:4.9rem; }
.tiefe-5 { padding-left:6.3rem; }
.tiefe-6 { padding-left:7.7rem; }

/* --------------------------------------------------------------------------
   Etwas, das abgetippt oder verglichen wird

   Der Faktorschluessel, ein Wurzelhash, eine Fassungsnummer. Dickte Schrift,
   weite Sperrung, umbruchfaehig - `word-break:break-all`, weil ein Hash sonst
   die Tabelle sprengt und `overflow-wrap` an einer Zeichenkette ohne
   Trennstelle nichts ausrichtet.
   -------------------------------------------------------------------------- */
.pruefsumme {
    font-family:ui-monospace,SFMono-Regular,Menlo,monospace;
    font-size:1.05rem; letter-spacing:.08em; word-break:break-all;
    background:var(--flaeche-2); border:1px solid var(--rand);
    border-radius:5px; padding:.7rem;
}

.kleingedruckt { color:var(--tinte-2); font-size:.85rem; }

/* === Geruest, Anmeldung, Cockpit, Formulare ===
   Grundbausteine, die jede Maske braucht. Dieser Abschnitt ERGAENZT app.css
   und definiert nichts daraus neu; wo eine Regel dicht an einer bestehenden
   liegt, steht der Grund daneben.

   Die Regeln unter ".huelle" sind der Inhalt des Inline-<style>-Blocks aus
   layout/schlank.html.twig. Der Block wird von der Content-Security-Policy
   verworfen (style-src 'self' ohne unsafe-inline), die Anmeldemaske erscheint
   deshalb unformatiert. Hier stehen die Regeln in einer ausgelieferten Datei;
   der Block in der Vorlage kann ersatzlos entfallen.
   -------------------------------------------------------------------- */

/* --- Ueberschriften ---------------------------------------------------- */

h1 { font-size:1.35rem; font-weight:650; letter-spacing:-.01em; margin:0 0 .8rem; }
h2 { font-size:1.05rem; font-weight:650; margin:2rem 0 .6rem; }
h3 { font-size:.95rem; font-weight:650; margin:1.5rem 0 .5rem; }
h1 + .unterzeile { margin-top:-.5rem; }

/* Sichtbare Tabellenueberschrift (Cockpit). Sie traegt dort die Einschraenkung
   "gezaehlt, nicht bewertet" und darf deshalb nicht wie Zierde aussehen. */
caption { text-align:left; color:var(--tinte-2); font-size:.85rem;
          padding:0 0 .5rem; max-width:70ch; }

code { font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace; font-size:.9em;
       /* 64 Hexzeichen sprengen sonst jede Tabellenzelle. */
       overflow-wrap:anywhere; padding:.05rem .25rem; background:var(--flaeche-2);
       border:1px solid var(--rand-weich); border-radius:3px; }

/* --- Beitexte ----------------------------------------------------------
   Drei Abstufungen, die im ganzen Bestand vorkommen: ".unterzeile" erklaert
   eine Maske, ".hilfe" ein Feld, ".nr" und ".klein" tragen Nebenangaben. */

.unterzeile { color:var(--tinte-2); font-size:.9rem; margin:0 0 1.5rem; max-width:70ch; }
.hilfe      { color:var(--tinte-2); font-size:.85rem; max-width:70ch; }
.nr         { color:var(--tinte-2); font-size:.85rem; }
.klein      { font-size:.85rem; color:var(--tinte-2); line-height:1.45;
              overflow-wrap:break-word; }

/* .nr steht auch unter mehrzeiligen Erlaeuterungen (Dokumentgestaltung) -
   dort ist es ein Absatz, kein Kuerzel. */
p.nr, p.hilfe { max-width:70ch; margin:.3rem 0 1rem; }

/* --- Zustandstexte -----------------------------------------------------
   ".warnung" bleibt reine Textauszeichnung: Sie sitzt sowohl in Kennzahlen
   und Tabellenzellen als auch auf ganzen Absaetzen. Ein Kasten wuerde die
   Kennzahlenzeile zerreissen - und die Aussage steht ohnehin im Text, die
   Farbe hebt sie nur hervor (WCAG 1.4.1 ist damit erfuellt, weil die Farbe
   nichts traegt, was der Wortlaut nicht sagt). */
.warnung { color:var(--warn); }

/* Der Hinweiskasten in app.css ist auf <p> eingeschraenkt; mehrere Masken
   setzen ihn auf <div>. Gleiche Anmutung, ohne die p-Regel anzutasten. */
div.hinweis {
    margin:0 0 1rem; padding:.6rem .8rem; border-radius:4px;
    border-left:3px solid currentColor; font-size:.95rem;
    color:var(--hinweis); background:color-mix(in srgb, var(--hinweis) 8%, transparent);
}
.hinweis > :first-child { margin-top:0; }
.hinweis > :last-child  { margin-bottom:0; }

/* Rueckmeldung im Portal und in einigen Backoffice-Masken. Eigene Klasse,
   weil diese Absaetze nicht aus app.flashes() stammen, sondern aus dem
   Vorgang selbst - sie stehen mitten in der Maske und nicht ganz oben. */
.meldung {
    margin:0 0 1rem; padding:.6rem .8rem; border-radius:4px;
    border-left:3px solid currentColor; font-size:.95rem;
    color:var(--tinte-2); background:var(--flaeche-2);
}
.meldung--erfolg { color:var(--gut);  background:color-mix(in srgb, var(--gut) 7%, transparent); }
.meldung--fehler { color:var(--warn); background:color-mix(in srgb, var(--warn) 7%, transparent); }

/* --- Marken (Zustandskuerzel in Tabellen) ------------------------------
   Zwei Absicherungen im Selektor, beide notwendig:
   "main" haelt die Regel von der Wortmarke im Kopf fern, die dieselbe Klasse
   traegt; ":not(.marke-gesetzlich)" laesst die Rechtsfolgen-Marke aus app.css
   unberuehrt, die eine staerkere Aussage macht als jede Zustandsmarke. */
main .marke:not(.marke-gesetzlich) {
    display:inline-block; padding:.05rem .4rem;
    font-size:.72rem; letter-spacing:.04em; text-transform:uppercase;
    color:var(--tinte-2); border:1px solid var(--rand); border-radius:3px;
}
main .marke.marke--ok    { color:var(--gut);     border-color:var(--gut); }
main .marke.marke--offen { color:var(--hinweis); border-color:var(--hinweis); }

/* --- Knoepfe -----------------------------------------------------------
   Der Grundknopf traegt Papierfarbe auf Akzent. --flaeche statt eines festen
   Weiss: im Dunkelmodus kippt der Akzent nach hell, die Schrift muss dann
   dunkel werden. Ein festes #fff bliebe hell auf hell stehen. */

button, input[type=submit] {
    font:inherit; font-size:.9rem; font-weight:600; cursor:pointer;
    padding:.45rem .9rem; border-radius:5px;
    color:var(--flaeche); background:var(--akzent); border:1px solid var(--akzent);
    transition:background-color .12s ease, border-color .12s ease;
}
button:hover, input[type=submit]:hover {
    background:color-mix(in srgb, var(--akzent) 85%, transparent);
}
button:disabled, input[type=submit]:disabled {
    cursor:not-allowed; color:var(--tinte-3);
    background:var(--flaeche-2); border-color:var(--rand);
}

/* .knopf-klein sitzt auf <a> UND auf <button> - die Klasse muss deshalb den
   Grundknopf oben abschalten, damit beide Traeger gleich aussehen.
   Schriftgroesse und Innenabstand stehen bereits in app.css und werden hier
   bewusst nicht wiederholt; die Schriftart kommt beim <button> aus der
   font:inherit-Regel oben. */
.knopf-klein {
    display:inline-block; font-weight:600; line-height:1.35;
    text-decoration:none; cursor:pointer;
    color:var(--akzent); background:var(--flaeche);
    border:1px solid var(--rand); border-radius:4px;
    transition:border-color .12s ease, background-color .12s ease;
}
.knopf-klein:hover { border-color:var(--akzent); background:var(--akzent-weich); }

/* Zerstoerende Nebenhandlung in einer Zeile ("Gespeicherten Wert entfernen").
   Bewusst kein Knopfrelief: Sie soll auffindbar sein, nicht einladen. */
.knopf-schlicht {
    font:inherit; font-size:.85rem; padding:0; cursor:pointer;
    color:var(--akzent); background:none; border:0;
    text-decoration:underline; text-underline-offset:2px;
}

.zurueck { display:inline-block; font-size:.9rem; margin:0 0 1rem; }
.weiter  { margin:2rem 0 0; font-size:.9rem; }

/* --- Formulare ---------------------------------------------------------
   Das Formularthema (templates/form/felder.html.twig) uebernimmt
   form_div_layout.html.twig unveraendert. Es erzeugt keine eigenen Klassen:
   Zeile = <div> ohne Klasse, Fehler = <ul><li id="..._errorN">,
   Hilfetext = .help-text, Pflichtfeld = label.required. Die Selektoren unten
   greifen deshalb an der erzeugten Struktur an, nicht an Wunschklassen. */

label { display:block; font-size:.85rem; font-weight:600; margin:1rem 0 .3rem; }

input[type=text], input[type=password], input[type=email], input[type=url],
input[type=tel], input[type=search], input[type=number], input[type=date],
input[type=datetime-local], input[type=time], input[type=file],
select, textarea {
    width:100%; max-width:26rem; padding:.45rem .6rem;
    font:inherit; font-size:.95rem;
    color:var(--tinte); background:var(--flaeche);
    border:1px solid var(--rand); border-radius:5px;
}
input[type=date], input[type=time] { max-width:12rem; }
input[type=number] { max-width:9rem; }
textarea { max-width:44rem; min-height:6rem; line-height:1.5; resize:vertical; }

/* app.css setzt die Fokusmarke fuer a, button und input - select und textarea
   fehlen dort und blieben sonst ohne sichtbaren Fokus. */
select:focus-visible, textarea:focus-visible {
    outline:2px solid var(--akzent); outline-offset:1px;
}

input:disabled, select:disabled, textarea:disabled {
    color:var(--tinte-3); background:var(--flaeche-2); cursor:not-allowed;
}
::placeholder { color:var(--tinte-2); opacity:1; }

/* Kontrollkaestchen: das Kaestchen steht vor seiner Beschriftung, beide in
   einer Zeile. Beide Schreibweisen kommen vor - Beschriftung um das Feld
   herum (handgeschriebene Masken) und Feld vor Beschriftung (erweiterte
   Auswahl aus dem Formularthema). */
input[type=checkbox], input[type=radio] { margin:0; accent-color:var(--akzent); }

label:has(> input[type=checkbox]), label:has(> input[type=radio]) {
    display:flex; align-items:baseline; gap:.5rem;
    font-weight:400; font-size:.95rem; max-width:60ch;
}
input[type=checkbox] + label, input[type=radio] + label {
    display:inline; margin:0 1.2rem 0 .4rem; font-weight:400; font-size:.95rem;
}

fieldset {
    margin:0 0 1.5rem; padding:.4rem 1.2rem 1.2rem;
    border:1px solid var(--rand-weich); border-radius:6px;
}
legend {
    padding:0 .4rem; font-size:.78rem; font-weight:650;
    letter-spacing:.05em; text-transform:uppercase; color:var(--tinte-2);
}

/* Pflichtkennzeichen des Formularthemas. Der Stern ist der zweite Traeger
   neben der Farbe (WCAG 1.4.1) - eine Legende dazu fehlt in den Vorlagen. */
label.required::after { content:" *"; color:var(--warn); }

.help-text { color:var(--tinte-2); font-size:.85rem; margin:.3rem 0 0; max-width:70ch; }

/* Feldfehler. Das Ausrufezeichen steht dort, weil die Fehlerzeile sonst nur
   an ihrer Farbe als Fehler erkennbar waere. */
form ul:has(> li[id*="_error"]) { list-style:none; margin:.3rem 0 0; padding:0; }
form li[id*="_error"] { color:var(--warn); font-size:.85rem; }
form li[id*="_error"]::before { content:"! "; font-weight:700; }

/* Sammlungen: das Formularthema haengt data-prototype an den Behaelter. Jede
   Zeile bekommt einen eigenen Rahmen, sonst laufen mehrere Untereintraege
   optisch ineinander. */
form [data-prototype] > div {
    margin:0 0 .6rem; padding:.7rem .9rem;
    background:var(--flaeche-2); border:1px solid var(--rand-weich); border-radius:5px;
}

.formular-inline {
    display:flex; flex-wrap:wrap; align-items:flex-end; gap:.6rem;
    margin:0 0 1rem;
}
.formular-inline label { margin:0; }
.formular-inline input, .formular-inline select { width:auto; }

/* --- Listen ------------------------------------------------------------ */

ul.liste { list-style:none; margin:0; padding:0; }
ul.liste li { border-bottom:1px solid var(--rand); }
ul.liste li:last-child { border-bottom:0; }
ul.liste a { display:block; padding:.8rem .2rem; color:inherit; text-decoration:none; }
ul.liste a:hover { color:var(--akzent); }

/* Schaltet bedingte Bloecke ab. Wird vom Stimulus-Controller "bedingung"
   gesetzt und ist damit kein Aussehen, sondern Funktion: Die Regel muss jede
   Anzeigeregel des Blocks schlagen, sonst bleibt ein abgewaehltes Feld
   sichtbar und wird mitgeschickt. */
.verborgen { display:none !important; }

/* --- Anmeldung und Mandantenauswahl (schlankes Layout) -----------------
   layout/schlank.html.twig hat weder Kopfzeile noch Impersonate-Banner. Keine
   Regel hier darf .kopf voraussetzen, und keine Regel oben faerbt die Karte:
   Die Anmeldemaske erbt vom Backoffice nur Grundfarben und Schrift. */

.huelle { max-width:26rem; margin:12vh auto; padding:0 1rem; }
.karte {
    padding:2rem; background:var(--flaeche);
    border:1px solid var(--rand); border-radius:8px;
}
.huelle h1 { margin:0 0 .35rem; }
.huelle .unterzeile { margin:0 0 1.5rem; }

/* Eingabefelder der Anmeldung fuellen die Karte und stehen abgesetzt vom
   Kartengrund - deshalb --grund und nicht --flaeche. */
.huelle input[type=text], .huelle input[type=password] {
    max-width:none; padding:.6rem .7rem; font-size:1rem; background:var(--grund);
}
.huelle button { width:100%; margin-top:1.5rem; padding:.7rem; font-size:1rem; }

/* --- Cockpit (AP-E43) --------------------------------------------------
   Zaehlwerte, keine Bewertung. Die Kacheln bekommen deshalb keine Ampel und
   keinen Reifegrad; "offen" und "leer" unterscheiden sich in Randstaerke und
   Sattheit, und die Aussage steht in der Zahl und im Text darunter. */

.kacheln { margin:0 0 2rem; }

.kachelliste {
    list-style:none; margin:0; padding:0;
    display:grid; gap:.8rem;
    grid-template-columns:repeat(auto-fill, minmax(15rem, 1fr));
}
.kachel {
    display:grid; gap:.15rem; padding:.9rem 1rem;
    background:var(--flaeche); border:1px solid var(--rand); border-radius:6px;
}
.kachel--offen { border-left:3px solid var(--hinweis); padding-left:calc(1rem - 2px); }
.kachel--leer  { background:var(--flaeche-2); }

.kachel__zahl {
    font-size:1.7rem; font-weight:650; line-height:1.15;
    font-variant-numeric:tabular-nums;
}
.kachel--offen .kachel__zahl { color:var(--hinweis); }
.kachel--leer  .kachel__zahl { color:var(--tinte-3); }

.kachel__bezeichnung { font-size:.95rem; font-weight:600; }
.kachel__mandate     { color:var(--tinte-2); font-size:.85rem; }
.kachel__norm        { color:var(--tinte-2); font-size:.78rem; margin-top:.25rem; }

.freigabestand { margin:0 0 2rem; }
.freigabestand table { max-width:36rem; }

@media (prefers-reduced-motion: reduce) {
    button, input[type=submit], .knopf-klein { transition:none; }
}

/* === Verarbeitungsverzeichnis und Kataloge ===
   templates/backoffice/{vt,katalog,system,loeschklasse,drittland,tom}

   Das fachliche Herz nach Art. 30. Hier steht die laengste Maske des Systems -
   48 Felder in acht Gruppen. Gliederung ist deshalb keine Zierde, sondern die
   Bedingung dafuer, dass jemand das Formular zu Ende ausfuellt.
   -------------------------------------------------------------------- */

/* --------------------------------------------------------------------
   Grundstil der Formularelemente

   ACHTUNG BEIM ZUSAMMENFUEGEN: Dieser Abschnitt ist nicht familienspezifisch.
   app.css kennt bisher kein einziges Formularelement, und das Formularthema
   (templates/form/felder.html.twig) ist das unveraenderte form_div_layout -
   form_row liefert also <div><label>...</label><input></div> ganz ohne Klasse.
   Ohne diese Regeln steht jede Maske als nacktes HTML da. Der Block gehoert
   fachlich in den Grundteil von app.css und darf nur EINMAL vorkommen.
   -------------------------------------------------------------------- */
form { max-width:60rem; }

form label {
    display:block; margin:0 0 .25rem;
    font-size:.85rem; font-weight:600; color:var(--tinte-2);
}

/* Ein Kaestchen bringt seine Beschriftung selbst mit - die steht dann in
   Lesefarbe und nicht in der gedaempften Feldbeschriftungsfarbe. */
form label:has(> input[type=checkbox]),
form label:has(> input[type=radio]) {
    margin:.5rem 0 .3rem; font-weight:400; color:var(--tinte);
}

form input, form select, form textarea {
    width:100%; max-width:34rem; margin:0 0 .9rem; padding:.45rem .6rem;
    font:inherit; font-size:.95rem; color:var(--tinte);
    background:var(--flaeche); border:1px solid var(--rand); border-radius:4px;
    transition:border-color 120ms ease-out;
}
form input:hover, form select:hover, form textarea:hover { border-color:var(--tinte-3); }
form select:focus-visible, form textarea:focus-visible, summary:focus-visible {
    outline:2px solid var(--akzent); outline-offset:1px;
}

form textarea { min-height:4.5rem; resize:vertical; line-height:1.5; }
form input[type=date], form input[type=number] { max-width:14rem; }
form input[type=file] { padding:.35rem; background:var(--flaeche-2); }
form select[multiple] { height:auto; padding:.3rem; }
form input[type=checkbox], form input[type=radio] {
    width:auto; margin:0 .4rem 0 0; accent-color:var(--akzent);
}

/* Ein Hilfetext gehoert an sein Feld, nicht in den Abstand zum naechsten. */
form input:has(+ small), form select:has(+ small), form textarea:has(+ small) { margin-bottom:.25rem; }
form small { display:block; max-width:34rem; margin:0 0 .9rem; font-size:.82rem; color:var(--tinte-2); }

form fieldset {
    margin:0 0 1.25rem; padding:.9rem 1.1rem .1rem;
    background:var(--flaeche-2); border:1px solid var(--rand); border-radius:6px;
}
form legend { padding:0 .4rem; font-size:.88rem; font-weight:650; color:var(--tinte-2); }


/* Pflichtangaben tragen WORT und Farbe. Eine rote Umrandung allein waere fuer
   farbenblinde Leser keine Aussage (WCAG 1.4.1) - und ausgerechnet hier
   entscheidet sie darueber, ob die Freigabe spaeter scheitert. Das Wort kommt
   derzeit aus dem CSS; es gehoert auf Dauer in die Vorlage. */
form label:has(+ input[required])::after,
form label:has(+ select[required])::after,
form label:has(+ textarea[required])::after {
    content:" (Pflichtangabe)"; font-weight:400; font-size:.78rem; color:var(--warn);
}
form input[required], form select[required], form textarea[required] {
    border-left:3px solid color-mix(in srgb, var(--warn) 45%, transparent);
}

/* Formular in einer Tabellenzelle: eine Zeile, keine Spalte. */
td form { display:flex; flex-wrap:wrap; align-items:center; gap:.4rem; margin:0; max-width:none; }
td form input, td form select, td form textarea { margin-bottom:0; max-width:16rem; }
pre {
    overflow-x:auto; margin:0 0 1.25rem; padding:.7rem .9rem;
    background:var(--flaeche-2); border:1px solid var(--rand); border-radius:5px;
}
pre code { background:none; border:0; padding:0; }

@media (prefers-reduced-motion: reduce) {
    form input, form select, form textarea, form button { transition:none; }
}
p.unterzeile { margin:-.2rem 0 1.25rem; max-width:70ch; }
h1 .unterzeile { font-size:.6em; font-weight:400; }
span.nr { font-size:.85em; }

/* --------------------------------------------------------------------
   Feldgruppen der langen Maske (AP-B29, ADR 0018)

   Acht aufklappbare Gruppen statt einer flachen Liste ueber 48 Felder. Die
   Gruppe traegt ihre Ueberschrift als <summary>; ohne sichtbaren Kopf waere
   der Aufklappmechanismus nur eine weitere Zeile.
   -------------------------------------------------------------------- */
details.feldgruppe {
    margin:0 0 .75rem; background:var(--flaeche);
    border:1px solid var(--rand); border-radius:6px;
}
details.feldgruppe > summary {
    padding:.7rem 1rem; font-weight:650; cursor:pointer;
    border-radius:6px;
}
details.feldgruppe[open] { padding-bottom:.9rem; }
details.feldgruppe[open] > summary {
    margin-bottom:.6rem; border-radius:6px 6px 0 0;
    border-bottom:1px solid var(--rand-weich);
}
details.feldgruppe > :not(summary) { margin-left:1rem; margin-right:1rem; }

/* Bedingte Sichtbarkeit: Die Einrueckung sagt, dass dieser Block an einer
   Bedingung haengt. Verborgen wird ueber BEIDES - der Controller setzt das
   hidden-Attribut und die Klasse; eine display-Angabe auf .bedingter-block
   wuerde hidden aushebeln, deshalb steht sie hier ausdruecklich nicht. */
.bedingter-block { margin-bottom:.9rem; padding-left:.8rem; border-left:2px solid var(--akzent-weich); }
.bedingter-block.verborgen, .bedingter-block[hidden] { display:none; }

/* Was noch nicht gebaut ist, steht sichtbar da - eine stille Luecke vermisst
   niemand. Gestrichelt, weil hier nichts einzugeben ist. */
.platzhalter {
    margin-bottom:.9rem; padding:.6rem .8rem; font-size:.9rem; color:var(--tinte-2);
    background:var(--flaeche-2); border:1px dashed var(--rand); border-radius:4px;
}
.platzhalter strong { display:block; color:var(--tinte); }

/* --------------------------------------------------------------------
   Art. 9 und Art. 10 (AP-B21)

   An besonderen Kategorien haengt eine ANDERE RECHTSFOLGE als am Rest der
   Maske, und der Block wandert unveraendert ins PDF. Er bekommt deshalb einen
   eigenen Rahmen mit warnfarbenem Ruecken. Traeger der Aussage bleibt der Text
   in den enthaltenen Absaetzen - sie nennen Art. 9 bzw. Art. 10 ausdruecklich
   (WCAG 1.4.1); die Farbe macht den Block nur auffindbar.
   -------------------------------------------------------------------- */
.art9-block {
    margin:.75rem 0 1rem; padding:.9rem 1.1rem 0;
    background:var(--flaeche-2);
    border:1px solid var(--rand); border-left:4px solid var(--warn);
    border-radius:0 5px 5px 0;
}

/* --------------------------------------------------------------------
   Kontrollmassnahmen (AP-B22, § 12 Abs. 4 DSG)

   Die drei Ziffern stehen EINZELN mit je einer bewussten Bestaetigung. Jede
   bekommt eine eigene Flaeche - ein Haken in einer Absatzwueste ist optisch
   ein Sammelhaken, und genau das soll er nicht sein.
   -------------------------------------------------------------------- */
fieldset.kontrollmassnahmen { background:var(--flaeche); }
fieldset.kontrollmassnahmen h4 { margin:1.4rem 0 .4rem; font-size:.95rem; }

label.ziffer {
    position:relative; display:block; margin:0 0 .4rem;
    padding:.5rem .7rem .5rem 2rem;
    font-weight:400; color:var(--tinte); font-size:.93rem;
    background:var(--flaeche-2); border:1px solid var(--rand-weich); border-radius:4px;
}
label.ziffer input { position:absolute; top:.7rem; left:.7rem; }
label.ziffer strong { color:var(--tinte-2); }

/* Der nicht zutreffende Nachweisweg bleibt sichtbar und erklaert sich. Die
   Ausgrauung ist nicht der Traeger der Aussage - der eingeschlossene .nr-Text
   sagt in Worten, warum dieser Weg hier nicht gilt. */
label.ausgegraut {
    display:block; margin:.6rem 0 .9rem; padding:.6rem .8rem;
    font-weight:400; color:var(--tinte-3);
    border:1px dashed var(--rand); border-radius:4px;
}
label.ausgegraut input { opacity:.6; cursor:not-allowed; }

/* --------------------------------------------------------------------
   Sammlungen: Betroffenengruppe > Datenart > Empfaenger (AP-B28)

   Drei Ebenen ineinander. Die Verschachtelung muss man SEHEN, sonst weiss
   niemand mehr, zu welcher Gruppe eine Datenart gehoert. Jede Ebene tiefer
   wechselt die Flaeche und rueckt ein.
   -------------------------------------------------------------------- */
.datenkategorie {
    margin:0 0 1rem; padding:1rem 1.1rem;
    background:var(--flaeche); border:1px solid var(--rand); border-radius:6px;
}

details.datenarten { margin:.5rem 0 .9rem; border-top:1px solid var(--rand-weich); }
details.datenarten > summary {
    padding:.55rem 0; font-size:.9rem; font-weight:650;
    color:var(--akzent); cursor:pointer;
}

.datenart-zeile {
    margin:.6rem 0; padding:.8rem 1rem;
    background:var(--flaeche-2);
    border:1px solid var(--rand-weich); border-left:3px solid var(--akzent-weich);
    border-radius:0 5px 5px 0;
}

/* Die Verknuepfungen haengen an der Datenart, nicht an der Gruppe - die
   hellere Flaeche haelt sie als eigene Ebene auseinander. */
fieldset.verknuepfungen { background:var(--flaeche); }

/* --------------------------------------------------------------------
   Pflichtangaben und offene Punkte (AP-B36)

   Dieselbe Liste erscheint in der Maske, vor der Freigabe und im
   Kontrollblock. Sie sieht ueberall gleich aus, weil es dieselbe Aussage ist.
   -------------------------------------------------------------------- */
section.vollstaendigkeit {
    margin:1.5rem 0; padding:1rem 1.2rem 0;
    background:var(--flaeche); border:1px solid var(--rand); border-radius:6px;
}
section.vollstaendigkeit h3 { margin:0 0 .6rem; font-size:1rem; }
section.vollstaendigkeit .kennzahl { margin:0 0 .8rem; font-size:.95rem; color:var(--tinte-2); }
section.vollstaendigkeit .kennzahl strong { color:var(--tinte); }

p.erfuellt {
    margin:0 0 1rem; padding:.6rem .8rem; font-size:.95rem;
    color:var(--gut); background:color-mix(in srgb, var(--gut) 7%, transparent);
    border-left:3px solid currentColor; border-radius:4px;
}

ul.offene-punkte { list-style:none; display:grid; gap:.5rem; margin:0 0 1.25rem; padding:0; }
ul.offene-punkte li {
    padding:.55rem .8rem; font-size:.93rem;
    background:var(--flaeche-2);
    border-left:3px solid var(--rand); border-radius:0 4px 4px 0;
}
ul.offene-punkte li.warnung, ul.offene-punkte li.blockiert {
    color:var(--warn); border-left-color:var(--warn);
    background:color-mix(in srgb, var(--warn) 7%, transparent);
}
ul.offene-punkte li.hinweis {
    color:var(--hinweis); border-left-color:var(--hinweis);
    background:color-mix(in srgb, var(--hinweis) 8%, transparent);
}

/* Das Normzitat steht VOR der Pflichtangabe und traegt einen eigenen Rahmen:
   "Feld fehlt" ist eine Aufforderung, "Art. 30 Abs. 1 lit. f" eine
   Begruendung - und die soll man auf einen Blick als solche erkennen. */
ul.offene-punkte .norm {
    display:inline-block; margin-right:.5rem; padding:.05rem .35rem;
    font-size:.72rem; letter-spacing:.03em; color:var(--tinte-2);
    border:1px solid var(--rand); border-radius:3px;
}
ul.offene-punkte .pflichtangabe { font-weight:650; }
ul.offene-punkte .begruendung { margin:.3rem 0 0; font-size:.88rem; color:var(--tinte-2); }

/* Der Vorbehalt aus ADR 0023 steht am Fuss und bleibt dort stehen. Klein, aber
   nicht versteckt: Vor Gericht zaehlt, was tatsaechlich dastand. */
p.vorbehalt {
    margin:0; padding:.7rem 0 .9rem; font-size:.82rem; color:var(--tinte-2);
    border-top:1px solid var(--rand-weich);
}

/* --------------------------------------------------------------------
   Konflikt bei gleichzeitiger Bearbeitung (AP-B24)

   Der Kasten muss den Blick halten: Der Benutzer entscheidet hier, welche
   Fassung gilt. Ein weggeklickter Konfliktdialog kostet die Eingaben.
   -------------------------------------------------------------------- */
.konflikt {
    margin:0 0 1.5rem; padding:1rem 1.2rem .1rem;
    background:var(--flaeche);
    border:1px solid var(--rand); border-left:4px solid var(--warn);
    border-radius:0 6px 6px 0;
}
.konflikt h2 { margin:0 0 .6rem; font-size:1.05rem; color:var(--warn); }
.konflikt label {
    display:inline-block; margin:0 .8rem .2rem 0;
    font-weight:400; color:var(--tinte); font-size:.9rem;
}

/* Der Freigabe-Abweis (vt/freigeben) ist ein <div class="fehler"> mit
   Ueberschrift; app.css kennt bisher nur p.fehler. */
div.fehler {
    margin:0 0 1.25rem; padding:.8rem 1rem .1rem;
    color:var(--warn); background:color-mix(in srgb, var(--warn) 7%, transparent);
    border-left:3px solid currentColor; border-radius:0 4px 4px 0;
}
div.fehler h2 { margin:0 0 .4rem; font-size:1.05rem; color:inherit; }
strong.warnung, span.warnung { font-weight:650; }
p.warnung {
    margin:0 0 1rem; padding:.6rem .8rem; font-size:.95rem;
    background:color-mix(in srgb, var(--warn) 7%, transparent);
    border-left:3px solid currentColor; border-radius:4px;
}
/* In der Kennzahlenzeile ist die Warnung eine Zahl in einer Reihe, kein
   Kasten - sonst bricht die Zeile aus app.css auseinander. */
.kennzahlen p.warnung { margin:0; padding:0; background:none; border:0; }
div.hinweis-warnung { color:var(--warn); background:color-mix(in srgb, var(--warn) 7%, transparent); }
span.hinweis { color:var(--hinweis); }

/* --------------------------------------------------------------------
   Kataloge: Vorschlaege, Dubletten, Pruefbloecke
   -------------------------------------------------------------------- */
ul.vorschlaege {
    list-style:none; max-width:34rem; margin:.25rem 0 1rem; padding:0;
    background:var(--flaeche); border:1px solid var(--rand);
    border-radius:5px; overflow:clip; overflow-clip-margin:3px;
}
ul.vorschlaege li { padding:.45rem .7rem; font-size:.93rem; border-bottom:1px solid var(--rand-weich); }
ul.vorschlaege li:last-child { border-bottom:0; }
ul.vorschlaege li:hover { background:var(--flaeche-2); }
ul.vorschlaege li[data-katalog-id] { cursor:pointer; }

/* >> DER GEWAEHLTE VORSCHLAG BRAUCHT EINE ANZEIGE, DIE NICHT NUR FARBE IST.
   
   Der Fokus bleibt beim Combobox-Muster im Eingabefeld; sichtbar bewegt sich
   nur aria-activedescendant. Ein Fokusring kann hier also gar nicht
   erscheinen - diese Regel ist sein Ersatz. Deshalb Flaeche UND Kante: Wer
   den Farbunterschied nicht sieht, erkennt die Kante an der Kontur
   (WCAG 1.4.1, 2.4.7). */
ul.vorschlaege li[aria-selected="true"] {
    background:var(--akzent-weich);
    box-shadow:inset 3px 0 0 var(--akzent);
}
ul.vorschlaege a { font-weight:600; text-decoration:none; }
ul.vorschlaege a:hover { text-decoration:underline; }

section.kandidat {
    margin:0 0 1.5rem; padding:1rem 1.2rem;
    background:var(--flaeche); border:1px solid var(--rand); border-radius:6px;
}
section.kandidat h2 { margin:0 0 .7rem; font-size:1.05rem; }
section.kandidat dl {
    display:grid; grid-template-columns:max-content 1fr; gap:.25rem .9rem;
    margin:0 0 1rem; font-size:.92rem;
}
section.kandidat dt {
    padding-top:.1rem; font-size:.75rem; letter-spacing:.04em;
    text-transform:uppercase; color:var(--tinte-2);
}
section.kandidat dd { margin:0; }

/* Je Massnahme ein Block mit eigenem Formular (AP-E12). Es gibt bewusst
   keinen Sammelknopf "alle geprueft" - die Gestaltung darf deshalb auch nicht
   nach einer Liste aussehen, die man von oben nach unten durchhaekelt. */
section.pruefblock {
    margin:0 0 1.25rem; padding:1rem 1.2rem;
    background:var(--flaeche); border:1px solid var(--rand); border-radius:6px;
}
section.pruefblock h3 { margin:0 0 .1rem; font-size:1rem; }
section.pruefblock > p { font-size:.93rem; }

/* app.css gibt .formular-schmal ein Raster mit eigenem Abstand; die
   Aussenabstaende der Felder wuerden sich darin verdoppeln. */
.formular-schmal label { margin-top:.6rem; }
.formular-schmal input, .formular-schmal select, .formular-schmal textarea { margin-bottom:0; }
.formular-schmal button { justify-self:start; margin-top:.8rem; }

/* === Datenschutzerklaerung, Bausteine, Durchsicht ===
   Vorlagen: templates/dse/ (12), templates/backoffice/dse/ (7),
   templates/backoffice/baustein/ (4), templates/backoffice/durchsicht/ (2).

   Ergaenzt den Grundstil aus app.css; nichts von dort wird hier ersetzt.
   Ausnahmen sind zwei eng gefasste Regeln in .dse-angaben, jede mit
   Begruendung an Ort und Stelle. Es bewegt sich nichts - deshalb steht
   hier auch keine Regel fuer prefers-reduced-motion. */

dl.angaben { margin:0 0 1.5rem; max-width:44rem; }
dl.angaben dt { margin-top:.9rem; font-weight:650; }
dl.angaben dd { margin:.15rem 0 0; color:var(--tinte-2); }

/* --------------------------------------------------------------------
   Der Rechtstext (.dse)

   Das Fragment aus templates/dse/ ist kein Verwaltungsformular: Ein
   Mensch muss es lesen und verantworten, bevor es als Information nach
   Art. 13 hinausgeht. Deshalb begrenzte Zeilenlaenge, groessere
   Zeilenhoehe und sichtbare Abschnittsgrenzen - und nicht die dichte
   Setzung der uebrigen Masken.
   -------------------------------------------------------------------- */
.dse { max-width:52rem; line-height:1.7; }

/* Fliesstext schmaler als die Tabellen: 38rem sind rund 75 Zeichen. Die
   Angabentabelle braucht mehr Breite und bekommt sie. */
.dse p, .dse-kurzuebersicht li { max-width:38rem; }

.dse h2 { margin:0 0 .7rem; font-size:1.15rem; letter-spacing:-.01em; }
.dse h3 { margin:1.3rem 0 .5rem; font-size:1rem; }
.dse strong { font-weight:650; }

.dse-abschnitt { margin:0 0 2rem; }

/* Wer prueft, muss sehen, wo eine Pflichtangabe aufhoert und die
   naechste beginnt. Uebersicht und Lueckenliste tragen eine eigene
   Flaeche und brauchen die Linie nicht. */
.dse-abschnitt + .dse-abschnitt:not(.dse-uebersicht):not(.dse-lueckenliste) {
    padding-top:1.6rem; border-top:1px solid var(--rand-weich);
}

.dse-rahmen p, .dse-typ p { margin:0 0 .9rem; }

/* Verantwortlicher und Anschrift sind die eine Angabe, die eine
   betroffene Person abschreibt, um sich zu wenden. */
.dse-verantwortlicher {
    margin:0 0 .9rem; padding-left:.9rem; line-height:1.5;
    border-left:2px solid var(--akzent);
}

.dse-normen p { font-size:.95rem; color:var(--tinte-2); }

/* --------------------------------------------------------------------
   Erste Schicht: die Kurzuebersicht (WP260 rev.01)

   Sie ordnet und ersetzt nichts. Eigene Flaeche, damit sie als Einstieg
   erkennbar ist - aber ohne Rahmen, der sie zu einem Kasten NEBEN dem
   Text machen wuerde; sie gehoert in den Text.
   -------------------------------------------------------------------- */
.dse-uebersicht {
    margin:0 0 2rem; padding:1.1rem 1.3rem;
    background:var(--flaeche-2); border-radius:5px;
}
.dse-kurzuebersicht { margin:0; padding:0; list-style:none; }
.dse-kurzuebersicht li {
    padding:.45rem 0 .45rem .9rem; border-left:2px solid var(--rand);
}
.dse-kurzuebersicht li + li { margin-top:.3rem; }
.dse-grundlage { color:var(--tinte-2); font-size:.9em; }

/* --------------------------------------------------------------------
   Zweite Schicht: die Einzelheiten je Verarbeitung
   -------------------------------------------------------------------- */
.dse-einzelheiten { margin:0 0 2rem; }
.dse-gruppe { margin:0 0 2.2rem; }
.dse-gruppe > h2 { padding-bottom:.35rem; border-bottom:1px solid var(--rand); }

.dse-verarbeitung { margin:0 0 1.5rem; }

/* Nur die Ueberschrift einer Verarbeitung traegt den Akzentstrich. Die
   Zwischenueberschriften im Typabschnitt (.dse-typ) sind Rahmentext -
   mit demselben Strich liesse sich ein Rahmenkapitel als Verarbeitung
   lesen. */
.dse-verarbeitung > h3 { padding-left:.7rem; border-left:3px solid var(--akzent); }

/* --------------------------------------------------------------------
   Die Angaben je Verarbeitung (.dse-angaben)

   Die Zeilenkoepfe sind hier keine Spaltenetiketten, sondern Woerter im
   Text ("Wie lange wir speichern"). Sie stehen deshalb in normaler
   Schreibweise: Die Versalien des Grundstils machten aus einer Angabe
   eine Rubrik - und aus dem Rechtstext eine Maske.
   -------------------------------------------------------------------- */
.dse-angaben { margin:0; font-size:1rem; }
.dse-angaben th[scope="row"] {
    width:12rem; padding:.55rem .9rem .55rem 0; vertical-align:top;
    font-size:.95rem; font-weight:650; letter-spacing:0; text-transform:none;
    color:var(--tinte-2);
    /* Gleiche Linienstaerke wie die Datenzelle daneben - zwei Staerken in
       einer Zeile lesen sich wie eine kaputte Tabelle. */
    border-bottom:1px solid var(--rand-weich);
}
.dse-angaben td { padding:.55rem 0; }

/* --------------------------------------------------------------------
   Luecken (AP-G07)

   Die Lueckenliste steht IM Wortlaut, nicht daneben. Sie ist der
   Unterschied zwischen einem Vorschlag und einer Datenschutzerklaerung
   und muss das Erste sein, was auffaellt. Die Aussage selbst ist Text -
   "Dieser Entwurf ist noch nicht vollstaendig"; Rahmen und Farbe
   wiederholen sie nur (WCAG 1.4.1).
   -------------------------------------------------------------------- */
.dse-lueckenliste {
    margin:0 0 2rem; padding:1.1rem 1.3rem; border-radius:0 5px 5px 0;
    border:1px solid var(--warn); border-left-width:4px;
    background:color-mix(in srgb, var(--warn) 6%, transparent);
}
.dse-lueckenliste > h2 { color:var(--warn); }
.dse-luecken { margin:1rem 0 0; font-size:.9rem; }

/* Erste Spalte ist das Normzitat - der Einstieg beim Nacharbeiten. */
.dse-luecke-zeile td:first-child { color:var(--warn); font-weight:650; }

/* Inline im Wortlaut. Der Text beginnt mit "Offen"; die Einfaerbung
   macht die Stelle auffindbar, traegt die Aussage aber nicht allein. */
.dse-luecke {
    padding:.05rem .3rem; border-radius:3px;
    color:var(--warn); font-weight:600;
    background:color-mix(in srgb, var(--warn) 8%, transparent);
    -webkit-box-decoration-break:clone; box-decoration-break:clone;
}

/* --------------------------------------------------------------------
   Die Vorschau im Backoffice (.dse-vorschau)

   Der eingefrorene Wortlaut, so wie er gehasht wurde. Er bekommt eine
   eigene Flaeche, weil er nicht Teil der Maske ist, sondern ihr
   Gegenstand.
   -------------------------------------------------------------------- */
.dse-vorschau {
    margin:1rem 0 2rem; padding:1.8rem 2rem;
    background:var(--flaeche); border:1px solid var(--rand); border-radius:6px;
}

/* Ein Vorschlag darf nicht wie eine geltende Fassung aussehen. Die
   Aussage tragen die Worte - p.warnung ueber der Vorschau und die
   Lueckenliste im Wortlaut; der Rahmen macht sie nur aus der Entfernung
   sichtbar. Eine lueckenlose Fassung, die trotzdem Vorschlag ist,
   erreicht diese Regel nicht - dafuer fehlt der Vorlage die Klasse. */
.dse-vorschau:has(.dse-lueckenliste) {
    border-color:var(--warn); border-top-width:4px;
}

/* --------------------------------------------------------------------
   Das Fragment zum Einbetten (.dse-einbettung)

   Es wird zum Kopieren gezeigt: dicktengleiche Schrift, umbruchfaehig an
   jeder Stelle - Pruefsummen und Adressen haben keine Leerzeichen - und
   auswaehlbar. Die Route liefert es heute als text/plain aus; dort
   erreicht es kein Stilblatt. Die Regeln greifen, sobald es in einer
   Seite steht.
   -------------------------------------------------------------------- */
.dse-einbettung {
    padding:1rem 1.2rem; border-radius:5px;
    background:var(--flaeche-2); border:1px solid var(--rand);
    font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
    font-size:.88rem; line-height:1.6;
    overflow-wrap:anywhere;
    -webkit-user-select:text; user-select:text;
}

/* Steht im Fragment selbst und geht damit auf die Mandantenwebsite: Dort
   gibt es diese Variablen nicht, und die Farbe faellt aus. Die Aussage
   traegt deshalb der fette Satz davor ("Diese Fassung ist
   zurueckgezogen."), nicht der Streifen. */
.dse-hinweis {
    margin:0 0 1.2rem; padding:.6rem .9rem; font-size:.95rem;
    border-left:3px solid var(--hinweis);
    background:color-mix(in srgb, var(--hinweis) 8%, transparent);
}

.dse-fassungsvermerk {
    margin:1.5rem 0 0; padding-top:.6rem;
    border-top:1px solid var(--rand-weich);
    color:var(--tinte-2); font-size:.85rem; overflow-wrap:anywhere;
}

/* --------------------------------------------------------------------
   Erzeugen je Erklaerungstyp (.dse-typen)

   Die nationalen Normen stehen NEBEN dem Knopf und nicht darunter: Sie
   sagen, was dieser Knopf erzeugt.
   -------------------------------------------------------------------- */
.dse-typen { margin:0 0 1.5rem; padding:0; list-style:none; display:grid; gap:.4rem; }
.dse-typen form { display:flex; flex-wrap:wrap; align-items:center; gap:.7rem; }

/* --------------------------------------------------------------------
   Fachliche Durchsicht

   Vier Zustaende. In jeder Legende steht das Wort dazu ("- bestaetigt",
   "- veraltet"), die Farbe kommt hinzu und traegt nichts allein
   (WCAG 1.4.1). "Veraltet" ist der gefaehrliche Zustand: Es gibt einen
   Vermerk, aber er gilt einem Wortlaut, der sich seither geaendert hat -
   er steht deshalb in der Warnfarbe und auf getoenter Flaeche.

   [class^="durchsicht-"] trifft genau die vier Zustandsklassen; die
   Klasse wird in der Vorlage aus p.zustand gebildet.
   -------------------------------------------------------------------- */
.durchsicht-offen, .durchsicht-veraltet,
.durchsicht-bestaetigt, .durchsicht-zu_aendern {
    margin:0 0 1.5rem; padding:1rem 1.2rem 1.2rem; border-radius:0 5px 5px 0;
    border:1px solid var(--rand); border-left-width:4px;
    background:var(--flaeche);
}
.durchsicht-offen { border-left-color:var(--tinte-3); }
.durchsicht-veraltet {
    border-left-color:var(--warn);
    background:color-mix(in srgb, var(--warn) 6%, transparent);
}
.durchsicht-zu_aendern { border-left-color:var(--hinweis); }
.durchsicht-bestaetigt { border-left-color:var(--gut); background:var(--flaeche-2); }

fieldset[class^="durchsicht-"] > legend {
    padding:0 .4rem; font-size:.95rem; font-weight:650;
}
.durchsicht-offen > legend { color:var(--tinte-2); }
.durchsicht-veraltet > legend { color:var(--warn); }
.durchsicht-zu_aendern > legend { color:var(--hinweis); }
.durchsicht-bestaetigt > legend { color:var(--gut); }

fieldset[class^="durchsicht-"] table { margin-bottom:1rem; }

/* size="80" sprengt sonst die Spalte auf schmalen Geraeten. */
fieldset[class^="durchsicht-"] input[type="text"] { max-width:100%; }

/* Feldpfad und Belegstelle sind Zitate aus dem Quelltext: Sie muessen
   sich von der Prosa daneben unterscheiden, sonst prueft man das
   falsche. */
.hilfe code,
fieldset[class^="durchsicht-"] code {
    padding:.05rem .3rem; border-radius:3px;
    background:var(--flaeche-2); border:1px solid var(--rand-weich);
    font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
    font-size:.9em; overflow-wrap:anywhere;
}

/* === Dokumente, Nachweis, Fristen, Einstellungen ===
   Vorlagen unter templates/backoffice/{dokument,datei,av,pruefung,zugriff,
   migration,loeschung,aufbewahrung,einstellungen,frist,inhalt,vorgang}/.

   Leitgedanke dieser Familie: Fast alles hier ist Beleg. Ein Hash, eine
   Kennung, eine Fassungsnummer wird nicht gelesen, sondern abgetippt oder
   verglichen - und eine Tabelle, in der ein SHA-256 die Spalte sprengt, wird
   im Pruefzeitpunkt nicht benutzt.

   Ergaenzt app.css, ueberschreibt nichts daraus. Wo app.css eine Klasse schon
   fuehrt (.knopf-klein, p.fehler, p.hinweis), kommt hier nur dazu, was dort
   nicht gesetzt ist.
   -------------------------------------------------------------------- */

/* Der Monatsauszug traegt seinen SHA-256 in einer .klein-Zelle. Klein ja,
   aber nicht kleiner: Er wird Zeichen fuer Zeichen verglichen. */
.klein code { font-size:.86rem; }

/* Maskiert wird im Server (AP-E30). Diese Regel versteckt nichts - sie macht
   nur den Platzhalter als solchen kenntlich. */
.maskiert { margin:0 0 .3rem; }
.maskiert code { color:var(--tinte-2); letter-spacing:.08em; }
span.unterzeile { display:inline; margin:0; }
small.hilfe, span.hilfe { display:block; margin-top:.25rem; line-height:1.45; }
caption.nr { text-align:left; padding:0 0 .5rem; }
span.klein { display:block; margin-top:.25rem; }

/* "Vorschau - kein Nachweis" in dokument/liste und "N Tage ueberschritten" in
   der Fristenliste sind dieselbe Aussage in zwei Spalten: Was hier steht,
   traegt im Streitfall nicht. */
td.warnung { color:var(--warn); }
td.fehler  { color:var(--warn); font-weight:650;
    background:color-mix(in srgb, var(--warn) 7%, transparent); }
div.hinweis > :first-child { margin-top:0; }
div.hinweis > :last-child  { margin-bottom:0; }
div.hinweis ul { margin:.5rem 0; padding-left:1.2rem; }
div.hinweis li { margin:.25rem 0; }

.vorschlag .marke {
    display:inline-block; margin:0 0 .5rem; padding:.05rem .4rem;
    font-size:.72rem; letter-spacing:.04em; text-transform:uppercase;
    color:var(--tinte-2); border:1px solid var(--rand); border-radius:3px;
}


/* --------------------------------------------------------------------
   Pruefansicht einer Meldung (AP-F15)

   Links der Wortlaut des Mandanten, rechts die Arbeit. Der Unterschied ist
   nicht Zierde: Links steht Nachweis und kein Eingabefeld, und die ruhige
   Flaeche sagt das, bevor jemand hineinzuklicken versucht.
   -------------------------------------------------------------------- */
.zweispaltig { display:grid; grid-template-columns:1fr; gap:1.5rem;
    align-items:start; }
@media (min-width:56rem) {
    .zweispaltig { grid-template-columns:minmax(0,1fr) minmax(0,1fr); }
}
.spalte { min-width:0; }

.spalte--original {
    padding:1rem 1.1rem; background:var(--flaeche-2);
    border:1px solid var(--rand-weich); border-radius:5px;
}
.spalte--original > :first-child { margin-top:0; }
.spalte--original > :last-child  { margin-bottom:0; }

.antworten { margin:0; }
.antworten dt { margin-top:.85rem; font-size:.78rem; letter-spacing:.05em;
    text-transform:uppercase; color:var(--tinte-2); }
.antworten dt:first-child { margin-top:0; }
.antworten dd { margin:.15rem 0 0; overflow-wrap:break-word; }

.rueckfrage { margin:0 0 1.25rem; background:var(--flaeche);
    border:1px solid var(--rand); border-radius:5px; }
.rueckfrage > summary { padding:.55rem .8rem; font-size:.92rem;
    font-weight:600; cursor:pointer; }
.rueckfrage[open] > summary { border-bottom:1px solid var(--rand-weich); }
/* Nur seitlicher Einzug: Den senkrechten Abstand bringt .formular-schmal aus
   app.css bereits mit, und der wird hier nicht ueberschrieben. */
.rueckfrage > form { padding:0 .8rem; }

.vorschlag {
    margin:0 0 1rem; padding:.9rem 1.1rem;
    background:var(--flaeche); border:1px solid var(--rand); border-radius:5px;
}
.vorschlag > :first-child { margin-top:0; }
.vorschlag > :last-child  { margin-bottom:0; }
.vorschlag h3 { margin:0 0 .35rem; font-size:1rem; }

/* Der Normbezug ist der Grund, aus dem der Vorschlag folgt. Er steht abgesetzt
   und nicht im Fliesstext der Begruendung - der Berater verantwortet ihn und
   muss dafuer sehen, woraus er sich ergibt. */
.vorschlag .norm {
    margin:.5rem 0 0; padding-left:.6rem;
    border-left:2px solid var(--akzent);
    color:var(--tinte-2); font-size:.86rem;
}

/* Der einzige der neun Typen, den die Sammeluebernahme nicht mitnimmt
   (ADR 0038, UebernahmeDienst::NICHT_SAMMELBAR): eine Rechtsfrage, die
   einzeln zu entscheiden ist. Der Rand ist die Zugabe - die Typbezeichnung
   steht als Wort in der .marke darueber. */
.vorschlag--pflichtpruefung { border-left:3px solid var(--hinweis); }
@media (min-width:34rem) {
    .angaben { grid-template-columns:minmax(0,max-content) minmax(0,1fr); }
}
.angaben dt { color:var(--tinte-2); font-size:.88rem; }
.angaben dd { margin:0; overflow-wrap:break-word; }


/* --------------------------------------------------------------------
   Listen mit Zeilenzustand
   -------------------------------------------------------------------- */
table.liste tbody tr:hover { background:var(--flaeche-2); }

/* Sofort-Prioritaet in der Meldungsliste. Zusaetzlich zur Faerbung ein Balken
   an der ersten Zelle, damit die Zeile nicht allein an der Farbe haengt
   (WCAG 1.4.1) - inset, damit sie nicht verspringt. Das WORT "sofort" liefert
   die Vorlage nicht; siehe Anmerkung. */
tr.zeile--offen td { background:color-mix(in srgb, var(--warn) 6%, transparent); }
tr.zeile--offen td:first-child { box-shadow:inset 3px 0 0 var(--warn);
    font-weight:650; }

/* Erfassungsstand der 57 Mandanten. Die letzte Spalte nennt den Zustand als
   Wort; die Faerbung ist die Zugabe fuer den Blick ueber die ganze Liste.
   "offen" bleibt ungefaerbt - es ist der Ausgangszustand und kein Befund. */
tr.zustand-bestaetigt td { background:color-mix(in srgb, var(--gut) 5%, transparent); }
tr.zustand-begonnen td   { background:color-mix(in srgb, var(--hinweis) 6%, transparent); }


/* --------------------------------------------------------------------
   Fortschritt der Stammdatenerfassung (AP-D09)

   Der Balken ist role="img" mit Beschriftung, und die Zahlen stehen im Satz
   darueber. Er ist damit Zugabe und nicht Traeger der Aussage.
   -------------------------------------------------------------------- */
.fortschritt { margin:0 0 1.5rem; }
.fortschrittsbalken {
    display:flex; height:.6rem; overflow:hidden;
    background:var(--rand-weich); border-radius:3px;
}
.balken-bestaetigt { background:var(--gut); }
.balken-begonnen   { background:var(--hinweis); }


/* --------------------------------------------------------------------
   Namensvorschlag und Kandidaten (AP-D09)
   -------------------------------------------------------------------- */
.kandidaten { display:grid; gap:.3rem; margin:.4rem 0 0; padding:0;
    list-style:none; }
.kandidaten li { display:flex; flex-wrap:wrap; align-items:baseline; gap:.5rem; }

/* Der Kandidat traegt nichts ein, er schlaegt vor - er sieht deshalb aus wie
   eine Schaltflaeche und nicht wie ein bereits gefuelltes Feld. */
button.kandidat {
    padding:.2rem .55rem; font:inherit; font-size:.92rem; text-align:left;
    color:var(--akzent); background:var(--flaeche);
    border:1px solid var(--rand); border-radius:4px; cursor:pointer;
}
button.kandidat:hover { background:var(--akzent-weich); }


/* --------------------------------------------------------------------
   Anhaenge, Einstellungen, Aufbewahrung
   -------------------------------------------------------------------- */
.anhaenge { margin:1.5rem 0; padding-top:1rem;
    border-top:1px solid var(--rand); }
.anhaenge h3 { margin:0 0 .6rem; font-size:1rem; }

.versandstand {
    margin:0 0 1.5rem; padding:1rem 1.1rem; background:var(--flaeche);
    border:1px solid var(--rand); border-radius:5px;
}
.versandstand > :first-child { margin-top:0; }
.versandstand > :last-child  { margin-bottom:0; }

.einstellungsgruppe { background:var(--flaeche); }

.einstellungsgruppe .feld { display:grid; gap:.25rem; margin:0 0 .9rem; max-width:34rem; }
.einstellungsgruppe .feld > label { font-size:.85rem; font-weight:600; }

/* Eine fehlende Pflichtangabe ist kein Fehler, sondern eine offene Stelle:
   Sie faellt am Rand auf und behaelt daneben den Stern im Label - die Farbe
   traegt die Aussage nicht allein (WCAG 1.4.1). */
.feld--fehlt { padding-left:.7rem; border-left:3px solid var(--hinweis); }
.pflicht { margin-left:.15rem; color:var(--warn); }

.hinweisliste { margin:0 0 1.5rem; padding:0; max-width:52rem;
    list-style:none; }
.hinweisliste li { margin:0 0 .7rem; padding-left:.9rem;
    border-left:2px solid var(--rand-weich); color:var(--tinte-2); }
.hinweisliste strong { color:var(--tinte); }


/* --------------------------------------------------------------------
   Schaltflaechen

   Groesse und Innenabstand von .knopf-klein setzt app.css; hier kommt nur das
   Aussehen dazu. Noetig, weil in derselben Tabellenzelle ein <a> ("Verlauf")
   und ein <button> ("Erledigt") nebeneinanderstehen und beide gleich aussehen
   muessen.
   -------------------------------------------------------------------- */
a.knopf-klein {
    display:inline-block; text-decoration:none; color:var(--akzent);
    background:var(--flaeche); border:1px solid var(--rand); border-radius:4px;
}
a.knopf-klein:hover { background:var(--akzent-weich); }

/* Der <button> daneben wird auf dieselbe ruhige Form zurueckgenommen - beides
   sind Nebenhandlungen in einer Tabellenzelle, keine Absendeknoepfe. */
button.knopf-klein { color:var(--akzent); background:var(--flaeche);
    border-color:var(--rand); }
button.knopf-klein:hover { background:var(--akzent-weich);
    border-color:var(--rand); }

/* Genau ein Absendeknopf je Stammdatenmaske (AP-D09) - er darf aussehen wie
   die Handlung, um die es geht. */
.haupt { padding:.6rem 1.1rem; font-size:1rem; font-weight:600; }
input::placeholder, textarea::placeholder { color:var(--tinte-2); }

label > input[type=checkbox] { margin-right:.4rem; }
form > label   { margin-bottom:.7rem; }
form p > label { font-size:.88rem; font-weight:600; }

a.knopf-klein, button, button.kandidat { transition:background-color .12s ease-out; }
@media (prefers-reduced-motion: reduce) {
    a.knopf-klein, button, button.kandidat { transition:none; }
}
/* === Anfragen, Vorfaelle, Beratung, Mandanten, Personen ===
   Betroffenenanfragen (Art. 15-22), Datenpannen (Art. 33/34), Beratungslog,
   Mandantenstammdaten, Portalzugaenge, Vertretungsregel.

   Zwei Gestaltungsentscheidungen ziehen sich durch diesen Abschnitt:

   1. Jede Flaeche, die Daten der Kunden, Mitarbeiter oder Patienten eines
      Mandanten zeigt, bekommt eine sichtbare Umrandung. Wer bei einer
      Bildschirmuebergabe scrollt, soll sehen, wo die Akte anfaengt und wo sie
      aufhoert.
   2. Wo eine Farbe einen Zustand meint, steht der Zustand bereits als Wort in
      der Vorlage ("erfuellt", "offen", "Vollzogen am", "nicht erhoben"). Die
      Farbe verstaerkt, sie traegt nicht (WCAG 1.4.1). Wo die Vorlage kein Wort
      liefert, bleibt die Farbe hier weg.

   Nichts in diesem Abschnitt bewegt sich, deshalb gibt es keinen Block fuer
   prefers-reduced-motion. */

p.klein { margin:.6rem 0 1rem; max-width:52rem; }

/* --------------------------------------------------------------------
   Meldungen und Hinweisbloecke

   app.css kennt p.fehler / p.erfolg / p.hinweis. Diese Familie schreibt
   dieselbe Aussage an zwei Stellen anders: als p.meldung mit Modifikator
   (portal/checkliste, vertretung/erfassen) und als div.hinweis mit mehreren
   Absaetzen. Ein Elementselektor p.hinweis trifft ein <div> nicht - deshalb
   hier die Ergaenzung, nicht die Neufassung.
   -------------------------------------------------------------------- */
p.meldung {
    margin:0 0 1rem; padding:.6rem .8rem; border-radius:4px;
    border-left:3px solid currentColor; font-size:.95rem;
    color:var(--tinte-2); background:var(--flaeche-2);
}
p.meldung--erfolg { color:var(--gut);  background:color-mix(in srgb, var(--gut) 7%, transparent); }
p.meldung--fehler { color:var(--warn); background:color-mix(in srgb, var(--warn) 7%, transparent); }
div.hinweis p { margin:0 0 .6rem; }
div.hinweis p:last-child { margin:0; }

/* Doppelte Klasse, damit der Modifikator gegen p.hinweis aus app.css gewinnt -
   ohne dessen Regel anzufassen. */
.hinweis.hinweis--warnung { color:var(--warn); background:color-mix(in srgb, var(--warn) 7%, transparent); }
.hinweis.hinweis--gut     { color:var(--gut);  background:color-mix(in srgb, var(--gut) 7%, transparent); }

/* In den Hinweisen stehen Konsolenaufrufe (portal/rollout, vertretung). */
.hinweis code {
    font-family:ui-monospace,SFMono-Regular,Menlo,monospace; color:var(--tinte); font-size:.88em;
    padding:.05rem .3rem; border-radius:3px;
    background:color-mix(in srgb, var(--tinte) 8%, transparent);
}
td .marke--ok {
    color:var(--gut); border-color:var(--gut);
    background:color-mix(in srgb, var(--gut) 8%, transparent);
}
td .marke--offen {
    color:var(--warn); border-color:var(--warn);
    background:color-mix(in srgb, var(--warn) 8%, transparent);
}

table.liste { margin:.5rem 0 1.5rem; }
table.liste td small { font-size:.82rem; color:var(--tinte-2); }

/* Ergaenzung zu .formular-schmal aus app.css: den Pruefvermerk nach
   Paragraf 96a ArbVG in portal/checkliste umschliesst ein fieldset. */
.formular-schmal fieldset {
    display:grid; gap:.35rem; margin:.9rem 0 .4rem;
    padding:.5rem .9rem .9rem; border:1px solid var(--rand); border-radius:5px;
}
.formular-schmal legend {
    padding:0 .35rem; font-size:.78rem; letter-spacing:.05em;
    text-transform:uppercase; color:var(--tinte-2);
}

/* --------------------------------------------------------------------
   Beratungseintrag (backoffice/beratung/_eintrag.html.twig)

   Der Eintrag ist eine Karte mit Rand, weil im Feld "Sachverhalt" Angaben
   ueber Beschaeftigte und Kunden des Mandanten stehen - beim internen Eintrag
   zusaetzlich die Beschreibung eines Hinweisgebers. Der Rand sagt, wo dieser
   Bestand endet.

   Der Nachtrag ist eingerueckt und traegt eine Akzentkante: Er gehoert zu
   einem frueheren Eintrag, ersetzt ihn aber nicht. Die Zuordnung steht
   zusaetzlich im Text ("Nachtrag vom ... zum Eintrag vom ...").
   -------------------------------------------------------------------- */
article.beratungseintrag {
    margin:0 0 1rem; padding:1rem 1.2rem;
    background:var(--flaeche); border:1px solid var(--rand); border-radius:6px;
}
article.beratungseintrag.nachtrag {
    margin-left:1.75rem; background:var(--flaeche-2);
    border-left:3px solid var(--akzent);
}
.beratungseintrag header h3 { margin:0 0 .25rem; font-size:1.02rem; }
.beratungseintrag header h3 .nr { font-weight:400; }
.beratungseintrag header .unterzeile { margin:0 0 .3rem; }
.beratungseintrag header .nr { margin:0; }

.beratungseintrag dl {
    display:grid; grid-template-columns:11rem 1fr; gap:.4rem .9rem;
    margin:.9rem 0 0; padding:.8rem 0 0; border-top:1px solid var(--rand-weich);
}
.beratungseintrag dt {
    font-size:.78rem; letter-spacing:.05em; text-transform:uppercase;
    color:var(--tinte-2);
}
.beratungseintrag dd { margin:0; }

.beratungseintrag form {
    display:flex; flex-wrap:wrap; align-items:end; gap:.9rem;
    margin:1rem 0 0; padding:.9rem 0 0; border-top:1px solid var(--rand-weich);
}
.beratungseintrag form label {
    display:grid; gap:.2rem; font-size:.82rem; color:var(--tinte-2);
}
.beratungseintrag form input[type=text] { min-width:20rem; }

/* --------------------------------------------------------------------
   Mandatsende (backoffice/mandant/offboarding.html.twig)

   Die Leiter zeigt zehn Jahre auf einen Blick. Vollzogene und offene Stufe
   unterscheiden sich am Rand der Ziffer (durchgezogen gegen gestrichelt) und
   nicht nur an der Farbe; der Zustand steht ausserdem als Satz darunter
   ("Vollzogen am ..." / "Offen.").
   -------------------------------------------------------------------- */
section.offboarding {
    margin:1rem 0 1.5rem; padding:1.2rem 1.4rem;
    background:var(--flaeche); border:1px solid var(--rand); border-radius:6px;
}
section.offboarding > h2 { margin:0 0 .8rem; font-size:1.1rem; }

ol.stufenleiter { list-style:none; margin:1.2rem 0; padding:0; }

li.stufe {
    position:relative; display:grid; grid-template-columns:2rem 1fr;
    gap:.9rem; padding:0 0 1.3rem;
}
li.stufe:last-child { padding-bottom:0; }

/* Die Linie zwischen den Ziffern macht aus Einzelpunkten eine Reihenfolge. */
li.stufe:not(:last-child)::before {
    content:""; position:absolute; left:1rem; top:2.2rem; bottom:.2rem;
    width:1px; background:var(--rand);
}

.stufe__nummer {
    position:relative; z-index:1;
    display:grid; place-items:center; width:2rem; height:2rem;
    font-size:.85rem; font-weight:650;
    color:var(--tinte-2); background:var(--flaeche);
    border:1px solid var(--rand); border-radius:50%;
}
.stufe--vollzogen .stufe__nummer {
    color:var(--gut); border-color:var(--gut);
    background:color-mix(in srgb, var(--gut) 12%, transparent);
}
.stufe--offen .stufe__nummer { border-style:dashed; color:var(--tinte-2); }

.stufe__inhalt h3 { margin:.2rem 0 .3rem; font-size:1rem; }
.stufe--offen .stufe__inhalt h3 { color:var(--tinte-2); }

.stufe__stand { margin:0; font-size:.92rem; }
.stufe__bemerkung { margin:.25rem 0 0; font-size:.92rem; color:var(--tinte-2); }
.stufe__bedingung { margin:.25rem 0 0; font-size:.92rem; color:var(--hinweis); }

/* Die Grundlage steht klein unter jeder Stufe - sie wird gelesen, wenn gefragt
   wird, worauf sich der Schritt stuetzt, nicht beim Ueberfliegen. */
.stufe__grundlage { margin:.35rem 0 0; font-size:.82rem; color:var(--tinte-2); }

.offboarding__naechste {
    margin:1rem 0 0; padding:.6rem .8rem; font-size:.95rem;
    background:var(--flaeche-2); border-left:3px solid var(--akzent);
    border-radius:0 4px 4px 0;
}

/* --------------------------------------------------------------------
   Ansprechpartner (backoffice/mandant/_ansprechpartner.html.twig)

   Fragment ohne eigenes Layout, per HTMX nachgeladen. Der Rand ist noetig,
   damit die Namensliste nicht in die umgebende Mandantenmaske ausfranst - und
   weil hier Namen, Funktionen und Rufnummern natuerlicher Personen stehen.
   -------------------------------------------------------------------- */
section.ansprechpartner {
    margin:1rem 0; padding:1rem 1.2rem;
    background:var(--flaeche); border:1px solid var(--rand); border-radius:6px;
}
section.ansprechpartner > h3 { margin:0 0 .6rem; font-size:1rem; }

/* --------------------------------------------------------------------
   Vertretungsregel (backoffice/vertretung/erfassen.html.twig)

   Je Rechtstraeger ein eigenes Formular, deshalb je Rechtstraeger eine eigene
   Karte: Zwei untereinander stehende Formulare ohne Rand sehen aus wie eines,
   und dann wird die Angabe des zweiten Traegers am ersten gespeichert.
   -------------------------------------------------------------------- */
form.vertretung {
    display:grid; gap:.3rem; max-width:46rem; margin:0 0 1.2rem;
    padding:1.1rem 1.3rem;
    background:var(--flaeche); border:1px solid var(--rand); border-radius:6px;
}
form.vertretung h2 { margin:0 0 .3rem; font-size:1.05rem; }
form.vertretung h2 small {
    margin-left:.5rem; font-size:.82rem; font-weight:400; color:var(--tinte-2);
}
form.vertretung label { margin-top:.6rem; font-size:.85rem; font-weight:600; }
form.vertretung button { justify-self:start; margin-top:1rem; }

p.stand {
    margin:0 0 .4rem; padding:.4rem .7rem; font-size:.92rem;
    background:var(--flaeche-2); border-left:3px solid var(--rand);
    border-radius:0 4px 4px 0;
}

/* Ein <strong> steht in dieser Zeile nur in den beiden Faellen, die die
   Freigabe blockieren oder unbelegt lassen: "nicht erhoben" und "ohne
   Abrufdatum". Beide sind ausgeschrieben - die Faerbung holt sie nur nach
   vorn. Ohne :has() bleibt die Zeile lesbar, nur ruhiger. */
p.stand:has(strong) {
    border-left-color:var(--warn);
    background:color-mix(in srgb, var(--warn) 6%, transparent);
}

/* --------------------------------------------------------------------
   Schmale Bildschirme

   Die Beschreibungsliste des Beratungseintrags und die Stufenleiter sind die
   einzigen zweispaltigen Gebilde dieser Familie. Unter 40rem wird aus beiden
   eine Spalte; die Tabellen bleiben, wie sie sind.
   -------------------------------------------------------------------- */
@media (max-width:40rem) {
    .beratungseintrag dl { grid-template-columns:1fr; gap:.15rem; }
    .beratungseintrag dd { margin:0 0 .5rem; }
    article.beratungseintrag.nachtrag { margin-left:.6rem; }
    li.stufe { grid-template-columns:1.6rem 1fr; gap:.6rem; }
    .stufe__nummer { width:1.6rem; height:1.6rem; font-size:.78rem; }
    li.stufe:not(:last-child)::before { left:.8rem; top:1.8rem; }
}

/* === Mandantenportal === templates/portal/ (16 Vorlagen) und
   templates/layout/portal.html.twig.

   Diese Masken sieht der MANDANT, nicht der Berater. Sie sind deshalb weiter
   gesetzt, groesser geschrieben und in abgegrenzte Bloecke geteilt, waehrend
   das Backoffice dicht und tabellarisch bleibt. Die Farbfamilie ist dieselbe -
   unterscheiden soll der Satzspiegel, nicht ein zweiter Farbkanon, sonst
   entstuenden zwei Themen, die getrennt gepflegt werden muessen.

   GRENZE DIESES ABSCHNITTS: layout/portal.html.twig traegt kein Kennzeichen -
   weder am <body> noch am <header class="kopf">. Kopfleiste, Grundschrift und
   Spaltenbreite lassen sich deshalb nicht portalseitig setzen, ohne das
   Backoffice mitzutreffen. Alles Folgende haengt an Klassen, die es nur im
   Portal gibt; die Breite tragen die Bloecke selbst (44-48rem Lesespalte).
   Siehe Anmerkungen. */

/* -- Zustandsbild (AP-F03) ----------------------------------------------- */

.zustandsbild {
    max-width:48rem; margin:0 0 1.5rem; padding:1.4rem 1.5rem;
    background:var(--flaeche); border:1px solid var(--rand); border-radius:8px;
}
.zustandsbild h2 { margin:0 0 .9rem; font-size:1.15rem; }

/* DIE STUFE BLEIBT ABSICHTLICH OHNE FARBABSTUFUNG.
   Die vier Werte kommen als .stufe--nicht_dokumentiert, --in_arbeit,
   --dokumentiert und --dokumentiert_und_freigegeben an. Sie rot/gelb/gruen zu
   faerben waere genau die Ampel, die AP-F03 ausschliesst und die
   tests/Golden/portal/sperrliste_scheingenauigkeit.txt bei jedem Lauf
   nachhaelt. Die Aussage traegt der ausgeschriebene Satz.
   Eingegrenzt auf .zustandsbild, weil .stufe im Backoffice-Offboarding eine
   andere Bedeutung hat. */
.zustandsbild .stufe {
    margin:0 0 1.1rem; padding:.7rem .9rem; font-size:1.05rem;
    background:var(--flaeche-2); border-left:3px solid var(--akzent);
    border-radius:0 4px 4px 0;
}

.zaehlwerte { list-style:none; margin:0; padding:0; }
.zaehlwerte li {
    padding:.4rem 0 .4rem .9rem; border-left:2px solid var(--rand-weich);
}

/* Der Vorbehalt ist die wichtigste Aussage der Seite und keine Fussnote: volle
   Schriftgroesse, eigener Block. Keine Warnfarbe - er meldet keinen Fehler,
   sondern begrenzt die Reichweite des Bildes. Backoffice benutzt dieselbe
   Klasse an einem <p>; die Regeln passen auf beides. */
div.vorbehalt {
    max-width:48rem; margin:2rem 0 0; padding:1.2rem 1.4rem;
    background:var(--flaeche-2);
    border:1px solid var(--rand); border-left:4px solid var(--akzent);
    border-radius:0 6px 6px 0;
}
div.vorbehalt h2 { margin:0 0 .6rem; font-size:1rem; }
div.vorbehalt p { margin:0 0 .8rem; }
div.vorbehalt p:last-child { margin-bottom:0; }

/* -- Freigegebene Fassung, Blaetter (AP-F04) ------------------------------ */

.blatt {
    max-width:48rem; margin:0 0 1.5rem; padding-top:1.2rem;
    border-top:1px solid var(--rand-weich);
}
.blatt h2 { margin:0 0 .7rem; font-size:1.1rem; }

/* Der Blattinhalt ist Klartext aus dem Snapshot: Er behaelt seine Zeilenform
   (pre-wrap), bricht aber innerhalb langer Zeichenketten um, damit er die
   Seite nicht aufzieht. Ein waagrechter Rollbalken auf Seitenebene wuerde die
   Kopfleiste mitverschieben. */
.blattinhalt {
    margin:0; padding:1rem;
    background:var(--flaeche-2); border:1px solid var(--rand-weich); border-radius:6px;
    font-family:ui-monospace,SFMono-Regular,Menlo,monospace;
    font-size:.9rem; line-height:1.55;
    white-space:pre-wrap; overflow-wrap:anywhere;
}

/* -- Etwas melden: Auswahl der Assistenten (AP-F12) ----------------------- */

/* Angefangenes zuerst und sichtbar abgesetzt. Steht es im selben Weiss wie die
   Neu-Liste, sucht der Mandant seinen unterbrochenen Lauf nicht dort, sondern
   faengt neu an. */
.angefangen {
    max-width:48rem; margin:0 0 2rem; padding:1rem 1.2rem;
    background:var(--akzent-weich); border-radius:6px;
}
.angefangen h2 { margin:0 0 .6rem; font-size:1rem; }

.liste-schlicht { list-style:none; margin:0; padding:0; }
.liste-schlicht li { padding:.45rem 0; }
.liste-schlicht li + li {
    border-top:1px solid color-mix(in srgb, var(--rand) 60%, transparent);
}
.liste-schlicht small { display:block; color:var(--tinte-2); font-size:.85rem; }

.assistentenliste { max-width:48rem; }
.assistentenliste h2 { margin:0 0 .7rem; font-size:1rem; }
.assistentenliste form { margin:0 0 .7rem; }

/* Ein Knopf in Kartenform: Hier waehlt der Mandant eine Aufgabe, keine
   Werkzeugleistenfunktion. Fragenzahl und Zeitangabe stehen mit im Knopf -
   "wie lange dauert das" muss vor dem Klick beantwortet sein, sonst wird
   nicht geklickt. */
.assistent-knopf {
    display:block; width:100%; text-align:left; cursor:pointer;
    padding:.9rem 1.1rem; font:inherit; color:inherit;
    background:var(--flaeche); border:1px solid var(--rand); border-radius:6px;
    transition:border-color 120ms ease, background-color 120ms ease;
}
.assistent-knopf:hover { border-color:var(--akzent); background:var(--flaeche-2); }
.assistent-knopf strong { display:block; font-size:1.05rem; }
.assistent-knopf small {
    display:block; margin-top:.2rem; color:var(--tinte-2); font-size:.88rem;
}

/* -- Assistentenrahmen (AP-F12) ------------------------------------------ */

.assistent { max-width:44rem; accent-color:var(--akzent); }

.assistent__kopf {
    margin:0 0 1.8rem; padding-bottom:1rem; border-bottom:1px solid var(--rand);
}
.assistent__kopf h1 { margin:0 0 .35rem; }

/* "Schritt 2 von 6", kein Balken und kein Prozentwert. Die Zeile ist eine
   Ortsangabe, keine Fortschrittsanzeige - sie steht deshalb klein und ruhig
   und nicht als Grafik. */
.assistent .fortschritt {
    margin:0; color:var(--tinte-2);
    font-size:.85rem; letter-spacing:.04em; text-transform:uppercase;
}

/* Eingegrenzt auf .assistent: .feld und .hilfe kommen im Backoffice mit
   anderer Bedeutung vor. */
.assistent .feld { margin:0 0 1.6rem; }
.assistent .feld > label { display:block; margin:0 0 .4rem; font-weight:600; }
.assistent .pflicht { color:var(--warn); }
.assistent .hilfe {
    display:block; margin-top:.4rem; color:var(--tinte-2); font-size:.88rem;
}

.assistent input[type=text],
.assistent input[type=date],
.assistent input[type=file],
.assistent textarea {
    width:100%; max-width:34rem; padding:.6rem .7rem; font:inherit;
    color:var(--tinte); background:var(--flaeche);
    border:1px solid var(--rand); border-radius:5px;
}
.assistent textarea { min-height:6.5rem; resize:vertical; }

/* Radiobuttons statt Auswahlliste, und die Beschriftung ist die ganze Zeile:
   Eine Antwort, die man aufklappen muss, um sie zu sehen, ist fuer den
   Antwortenden keine. */
.assistent .optionen { margin:0; padding:0; border:0; }
.assistent .optionen legend { padding:0; }
.assistent .option {
    display:flex; align-items:flex-start; gap:.6rem;
    padding:.6rem .75rem; cursor:pointer;
    background:var(--flaeche); border:1px solid var(--rand-weich); border-radius:5px;
    transition:border-color 120ms ease;
}
.assistent .option + .option { margin-top:.4rem; }
.assistent .option:hover { border-color:var(--rand); }
.assistent .option input { margin:.3rem 0 0; }

/* "Weiss ich nicht" ist eine gueltige Antwort und kein Fehler: abgesetzt,
   damit man sie findet, aber ohne Warnfarbe. Wer sie rot faerbt, erzieht zum
   Raten - und ein geratener Wert steht anschliessend im Verzeichnis. */
.assistent .option.option--unbekannt {
    margin-top:.8rem; border-style:dashed; color:var(--tinte-2);
}

.assistent__fuss {
    display:flex; flex-wrap:wrap; align-items:center; gap:1rem;
    margin-top:2rem; padding-top:1.2rem; border-top:1px solid var(--rand-weich);
}
/* "Spaeter fortsetzen" ans andere Ende: Es ist der Ausstieg, nicht die
   Zweitfassung des Weiter-Knopfes. */
.assistent__fuss .spaeter { margin-left:auto; }
.spaeter { color:var(--tinte-2); font-size:.92rem; }

/* Der Stand wechselt per aria-live, wenn der Stimulus-Controller gesichert
   hat. Feste Zeilenhoehe, damit der Text darunter beim Wechsel nicht springt. */
.sicherung {
    margin:1.2rem 0 0; min-height:1.6rem;
    color:var(--tinte-2); font-size:.85rem;
}

/* -- Zusammenfassung vor dem Absenden (AP-F12) --------------------------- */

/* Ganze Saetze, kein Formular - und darum groesser gesetzt als der uebrige
   Fliesstext. Das ist der letzte Text, den jemand vor dem Absenden liest. */
.zusammenfassung {
    max-width:44rem; margin:0 0 1.5rem; padding:1.3rem 1.5rem;
    background:var(--flaeche); border:1px solid var(--rand); border-radius:8px;
}
.zusammenfassung p { margin:0 0 .9rem; font-size:1.08rem; line-height:1.65; }
.zusammenfassung p:last-child { margin-bottom:0; }

/* Offen Gebliebenes erzeugt eine Rueckfrage, keinen Fehler: Hinweisfarbe,
   nicht Warnfarbe. Der entlastende Satz steht in der Vorlage darueber. */
section.offene-punkte {
    max-width:44rem; margin:0 0 1.5rem; padding:1rem 1.2rem;
    background:color-mix(in srgb, var(--hinweis) 8%, transparent);
    border-left:3px solid var(--hinweis); border-radius:0 6px 6px 0;
}
section.offene-punkte h2 { margin:0 0 .5rem; font-size:1rem; }
section.offene-punkte p { margin:0 0 .6rem; }
section.offene-punkte ul { margin:0; padding-left:1.2rem; }
section.offene-punkte li { margin:.3rem 0; }

/* -- Quartalsbestaetigung (AP-F06) --------------------------------------- */

/* Der Wortlaut steht auf der Seite, nicht hinter einem Link. Der Abschnitt
   rahmt ihn und gibt ihm Luft, damit er auch gelesen wird;
   blockquote.wortlaut selbst kommt aus app.css. */
.erklaerung { max-width:44rem; margin:1.5rem 0; }
.erklaerung h2 { margin:0 0 .7rem; font-size:1.05rem; }

/* -- Jahresfreigabe: was noch fehlt (AP-F05) ----------------------------- */

/* Die Liste ZEIGT AN, sie entscheidet nichts - die Sperre sitzt im Endpunkt.
   Erfuellt und offen unterscheiden sich in Randfarbe, Flaeche UND Wortlaut;
   der offene Punkt traegt zusaetzlich ein <strong> aus der Vorlage. Die Farbe
   allein traegt die Aussage damit nicht (WCAG 1.4.1). Ein Zeichen (Haken,
   Punkt) waere deutlicher, steht aber nicht im Markup - siehe Anmerkungen. */
.sperren { list-style:none; max-width:44rem; margin:0 0 2rem; padding:0; }
.sperren li { margin:0 0 .6rem; padding:.75rem .9rem; border-radius:0 5px 5px 0; }
.sperren .erfuellt {
    color:var(--tinte-2); background:var(--flaeche-2);
    border-left:3px solid var(--gut);
}
.sperren .offen {
    background:color-mix(in srgb, var(--hinweis) 8%, transparent);
    border-left:3px solid var(--hinweis);
}
.sperren .offen strong { display:block; margin-bottom:.25rem; }

/* Drei Wege, nicht einer: Freigabe, Freigabe mit Anmerkung, Ablehnung stehen
   gleichrangig untereinander. Die Textfelder sind volle Breite - das
   cols="60" der Vorlage waere auf einem Telefon breiter als der Bildschirm. */
.zeichnen { max-width:44rem; accent-color:var(--akzent); }
.zeichnen fieldset {
    margin:0 0 1.5rem; padding:1.2rem 1.4rem;
    background:var(--flaeche); border:1px solid var(--rand); border-radius:8px;
}
.zeichnen legend { padding:0 .4rem; font-weight:650; }
.zeichnen label { display:block; margin:.7rem 0 .3rem; }
.zeichnen textarea {
    width:100%; max-width:100%; margin:0 0 1rem; padding:.6rem .7rem; font:inherit;
    color:var(--tinte); background:var(--flaeche-2);
    border:1px solid var(--rand); border-radius:5px; resize:vertical;
}

/* Die einzigen Bewegungen dieses Abschnitts sind zwei Randfarbwechsel. */
@media (prefers-reduced-motion: reduce) {
    .assistent-knopf, .assistent .option { transition:none; }
}