/* Preventra — Designsystem.
 *
 * Anmutung: Microsoft 365 / SharePoint (Fluent 2). Ruhige neutrale Flächen, Akzent in den
 * Markenfarben (Lila, ADR 0048),
 * dünne Trennlinien statt Rahmen überall, weiche Schatten, 4-px-Radien, 14 px Grundschrift.
 * Leitgedanke ist Einfachheit: wenige Bausteine, klare Hierarchie, keine Effekte ohne Zweck.
 *
 * Hell ist die Vorgabe; dunkel wird über data-theme="dark" am <html>-Element gesetzt. Das
 * Attribut kommt serverseitig aus dem Cookie (siehe ThemePreference), damit beim Laden nichts
 * aufblitzt.
 *
 * Eine Datei, keine Framework-Abhängigkeit, keine externen Schriftarten: die CSP erlaubt keine
 * Fremd-Origins, und ein externer Font-Aufruf würde die IP des Nutzers an Dritte übertragen
 * (MANIFEST §2).
 *
 * Es gibt bewusst KEINE style="…"-Attribute im Markup: Nonces gelten nicht für Attribute, solche
 * Stile würde die CSP blockieren (MANIFEST §1.3). Alles läuft über Klassen aus dieser Datei.
 */

/* ── Schrift ────────────────────────────────────────────────────────────────────────────────────
 *
 * Die Hausschrift ist Google Sans Flex (Corporate Design, ADR 0048). Sie steht VORN im Stapel und
 * gilt damit auf jedem System gleich — Windows, macOS und Linux zeigen dieselbe Schrift, dieselbe
 * Laufweite, denselben Umbruch. Die Systemschriften dahinter greifen nur, solange die Datei lädt
 * (font-display: swap) oder wenn sie fehlt.
 *
 * EINE Datei statt drei Schnitte: Die Schrift ist variabel. Ausgeliefert wird eine Teilmenge —
 * Lateinisch mit Erweiterung A, Satzzeichen, Euro, Vergleichszeichen — mit den Achsen 'wght'
 * (300–700, mehr nutzt diese Datei nicht) und 'opsz' (die Browser wählen die optische Größe
 * selbst). Die übrigen Achsen (GRAD, ROND, slnt, wdth) sind auf ihren Vorgabewert festgelegt.
 * Das bringt 4 MB auf 120 KB. Wer ein Zeichen außerhalb der Teilmenge braucht, erzeugt die Datei
 * neu (Befehl in docs/design.md), statt eine zweite Schrift dazuzunehmen.
 *
 * KEIN Ω: Weder die Vorlage noch die Teilmenge hat eine Glyphe dafür. Der Browser setzt es aus
 * der Systemschrift — deshalb stehen die Systemschriften überhaupt im Stapel.
 *
 * Selbst gehostet (SIL OFL 1.1 ohne reservierten Schriftnamen, Lizenztext unter wwwroot/fonts/),
 * niemals per CDN: die CSP erlaubt keine Fremd-Origins, und ein externer Font-Aufruf würde die
 * IP-Adresse des Nutzers an Dritte übertragen (MANIFEST §2).
 */

@font-face {
    font-family: "Google Sans Flex";
    src: url("../fonts/google-sans-flex.woff2") format("woff2");
    font-weight: 300 700;
    font-style: normal;
    font-display: swap;
}

/* ── Farb- und Maßtoken ─────────────────────────────────────────────────────────────────────── */

:root {
    color-scheme: light;

    /* Neutrale Flächen */
    /* Ein Hauch Dunkel-Lila im Grau: wärmer und erkennbar Preventra, ohne lila zu sein. */
    --color-canvas: #f5f4f8;
    --color-surface: #ffffff;
    --color-surface-hover: #f7f6fa;
    --color-surface-pressed: #eeecf3;

    /* Linien.
       'stroke' ist dekorativ (Trennlinien, Tabellenzeilen) und darf zart sein.
       'stroke-accessible' umreißt Bedienelemente und muss 3,0:1 erreichen (WCAG 1.4.11) —
       Fluent nennt dieses Token NeutralStrokeAccessible. */
    --color-stroke: #e6e3ec;
    --color-stroke-strong: #c8c6c4;
    --color-stroke-accessible: #616161;

    /* Schrift */
    --color-text: #242424;
    --color-text-secondary: #4d4d4d;
    --color-text-disabled: #767676;

    /* Akzent — die Markenfarben (ADR 0048): Hell-Lila #6f01f5 und Dunkel-Lila #190333.
       #6f01f5 erreicht auf Weiß genau 7,0:1 und trägt Akzenttext und gefüllte Flächen
       unverändert; Hover und Druck dunkeln Richtung Dunkel-Lila ab. */
    --color-accent: #6f01f5;
    --color-accent-hover: #5c00cc;
    --color-accent-bg: #6f01f5;
    --color-accent-bg-hover: #5c00cc;
    --color-accent-bg-pressed: #190333;
    --color-on-accent: #ffffff;

    /* Grund unter QR-Codes: in BEIDEN Schemata weiß, deshalb nur hier und nicht im Dunkelblock.
       Ein QR-Code braucht dunkle Module auf hellem Grund, sonst liest ihn keine Kamera. */
    --color-qr-grund: #ffffff;

    /* Ausgewählt/hervorgehoben (Navigation, Abzeichen, Hinweise): neutral, nicht lila. Das Lila
       sitzt dort nur als Markierungsstrich daneben. Flächig eingesetzt wirkte es verspielt statt
       sachlich (Daniel, 2026-10-08) — die Markenfarbe trägt Schaltflächen, Logo und Fokus. */
    --color-accent-subtle: #ebe8f2;

    /* Zarte Tönung NUR als Grund kleiner Symbole (leerer Zustand, Kennzahlen) — nie für Flächen,
       Zeilen oder Abzeichen. Das bringt Farbe in die Seite, ohne sie lila zu machen. */
    --color-accent-tint: #f1ebfe;

    /* Wort-Bild-Marke (_Logo): Signet in Hell-Lila, Schrift fast schwarz wie in der Markendatei. */
    --color-marke-signet: #6f01f5;
    --color-marke-schrift: #1d1d1b;

    /* Markenfläche der Anmeldung (ADR 0053): Dunkel-Lila in BEIDEN Schemata — sie ist Marke, kein
       Arbeitsgrund. Deshalb nur hier und nicht im Dunkelblock. */
    --color-markenflaeche: #190333;
    --color-auf-markenflaeche: #ffffff;
    --color-auf-markenflaeche-neben: #d8cdf0;
    --color-markenflaeche-zeichen: #24094a;

    /* Nachrichtenblasen: die eigene in der zarten Markenfarbe, fremde in Grau. */
    --color-nachricht-eigen: #f1ebfe;
    --color-nachricht-fremd: #f2f0f6;

    /* Verweise: ein ruhiges, tiefes Indigo statt des leuchtenden Markenlilas. Es bleibt als
       Verweis erkennbar und erreicht auf jeder hellen Fläche AAA. */
    --color-link: #4b2a8a;
    --color-link-hover: #6f01f5;

    /* Statusfarben (Fluent MessageBar) */
    --color-danger: #a4262c;
    --color-danger-subtle: #fdf3f4;
    --color-warning: #7a4d05;
    --color-warning-subtle: #fff4ce;
    --color-success: #0e700e;
    --color-success-subtle: #f1faf1;
    --color-info: var(--color-link);
    --color-info-subtle: #f5f4f8;

    /* Dateiarten in der Ablage. Die Farbe ist Wiedererkennung, kein Bedeutungstraeger: Neben
       jedem Symbol steht der Dateiname mit seiner Endung (WCAG 1.4.1). Alle Werte erreichen
       gegen Arbeitsflaeche, Karte und Hoverflaeche mindestens 3:1 (WCAG 1.4.11) —
       nachgerechnet in scripts/pruefe-kontrast.py, nicht geschaetzt. */
    --color-datei-pdf: #b8232f;
    --color-datei-word: #185abd;
    --color-datei-excel: #0e6e35;
    --color-datei-powerpoint: #b7472a;
    --color-datei-bild: #7160a8;

    /* Erhebung */
    /* Weich und weit statt eng und grau, getönt mit dem Dunkel-Lila (25, 3, 51): Flächen
       schweben leicht, statt aufzuliegen. */
    --shadow-2: 0 1px 2px rgba(25, 3, 51, 0.04), 0 4px 16px rgba(25, 3, 51, 0.05);
    --shadow-4: 0 2px 4px rgba(25, 3, 51, 0.05), 0 8px 24px rgba(25, 3, 51, 0.08);
    --shadow-8: 0 4px 8px rgba(25, 3, 51, 0.06), 0 16px 40px rgba(25, 3, 51, 0.12);

    /* Radien */
    --radius-sm: 6px;
    --radius-md: 12px;
    --radius-lg: 16px;
    --radius-pill: 999px;

    /* Abstände */
    --space-xs: 4px;
    --space-s: 8px;
    --space-m: 12px;
    --space-l: 16px;
    --space-xl: 24px;
    --space-xxl: 32px;

    /* Maße */
    --topbar-height: 48px;
    --nav-width: 228px;
    --control-height: 36px;

    /* Reihenfolge und Begründung: siehe Abschnitt "Schrift" oben. */
    --font-family: "Google Sans Flex", "Segoe UI Variable Text", "Segoe UI", -apple-system,
        BlinkMacSystemFont, system-ui, "Helvetica Neue", Arial, sans-serif;
    --font-size-caption: 12px;
    --font-size-body: 14px;
    --font-size-subtitle: 16px;
    --font-size-section: 18px;
    --font-size-title: 20px;
    --font-size-display: 32px;
}

:root[data-theme="dark"] {
    color-scheme: dark;

    --color-canvas: #131216;
    --color-surface: #1e1c22;
    --color-surface-hover: #28262d;
    --color-surface-pressed: #322f38;

    --color-stroke: #333333;
    --color-stroke-strong: #494949;
    --color-stroke-accessible: #adadad;

    --color-text: #f5f5f5;
    --color-text-secondary: #c7c7c7;
    --color-text-disabled: #8f8f8f;

    /* Im Dunkelmodus muss der Akzent heller sein, damit der Kontrast auf dunkler Fläche
       ausreicht; Flächen mit Akzentfarbe bleiben dagegen dunkler als im Hellmodus. */
    --color-accent: #b38cff;
    --color-accent-hover: #c4a6ff;
    --color-accent-bg: #6f01f5;
    --color-accent-bg-hover: #5c00cc;
    --color-accent-bg-pressed: #190333;
    --color-on-accent: #ffffff;
    --color-accent-subtle: #2c2933;
    --color-accent-tint: #24113f;
    --color-marke-signet: #ffffff;
    --color-marke-schrift: #ffffff;
    --color-nachricht-eigen: #2a1648;
    --color-nachricht-fremd: #2a2830;
    --color-link: #c9b6f2;
    --color-link-hover: #e2d7fa;

    --color-danger: #ff9ea0;
    --color-danger-subtle: #3b1f21;
    --color-warning: #fdd8a5;
    --color-warning-subtle: #3a2c0f;
    --color-success: #9fd89f;
    --color-success-subtle: #10290f;
    --color-info: var(--color-link);
    --color-info-subtle: #26232c;

    /* Auf dunklem Grund muessen die Dateifarben heller werden — dieselbe Regel wie beim Akzent. */
    --color-datei-pdf: #f08a92;
    --color-datei-word: #7cb7f5;
    --color-datei-excel: #6ecf8e;
    --color-datei-powerpoint: #f39a7e;
    --color-datei-bild: #c3b0e8;

    /* Auf dunklem Grund brauchen Schatten mehr Deckkraft, um überhaupt sichtbar zu sein. */
    --shadow-2: 0 1px 2px rgba(0, 0, 0, 0.28), 0 0 2px rgba(0, 0, 0, 0.24);
    --shadow-4: 0 2px 4px rgba(0, 0, 0, 0.28), 0 0 2px rgba(0, 0, 0, 0.24);
    --shadow-8: 0 4px 8px rgba(0, 0, 0, 0.28), 0 0 2px rgba(0, 0, 0, 0.24);
}

/* ── Grundlagen ─────────────────────────────────────────────────────────────────────────────── */

*,
*::before,
*::after {
    box-sizing: border-box;
}

html {
    /* Verhindert, dass die Seite beim Wechsel zu einer scrollenden Ansicht springt. */
    scrollbar-gutter: stable;
}

body {
    margin: 0;
    font-family: var(--font-family);
    font-size: var(--font-size-body);
    line-height: 20px;
    color: var(--color-text);
    background: var(--color-canvas);

    /* Graustufen-Glättung auf macOS: ergibt feinere, gleichmäßigere Stämme als die
       Subpixel-Glättung und entspricht dem, was Microsoft 365 im Browser zeigt. */
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;

    /* Kein künstlicher Fett- oder Kursivschnitt. Fehlt ein Schnitt, rechnet der Browser ihn
       sonst hoch — das Ergebnis ist unscharf und ungleichmäßig. Die variable Hausschrift deckt
       300 bis 700 ab, also jeden Schnitt, den diese Datei verwendet. */
    font-synthesis: none;

    /* Kerning und Standardligaturen ausdrücklich an — bei Schriften, die sie mitbringen. */
    font-kerning: normal;
    font-variant-ligatures: common-ligatures;

    /* Verhindert, dass iOS beim Drehen die Schrift eigenmächtig vergrößert. */
    -webkit-text-size-adjust: 100%;
    text-size-adjust: 100%;
}

a {
    color: var(--color-link);
    text-decoration: none;
}

a:hover {
    color: var(--color-link-hover);
    text-decoration: underline;
}

/* Verweise innerhalb von Textblöcken tragen dauerhaft eine Unterstreichung: Farbe allein darf
   keine Bedeutung tragen (WCAG 1.4.1, Use of Color). In Navigation und Schaltflächen ist die Rolle
   durch Position und Form erkennbar, dort bleibt es ohne.

   Die Regel ist auf den Inhaltsbereich begrenzt, nicht bloß durch eine spätere Regel überschrieben:
   'li:not(.nav-item) > a:not(.button)' hat eine höhere Spezifität als '.sidebar a' und gewann
   deshalb auch dann, wenn danach 'text-decoration: none' stand — die Navigationspunkte waren
   unterstrichen. Eine strukturelle Eingrenzung ist verlässlicher als ein Wettlauf um Spezifität. */
/* Das ':not(.button)' gehört an JEDEN dieser Selektoren, nicht nur an den letzten. Eine
   Schaltfläche in einem Absatz — '<p><a class="button">…' — wurde sonst unterstrichen: Der
   Selektor '.content p a' ist spezifischer als '.button' und gewann. Dass danach irgendwo
   'text-decoration: none' steht, hilft nicht; Spezifität schlägt Reihenfolge. */
.content p a:not(.button),
.content .notice a:not(.button),
.content .lead a:not(.button),
/* ':not(.kalender-eintrag)': Ein Kalendereintrag ist ein Verweis mit Form — Akzentstrich,
   Fläche, ganzes Kästchen — wie eine Schaltfläche, nicht wie ein Wort im Fließtext. Drei
   unterstrichene Zeilen je Kästchen waren Lärm, keine Auszeichnung. */
.content li:not(.nav-item):not(.kalender-eintrag) > a:not(.button),
/* Vor der Anmeldung ist JEDER Verweis einer im Fliesstext — es gibt weder Navigation noch
   Werkzeugleiste, deren Form die Rolle schon zeigt. Die Regel war auf '.content' begrenzt, also
   auf die angemeldete Anwendung; '.schlicht-inhalt' war nie erfasst. Folge: Der Verweis
   "Zurueck zur Anmeldung" auf /passwort-vergessen war allein an seiner Farbe erkennbar — ein
   Verstoss gegen WCAG 1.4.1 an einer Stelle, an der ihn niemand suchte, weil es die Regel
   "im Fliesstext" ja gibt. ':not(.brand)' ist Vorsorge fuer den Fall, dass die Wortmarke je als
   Verweis hierher wandert. */
.schlicht-inhalt a:not(.button):not(.brand) {
    text-decoration: underline;
    text-underline-offset: 2px;
}

.sidebar a,
.brand,
.button {
    text-decoration: none;
}

:focus-visible {
    /* Zweifarbiger Ring wie in Fluent: innen dunkel/hell nach Textfarbe, außen die Fläche.
       Ein einfarbiger Ring wäre unsichtbar, sobald das Element selbst diese Farbe trägt —
       etwa ein Akzentring auf einer gefüllten Akzentschaltfläche (WCAG 2.4.11/2.4.13). */
    outline: 2px solid var(--color-text);
    outline-offset: 1px;
    box-shadow: 0 0 0 4px var(--color-canvas);
    border-radius: var(--radius-sm);
}

/* Sprungmarke, nur bei Tastaturfokus sichtbar. */
.skip-link {
    position: absolute;
    left: -9999px;
    z-index: 100;
}

.skip-link:focus {
    left: var(--space-s);
    top: var(--space-s);
    padding: var(--space-s) var(--space-m);
    background: var(--color-surface);
    color: var(--color-text);
    border-radius: var(--radius-sm);
    box-shadow: var(--shadow-8);
}

/* Für Screenreader vorhanden, visuell entfernt. */
.visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/*
 * Übergänge: Hover, Druck und Fokus wechseln in 120 ms statt hart umzuspringen. Kurz genug, dass
 * nichts wartet; lang genug, dass die Oberfläche nicht flackert. Nur Farben und Schatten, nie
 * Größe oder Lage — und bei 'prefers-reduced-motion' kürzt der Block am Dateiende jede Dauer.
 */
:where(a, .button, button, input, select, textarea, summary, tbody tr, .search-field, .badge) {
    transition:
        background-color 120ms ease,
        color 120ms ease,
        border-color 120ms ease,
        box-shadow 120ms ease;
}

/* ── Gerüst ─────────────────────────────────────────────────────────────────────────────────── */

.shell {
    display: grid;
    grid-template-columns: var(--nav-width) 1fr;
    grid-template-rows: var(--topbar-height) 1fr;
    grid-template-areas:
        "topbar topbar"
        "nav    main";
    min-height: 100vh;
}

/* ── Kopfzeile ──────────────────────────────────────────────────────────────────────────────── */

/*
 * Drei Spalten statt einer Reihe mit Abstandshaltern.
 *
 * Mit Abstandshaltern saß die Suche mittig *zwischen* Logo und rechter Seite — und weil rechts
 * Name, zwei Marken und drei Schaltflächen stehen, links aber nur das Logo, lag sie sichtbar
 * links von der Mitte. Zwei gleich große Abstandshalter teilen den *Rest* gleichmäßig auf, nicht
 * die Kopfzeile.
 *
 * 'minmax(0, 1fr)' statt '1fr': Damit dürfen die äußeren Spalten schmaler werden als ihr Inhalt.
 * Sonst wüchse die rechte Spalte über ihren Anteil hinaus, sobald der Name lang ist — und die
 * Mitte wäre wieder keine.
 */
.topbar {
    grid-area: topbar;
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
    align-items: center;
    gap: var(--space-m);
    padding: 0 var(--space-l);
    background: var(--color-canvas);
}

.brand {
    display: inline-flex;
    align-items: center;
    gap: var(--space-s);
    color: var(--color-text);
}

.brand:hover {
    color: var(--color-text);
    text-decoration: none;
}

/* Der Menüknopf steht rechts außen in der Kopfzeile und erscheint nur unter 801 px (Block
   „Schmale Fenster"). Mit '.topbar-actions' davor: '.button' steht weiter unten und setzte sonst
   'inline-flex'. */
.topbar-actions .nav-schalter {
    display: none;
}

.topbar-actions {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    justify-self: end;
    gap: var(--space-s);
    min-width: 0;
}

/* ── Konto-Menü ─────────────────────────────────────────────────────────────────────────────── */

/*
 * Als <details>/<summary>: Aufklappen kann der Browser selbst — ohne Skript, mit Tastatur und
 * mit Ansage durch Screenreader. Das Dreieck, das Browser vor <summary> setzen, ist hier falsch
 * (es ist kein Text, der sich ausklappt, sondern ein Menü) und wird entfernt.
 */
.user-menu-wrap {
    position: relative;
}

.user-menu > summary {
    display: flex;
    align-items: center;
    gap: var(--space-s);
    padding: var(--space-xs) var(--space-s) var(--space-xs) var(--space-xs);
    border: 1px solid transparent;
    border-radius: var(--radius-pill);
    cursor: pointer;
    list-style: none;
    color: var(--color-text-secondary);
}

.user-menu > summary::-webkit-details-marker {
    display: none;
}

.user-menu > summary:hover {
    background: var(--color-surface-hover);
    border-color: var(--color-stroke);
    color: var(--color-text);
}

.user-menu > summary:focus-visible {
    outline: 2px solid var(--color-accent);
    outline-offset: 2px;
}

/* Initialen im Kreis, in der Akzentfarbe — der Markenfarbe, damit es zur Wortmarke passt. */
.user-mark {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    border-radius: 50%;

    /* Die Flächenfarbe, nicht die Textfarbe des Akzents: Im dunklen Schema ist '--color-accent'
       ein helles Lila für Schrift auf Dunkel, und Weiß darauf erreichte keine 3:1. */
    background: var(--color-accent-bg);
    color: var(--color-on-accent);
    font-size: var(--font-size-caption);
    font-weight: 600;
}

/* Auf schmalen Bildschirmen bleibt nur der Kreis. */
@media (max-width: 1100px) {
    .user-menu-name {
        display: none;
    }
}

.user-menu-panel {
    position: absolute;
    inset-inline-end: 0;
    z-index: 20;
    min-width: 18rem;
    margin-top: var(--space-xs);
    padding: var(--space-m);
    background: var(--color-surface);
    border: 1px solid var(--color-stroke);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-2);
}

.user-menu-title {
    margin: 0 0 var(--space-xs);
    font-weight: 600;
}

.user-menu-badges {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-xs);
    margin: var(--space-s) 0;
}

.user-menu-switch {
    display: flex;
    gap: var(--space-xs);
    margin: var(--space-s) 0;
}

.user-menu-switch select {
    min-width: 0;
}

.user-menu-signout {
    width: 100%;
    margin-top: var(--space-s);
}

/* Bei wenig Platz zuerst den Namen weglassen, dann die Rolle. */
@media (max-width: 900px) {
    .topbar-user {
        display: none;
    }
}

/* ── Navigation ─────────────────────────────────────────────────────────────────────────────── */

.sidebar {
    grid-area: nav;
    display: flex;
    flex-direction: column;
    padding: var(--space-m) var(--space-s);
    background: var(--color-canvas);
}

/*
 * Grundmuster jeder Liste in der Navigation — und ':where()' ist hier kein Schönheitsfehler.
 *
 * Als '.sidebar ul' hatte diese Regel die Spezifität (0,1,1) und schlug damit JEDE Klassenregel
 * darunter, obwohl die später steht: Spezifität schlägt Reihenfolge. Zwei Dinge sind daran
 * lautlos gescheitert — die Pakete standen 12 px weiter links als alles andere in der Leiste
 * (ihr 'padding' kam nie an), und 'margin-top: auto' der Fußzeile ebenso wenig, weshalb
 * „Einstellungen und Hilfe" direkt unter dem letzten Eintrag klebte statt am Fuß zu sitzen.
 * Beides sah nach einem Gestaltungsfehler aus und war einer der Kaskade.
 *
 * ':where()' zählt bei der Spezifität nicht mit. Die Regel wirkt damit als (0,1,0) und ist das,
 * was sie sein soll: die Vorgabe, die jede Liste mit eigener Klasse überschreiben darf.
 */
.sidebar :where(ul) {
    list-style: none;
    margin: 0 0 var(--space-l);
    padding: 0;
}

/*
 * Hilfe sitzt am Fuß der Navigation, abgesetzt durch eine Linie und den freien Raum darüber.
 * 'margin-top: auto' schiebt sie ans untere Ende, solange die Navigation Platz hat — sie soll nicht
 * unmittelbar unter dem letzten Arbeitspunkt kleben und dadurch wie einer aussehen.
 */
.nav-footer {
    margin-top: auto;

    /* Kein Abstand nach unten: '.sidebar ul' gibt jeder Liste einen, und beim letzten Block
       stand er zwischen Eintrag und Fensterrand — sichtbar als Loch unter dem Trennstrich. */
    margin-bottom: 0;
    padding-top: var(--space-m);
    border-top: 1px solid var(--color-stroke);
}

/* '.nav-wechsel': ein Eintrag, der die Sitzung wechselt (_Raumrueckweg) und deshalb ein
   Formularknopf ist — in derselben Gestalt wie die Verweise daneben. */
.sidebar a,
.sidebar .nav-wechsel {
    display: flex;
    align-items: center;
    gap: var(--space-m);
    min-height: 36px;
    padding: 0 var(--space-m);
    border-radius: var(--radius-sm);
    color: var(--color-text);
    font-size: var(--font-size-body);
}

.sidebar .nav-wechsel {
    width: 100%;
    background: none;
    border: 0;
    font-family: inherit;
    font-weight: inherit;
    text-align: start;
    cursor: pointer;
}

/* Das Formular darum ist im Fluss inline (.raumverweis); in der Leiste füllt es die Zeile. */
.sidebar .raumverweis {
    display: block;
}

/* Das Symbol vor jedem Eintrag (NavSymbolTagHelper): 20 px, in der Nebenfarbe, beim aktiven
   Eintrag in der Markenfarbe. Es schrumpft nie — sonst drückt ein langer Name es zusammen. */
.nav-symbol {
    flex: none;
    width: 20px;
    height: 20px;
    color: var(--color-text-secondary);
}

.sidebar a[aria-current] .nav-symbol {
    color: var(--color-accent);
}

.sidebar a:hover,
.sidebar .nav-wechsel:hover {
    /* Auf der grauen Grundfläche: dieselbe Fläche wie die Auswahl. Was ausgewählt ist, sagen
       Strich, Schnitt und Symbolfarbe — die Fläche sagt nur „hier bist du mit der Maus". */
    background: var(--color-accent-subtle);
    color: var(--color-text);
    text-decoration: none;
}

.sidebar a[aria-current] {
    /* Der aktive Punkt ist zart in der Markenfarbe hinterlegt — ohne Strich daneben (Daniel,
       2026-10-08). Farbe trägt es nicht allein: Schnitt 600, Symbol in der Markenfarbe und
       'aria-current' sagen es auch (WCAG 1.4.1). */
    background: var(--color-accent-tint);
    color: var(--color-text);
    font-weight: 600;
}


/*
 * Gruppen mit Überschrift lassen sich zuklappen; die Überschrift ist der Schalter.
 *
 * 'details'/'summary' statt Schaltfläche und Skript: Tastaturbedienung, Rolle und 'aria-expanded'
 * bringt der Browser mit, und ohne JavaScript klappt es weiterhin auf und zu. Gemerkt wird der
 * Zustand im Cookie und serverseitig ins Markup geschrieben (siehe Navigationszustand) — sonst
 * klappte die Gruppe bei jedem Seitenaufruf sichtbar zusammen, nachdem sie kurz offen stand.
 *
 * Der Abstand nach unten sitzt an der Gruppe, nicht an der Liste darin: Ist sie zugeklappt, gibt
 * es die Liste nicht, und die nächste Gruppe klebte an der Überschrift.
 */
.nav-gruppe {
    margin-bottom: var(--space-l);
}

.nav-gruppe > ul {
    margin-bottom: 0;
}

/* Die Maße von '.nav-heading', das diese Zeile abgelöst hat — die Gruppenüberschriften sollen
   aussehen wie vorher, sie können jetzt nur zusätzlich etwas. */
.nav-gruppe > summary {
    display: flex;
    align-items: center;
    gap: var(--space-xs);

    /* Über die ganze Breite der Leiste und 24 px hoch: das geforderte Mindestziel, und getroffen
       wird die Zeile, nicht das Wort (WCAG 2.5.8). */
    min-height: 24px;
    margin: 0 0 var(--space-xs);
    padding: 0 var(--space-m);
    border-radius: var(--radius-sm);
    color: var(--color-text-secondary);
    font-size: var(--font-size-caption);
    font-weight: 600;
    cursor: pointer;
}

/* Safari zeigt sein eigenes Dreieck auch dann noch an, wenn 'display: flex' das Listenzeichen
   der übrigen Browser längst entfernt hat. Sonst stünden dort zwei Zeichen nebeneinander. */
.nav-gruppe > summary::-webkit-details-marker {
    display: none;
}

.nav-gruppe > summary:hover {
    background: var(--color-surface-hover);
    color: var(--color-text);
}

/*
 * Das Zeichen sagt, was ein Klick bewirkt: zur Seite heißt zu, nach unten heißt offen. Es trägt
 * die Aussage nicht allein — 'aria-expanded' am summary sagt dasselbe ohne jede Darstellung
 * (WCAG 1.4.1). Dasselbe Zeichen wie in den Brotkrumen, damit die Leiste keine zweite Formsprache
 * aufmacht.
 *
 * Die Drehung wirkt, weil das Pseudoelement in einem Flex-Behälter steht und damit ein
 * Flex-Element ist; an einem gewöhnlichen Inline-Element bliebe 'transform' ohne Wirkung.
 */
.nav-gruppe > summary::before {
    content: "›";
    flex: 0 0 auto;
}

.nav-gruppe[open] > summary::before {
    transform: rotate(90deg);
}

/*
 * Die Paketeinträge sehen aus wie jeder andere Navigationspunkt: Symbol, Name, dieselbe Höhe,
 * dieselbe Auswahl. Vorher waren sie ein eigenes, kleineres Untermenü mit Punkt davor — eine
 * zweite Gestalt für dieselbe Sache. Die Gruppe sagt die Überschrift „Pakete", nicht die Schrift.
 * Ein langer Name („Sicherheitstechnische Betreuung (DGUV V2)") bricht innerhalb seiner Spalte
 * um, das Symbol bleibt oben stehen.
 */
.sidebar .nav-pakete a {
    align-items: flex-start;
    padding-block: var(--space-s);
    line-height: 20px;
}

.sidebar .nav-pakete .nav-symbol {
    margin-top: 0;
}

/* ── Inhalt ─────────────────────────────────────────────────────────────────────────────────── */

/* Volle Breite. Listen und Tabellen sind der Kern dieses Portals und sollen den Platz nutzen —
   eine Betriebsliste mit acht Spalten auf 1264 px zu beschränken verschenkt Bildschirm.
   Fließtext bekommt dagegen weiter unten eine Lesebreite: Zeilen über etwa 90 Zeichen sind
   messbar schlechter lesbar, und Lesbarkeit ist Teil der Barrierefreiheit (WCAG 1.4.8). */
.content {
    grid-area: main;
    padding: var(--space-xxl);
    min-width: 0;

    /* Die Arbeitsfläche liegt als eigene Ebene auf der Grundfläche — wie in Microsoft 365
       (OneDrive, Outlook im Web): Kopfzeile und Navigation sind Grund, der Inhalt ist Blatt.
       Rechts und unten reicht es bis an den Fensterrand, gerundet ist nur die Ecke zur Navigation:
       Mit einem grauen Rand rechts stand die Scrollleiste des Blatts mitten in der Fläche statt
       am Fensterrand (Daniel, 2026-10-08). */
    margin: 0;
    background: var(--color-surface);
    border-radius: var(--radius-lg) 0 0 0;
    box-shadow: var(--shadow-2);
}

/*
 * Auf dem Blatt keine schwebenden Kästen mehr. Vorher trug fast alles eine eigene Karte mit
 * Schatten — Werkzeugleiste, Tabelle, sogar der leere Zustand. Auf grauem Grund gliederte das,
 * auf dem weißen Blatt ist es Lärm und wirkt nach Formularsoftware.
 *
 *   Karten und Listen   → feiner Rahmen statt Schatten (Weiß auf Weiß braucht eine Kante)
 *   Werkzeugleiste      → flach, ohne Fläche: sie gehört zum Blatt, nicht in einen Kasten
 *   Leerer Zustand      → Symbol und Text, mittig, mit Luft, ohne Rahmen
 *
 * Außerhalb von .content (Seiten vor der Anmeldung) bleiben Schatten: dort ist der Grund grau.
 */
.content .card,
.content .list-surface {
    box-shadow: none;
    border: 1px solid var(--color-stroke);
}

.content .command-bar {
    padding: 0;
    background: transparent;
    box-shadow: none;
    border-radius: 0;
}

.content .empty-state {
    background: transparent;
    box-shadow: none;
}

/* Lesebreite für zusammenhängenden Text — nicht für Listen, Tabellen und Kennzahlen. */
.lead,
.notice,
.empty-state p,
.content > p {
    max-width: 90ch;
}

/*
 * Formularkarten füllen die Inhaltsspalte — wie Tabellen und Listen auch.
 *
 * Vorher standen sie auf 1100px. Auf einem Notebook fiel das kaum auf, auf einem breiten Bildschirm
 * sehr wohl: Über der Karte laufen die Tabellen durch, die Karte darunter bricht mittendrin ab und
 * hängt links. Das liest sich nicht als bewusste Lesebreite, sondern als Fehler.
 *
 * Die Sorge hinter dem Deckel war richtig — ein Eingabefeld über die ganze Bildschirmbreite ist
 * schwer zu überblicken. Sie ist aber am falschen Ort gelöst: Dafür sind die Feldraster da
 * (.field-row), die mehrere Felder nebeneinander legen und die Breite so sinnvoll aufteilen.
 * Ein einzeln stehendes Feld gehört in ein solches Raster, nicht in eine schmalere Karte.
 */

h1 {
    /* 8 px zur Zeile darunter: Bei 32 px Titel klebte die Einleitung mit 4 px daran. */
    margin: 0 0 var(--space-s);
    font-size: var(--font-size-display);
    font-weight: 600;
    line-height: 40px;

    /* Große Grade wirken mit leicht engerer Laufweite geschlossener — wie in Microsoft 365. */
    letter-spacing: -0.01em;
}

h2 {
    margin: var(--space-xxl) 0 var(--space-m);
    font-size: var(--font-size-section);
    font-weight: 600;
    line-height: 24px;
}

h3 {
    margin: var(--space-l) 0 var(--space-s);
    font-size: var(--font-size-body);
    font-weight: 600;
}

/* Gruppe innerhalb einer Karte (Einstellungen, Auskunft): wie 'h3', mit weniger Luft darüber.
   Ohne eigene Regel galten die Vorgaben des Browsers — 700 und 18,62 px Abstand. */
h4 {
    margin: var(--space-m) 0 var(--space-xs);
    font-size: var(--font-size-body);
    font-weight: 600;
}

/* Fett ist immer 600 (docs/design.md §4). Die Vorgabe des Browsers für 'strong' ist 'bolder',
   bei 400 also 700 — ein dritter Schnitt neben 400 und 600. */
strong,
b {
    font-weight: 600;
}

.lead {
    margin: 0 0 var(--space-xl);
    color: var(--color-text-secondary);
}

.subtle {
    color: var(--color-text-secondary);
}

.caption {
    font-size: var(--font-size-caption);
    color: var(--color-text-secondary);
}

/* Abstandshilfen — ersetzen die von der CSP blockierten style-Attribute. */
.stack-top {
    margin-top: var(--space-l);
}

.stack-top-lg {
    margin-top: var(--space-xxl);
}

.stack-bottom {
    margin-bottom: var(--space-l);
}

.align-end {
    align-self: end;
}

/*
 * Überschrift mit Schaltfläche rechts daneben. Die Schaltfläche gehört sichtbar zum Abschnitt,
 * deshalb in dieselbe Zeile — und nicht ans Ende der Liste, wo sie erst nach dem Scrollen auftaucht.
 */
.section-header {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--space-m);

    /* Der Abschnittsabstand sitzt am Kopf, nicht an der 'h2' darin: Ein Flex-Behälter lässt die
       Außenabstände seiner Kinder nicht mit denen davor zusammenfallen. Mit 32 px an der 'h2'
       standen Abschnitte mit Aktion 56 px tief, Abschnitte ohne 32 px. */
    margin-top: var(--space-xxl);
}

.section-header h2 {
    margin-top: 0;
    margin-bottom: var(--space-s);
}

/*
 * Das Pluszeichen ist Schmuck, die Beschriftung trägt die Bedeutung — deshalb aria-hidden im
 * Markup. Ein Zeichen allein wäre für 30- bis 60-jährige Gelegenheitsnutzer eine Ratearbeit, und
 * für Screenreader gar nichts.
 */
.button-plus {
    margin-inline-end: var(--space-xs);
    font-size: var(--font-size-subtitle);
    line-height: 1;
}

/* Verweis auf die Suchseite, wenn es zu viele Mandanten für ein Auswahlfeld sind. */
/* ── Seiten vor der Anmeldung ───────────────────────────────────────────────────────────────── */

/*
 * Eine Aufgabe, ein Objekt. Es gibt hier keine Navigation, keine Werkzeugleiste und kein zweites
 * Ziel — vor der Anmeldung ist ein Dialoglayout die ehrliche Beschreibung des Zustands, und ein
 * Dialog ist genau das, was unsere Nutzer jeden Morgen in Outlook Web sehen.
 *
 * 'flex-direction: column' ist kein Geschmacksentscheid, sondern eine Reparatur: Das
 * Umgebungsbanner ist im Layout ein Geschwister von <main>. In der Vorgaberichtung 'row' wurde es
 * zum zweiten Flex-Element und stand als schmale Saeule NEBEN dem Formular, sobald
 * AppOptions.EnvironmentLabel gesetzt ist (Vorschau, Stage). Als Spalte liegt es wieder oben und
 * ueber die volle Breite.
 *
 * 'justify-content: center' faellt ersatzlos weg; die Zentrierung uebernimmt der automatische
 * Aussenabstand am Inhalt (Begruendung dort).
 */
.schlicht {
    display: flex;
    flex-direction: column;
    min-height: 100vh;
    background: var(--color-canvas);
}

/*
 * Mittig — waagerecht UND senkrecht, aber ueber 'margin: auto' statt 'justify-content: center'.
 *
 * Automatische Raender nehmen in einer Flexbox nur POSITIVEN Restplatz auf. Ist der Inhalt hoeher
 * als das Fenster — 200 % Zoom, kleines Notebook, aufgeklappte Fehlermeldung, eingeblendete
 * Bildschirmtastatur —, loesen sie sich zu null auf und der Inhalt beginnt oben. Mit
 * 'justify-content: center' waere in genau diesem Fall die Oberkante aus dem Fenster geschoben
 * und mit keiner Bildlaufleiste erreichbar: der klassische Weg, WCAG 1.4.4 und 1.4.10 mit einer
 * Zeile Zentrierung zu verlieren. Diese Zeile bitte nicht "aufraeumen".
 *
 * Die 30 rem bleiben. Ein Anmeldeformular wird nicht besser, wenn es breiter ist.
 */
.schlicht-inhalt {
    width: min(30rem, 100%);
    margin: auto;
    padding: var(--space-xxl) var(--space-l);
}

/* Inhaltsseiten ohne Anmeldung (etwa /funktionen/verbandbuch): eine Lesespalte statt eines
   Formulars. Zwei Klassen (0,2,0), damit die Breite gegen '.schlicht-inhalt' gewinnt, gleich wo
   sie steht. Oben ausgerichtet statt senkrecht mittig — ein langer Text beginnt oben. */
.schlicht-inhalt.schlicht-breit {
    width: min(48rem, 100%);
    margin: 0 auto;
}

/* Die Wortmarke sagt, wo man ist — mehr nicht. Sie bleibt im selben Zustand wie in der Kopfzeile
   der angemeldeten Anwendung (.brand-logo, 24 px hoch). Auf einer sonst leeren Seite
   ist die Versuchung gross, sie zu vergroessern; genau dort wird aus einer Fachanwendung eine
   Marketingseite (MANIFEST §5.1). */
.schlicht-marke {
    margin-bottom: var(--space-xl);
    font-size: var(--font-size-subtitle);
}

/*
 * Der eigentliche Grund, warum diese Seiten "nur vorhanden" statt gestaltet wirkten.
 *
 * 'h1' traegt global 'margin: 0 0 var(--space-xs)' (app.css:577) — 4 px. In den Arbeitsansichten
 * stimmt das, dort folgt eine Werkzeugleiste, die selbst Abstand mitbringt. Hier klebt die
 * Ueberschrift an der Karte bzw. an der Fehlermeldung. 16 px trennen den Titel vom Objekt und
 * binden ihn zugleich staerker an dieses als an die Wortmarke darueber (24 px).
 *
 * Spezifitaet 0,1,1 gegen 0,0,1 — die Regel gewinnt unabhaengig von der Reihenfolge.
 */
.schlicht-inhalt h1 {
    margin-bottom: var(--space-l);
}

/*
 * Die Karte.
 *
 * ZWEI Dinge sind hier bewusst und beide sind nachgerechnet, nicht gefuehlt:
 *
 * 1. Der Selektor ist '.schlicht .card' (0,2,0) und NICHT eine eigene Klasse (0,1,0). '.card'
 *    steht in app.css:1028 mit 0,1,0 und WEITER UNTEN — eine gleich spezifische Regel hier oben
 *    verloere gegen sie, und zwar lautlos: Die Karte behielte 16 px Innenrand und --shadow-2,
 *    also exakt das heutige Bild. app.css warnt zwei Absaetze weiter oben (Zeile 250–253) woertlich
 *    vor diesem Fehler: Spezifitaet schlaegt Reihenfolge.
 *
 * 2. Der Selektor greift damit fuer ALLE drei Seiten vor der Anmeldung. Das ist kein Nebeneffekt,
 *    sondern Absicht: Anmelden, Passwort vergessen und Passwort setzen teilen sich dieses Layout.
 *    Eine erhobene Karte auf einer und zwei flache daneben waeren schlechter als der Zustand von
 *    heute. So ziehen alle drei ohne eine Zeile Markup-Aenderung mit.
 *
 * --shadow-8 statt --shadow-2, weil die Karte hier das einzige Objekt der Seite ist und nicht
 * eines von vielen in einer Liste; dort bleibt --shadow-2 richtig. 24 px statt 40 px Innenrand,
 * weil eine Erhebung nur glaubwuerdig ist, wenn sie etwas hebt: Zwei Felder in einer 30-rem-Karte
 * mit 40 px Rand heben vor allem Leere.
 *
 * Kontrast: Karte gegen Arbeitsflaeche sind 1,05:1 hell (#ffffff auf #faf9f8) und 1,12:1 dunkel.
 * Die Trennung leistet also nicht die Farbe, sondern die Erhebung. Das ist zulaessig: Die Karte
 * ist kein Bedienelement, WCAG 1.4.11 fordert fuer sie keine 3,0:1 — ohne die Kante geht keine
 * Information verloren, die Felder darin tragen ihre eigenen 6,19:1 (hell) bzw. 7,34:1 (dunkel).
 */
.schlicht .card {
    padding: var(--space-xl);
    box-shadow: var(--shadow-8);
}

/*
 * Im Dunkelmodus traegt der Schatten nicht: Schwarz auf fast schwarzem Grund ist unsichtbar, und
 * 1,12:1 zwischen Karte und Flaeche waere nur zu ahnen. Deshalb dort eine Haarlinie statt der
 * Erhebung — dekorativ, kein Bedienelement-Umriss (#494949 auf #1f1f1f = 1,83:1, gegen die
 * Arbeitsflaeche 2,05:1).
 *
 * Unter 'prefers-contrast: more' wird --color-stroke-strong ohnehin zu #c7c7c7 und die Linie mit
 * 9,75:1 gegen die Karte deutlich. Der Zweig verbessert also, er verschlechtert nichts.
 *
 * Damit gibt es voruebergehend zwei Kartensorten im Dunkelmodus. Sauber waere, '.card' global eine
 * Kante zu geben — das ist ein Eingriff in jede Liste, jedes Dashboard und jede Detailseite und
 * gehoert in einen eigenen Schritt mit eigenem Blick auf alle Seiten.
 */
:root[data-theme="dark"] .schlicht .card {
    border: 1px solid var(--color-stroke-strong);
}

/*
 * Der 60-ch-Deckel aus '.field > input' faellt hier weg.
 *
 * Er existiert, weil das Auge bei einem Feld ueber die halbe Bildschirmbreite auf dem Rueckweg vom
 * Ende der Eingabe die Zuordnung zur Beschriftung links verliert. In einer 30-rem-Spalte gibt es
 * dieses Problem nicht — dort teilt die Spalte die Breite bereits auf, genau wie '.field-row' es
 * in der Anwendung tut (siehe die Begruendung bei '.field-row .field > input').
 *
 * Und er kostet hier etwas: Endet das Feld vor der Kartenkante, steht die rechtsbuendige
 * Schaltflaeche darunter an keiner Fluchtlinie, sondern frei im Raum. Ob 60 ch bei der aktuellen
 * Schrift ueberhaupt greifen, haengt am Zeichensatz — eine Ausrichtung, die von der geladenen
 * Schrift abhaengt, ist keine.
 */
.schlicht .card .field > input,
.schlicht .card .field > select {
    max-width: none;
}

/* Absaetze, die unmittelbar in der Karte stehen, folgen ihrem 16-px-Raster und nicht der
   Browservorgabe von 1em oben und unten. Betrifft heute genau den Verweis-Absatz. */
.schlicht .card > p {
    margin: 0 0 var(--space-l);
}

/*
 * Die Hauptaktion vor der Anmeldung: volle Breite, nicht rechts in der Ecke.
 *
 * Hier stand bis heute 'justify-content: flex-end' — die Fluent-Dialogordnung, Hauptaktion unten
 * rechts. In einem Dialog stimmt sie: Dort stehen mehrere Aktionen nebeneinander und die Ecke
 * sagt, welche die Vorfahrt hat. Auf diesen vier Seiten gibt es genau eine Aktion und nichts zu
 * entscheiden. Eine 100 px breite Schaltflaeche an der Kante einer 480-px-Karte sah deshalb aus
 * wie ein Rest, nicht wie ein Ziel.
 *
 * Die Hoehe: 40 px statt der 32 px aus '--control-height'. Es ist die einzige Schaltflaeche der
 * Seite und wird oft am Telefon gedrueckt; WCAG 2.5.5 (AAA) nennt 44 px, die AA-Pflicht aus
 * 2.5.8 sind 24 px. Zusammen mit der vollen Breite ist die Trefferflaeche ein Vielfaches davon.
 * Das gilt AUSDRUECKLICH nur in der Karte vor der Anmeldung ('.schlicht .card') — in der
 * Anwendung bleibt es bei 32 px, sonst entstuende eine zweite Groesse ohne Anlass.
 *
 * Die Breite selbst kommt aus '.button-block' und steht bei den uebrigen Schaltflaechen-
 * Zusaetzen; hier steht nur, was an DIESER Stelle anders ist.
 */
.schlicht .card .button-block {
    min-height: 40px;
}

/*
 * Der Nebenweg unter der Hauptaktion — „Passwort vergessen", „Zurueck zur Anmeldung",
 * „Code erneut schicken".
 *
 * Er steht NACH der Schaltflaeche, und das ist der Punkt: Im Markup wie im Bild wie in der
 * Tabulatorfolge. Vorher stand der Verweis zwischen Passwortfeld und Schaltflaeche — wer sich
 * anmelden wollte, kam auf dem Weg zur Hauptaktion erst am Ausweg vorbei. Ein Nebenweg gehoert
 * hinter den Hauptweg, nicht davor (WCAG 2.4.3).
 *
 * Mittig, weil die Schaltflaeche darueber die ganze Breite einnimmt: Es gibt keine linke
 * Fluchtlinie mehr, an der ein einzelner Verweis haengen koennte.
 *
 * Die Trefferflaeche leistet '.standalone-link' (28 px) bzw. '.button' (32 px), die Farbe die
 * Verweisregel des Geruests. Hier steht nur die Anordnung.
 *
 * Zwei Selektoren, eine Regel: Der Nebenweg steht meist IN der Karte (ein Absatz mit Verweis),
 * beim Nachschicken des Codes aber DAVOR — ein Formular darf kein zweites enthalten. Der zweite
 * Selektor existiert nur, um '.schlicht .card > p' (0,2,1) zu schlagen; ohne ihn behielte der
 * Absatz in der Karte dessen 16 px unten und stuende links.
 */
.nebenweg,
.schlicht .card > .nebenweg {
    margin: var(--space-m) 0 0;
    text-align: center;
}

/*
 * Ein Verweis, der ALLEIN in einer Zeile steht, ist ein eigenstaendiges Ziel. Die Inline-Ausnahme
 * aus WCAG 2.5.8 gilt nur fuer Verweise innerhalb eines Satzes, deren Groesse die Zeilenhoehe des
 * umgebenden Textes begrenzt — hier gibt es keinen umgebenden Text. 20 px Zeilenhoehe (body)
 * plus zweimal 4 px ergeben 28 px und damit mehr als die geforderten 24 px. MANIFEST §5.2
 * formuliert die 24 px ohne Ausnahme; auf die WCAG-Spacing-Ausnahme darf man sich hier also gar
 * nicht erst berufen.
 *
 * Eigener Klassenname statt 'p > a': Ein Verweis mitten in einem Satz darf nicht 'inline-block'
 * werden, sonst bricht er nicht mehr um.
 */
.standalone-link {
    display: inline-block;
    padding-block: var(--space-xs);
}

/*
 * Fussnote unter einer Trennlinie, IN der Karte.
 *
 * Sie beantwortet eine Frage, die nur wenige haben (Einladung erhalten, noch kein Passwort), und
 * darf deshalb nicht mit dem Formular konkurrieren — aber sie spart der Betreuung Anrufe. In der
 * Karte statt darunter, weil eine Erhebung nur glaubwuerdig ist, wenn sie etwas hebt: Die Fussnote
 * gibt der Karte eine untere Kante mit Inhalt statt einen dekorativen Rand. Eine Seite, ein Objekt.
 *
 * Groesse und Farbe kommen aus '.caption' (8,45:1 hell, 9,75:1 dunkel gegen die Karte — AAA),
 * hier steht nur die Abtrennung. Die Linie ist dekorativ (1,33:1 hell, 1,30:1 dunkel) und darf das
 * sein: Sie trennt, sie bedient nichts.
 *
 * Spezifitaet 0,3,0 — schlaegt '.schlicht .card > p' (0,2,1). Ohne den Kindkombinator dort waeren
 * die beiden Regeln in Konflikt geraten.
 */
.schlicht .card > .schlicht-fussnote {
    margin: var(--space-xl) 0 0;
    padding-top: var(--space-l);
    border-top: 1px solid var(--color-stroke);
}

.schlicht-fussnote > p {
    margin: 0;
}

.schlicht-fussnote > p + p {
    margin-top: var(--space-s);
}

/* ── Prüfhistorie ───────────────────────────────────────────────────────────────────────────── */

/*
 * Die Prüfvorgeschichte eines Betriebsmittels, aufklappbar in der Tabellenzelle.
 *
 * <details>/<summary> statt eines nachgebauten Aufklappens: Es funktioniert ohne eine Zeile
 * JavaScript, ist mit der Tastatur bedienbar und wird von Screenreadern als Ausklappbereich
 * angesagt. Ein Nachbau müsste all das erst herstellen — und tut es erfahrungsgemäß halb.
 */
.historie {
    margin-top: var(--space-s);
}

.historie summary {
    /* Trefferfläche: 14 px Schrift, 20 px Zeilenhöhe plus zweimal 4 px sind 28 px und damit mehr
       als die geforderten 24 px (WCAG 2.5.8). */
    padding: var(--space-xs) 0;
    color: var(--color-text-secondary);
    font-size: var(--font-size-caption);
    cursor: pointer;
}

.historie summary:hover,
.historie summary:focus-visible {
    color: var(--color-text);
}

.historie ul {
    margin: var(--space-xs) 0 0;
    padding-inline-start: var(--space-m);
    /* Bei sechzehn Prüfungen wächst die Tabellenzeile sonst über den Bildschirm hinaus. */
    max-height: 16rem;
    overflow-y: auto;
}

.historie li {
    padding: var(--space-xs) 0;
    font-size: var(--font-size-caption);
    border-bottom: 1px solid var(--color-stroke);
}

.historie li:last-child {
    border-bottom: none;
}

/* ── Brotkrumen ─────────────────────────────────────────────────────────────────────────────── */

/*
 * Sie stehen über der Überschrift und sind bewusst zurückhaltend: Sie beantworten die Frage
 * „wo bin ich", ohne sie zu stellen. Das Trennzeichen kommt aus CSS und nicht aus dem Markup —
 * ein Screenreader liest sonst bei jedem Eintrag ein sinnloses Zeichen mit.
 */
.breadcrumbs {
    margin-bottom: var(--space-m);
}

.breadcrumbs ol {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-xs);
    margin: 0;
    padding: 0;
    list-style: none;
    font-size: var(--font-size-body);
}

.breadcrumbs li + li::before {
    content: "›";
    margin-inline-end: var(--space-xs);
    color: var(--color-text-secondary);
}

.breadcrumbs a {
    color: var(--color-text-secondary);
    text-decoration: none;
}

.breadcrumbs a:hover,
.breadcrumbs a:focus-visible {
    color: var(--color-text);
    text-decoration: underline;
}

/* Die aktuelle Seite: sichtbar als Endpunkt, aber nicht als Ziel. */
.breadcrumbs [aria-current="page"] {
    color: var(--color-text);
    font-weight: 600;
}

/* ── Suche in der Kopfzeile ─────────────────────────────────────────────────────────────────── */

/*
 * Sie wächst mit dem verfügbaren Platz, bleibt aber lesbar begrenzt. Ohne 'min-width: 0' würde
 * das Eingabefeld in einem Flex-Kopf nicht unter seine Inhaltsbreite schrumpfen und die
 * Identitätsangabe rechts hinausdrücken.
 */
/*
 * Mittig durch zwei Abstandshalter links und rechts. Bewusst nicht 'flex: 1' — dann wüchse das
 * Feld über die halbe Kopfzeile und wäre kein Bedienelement mehr, sondern eine Fläche. Eine feste
 * Breite hält es dort, wo das Auge es sucht, auch wenn der Name daneben länger oder kürzer ist.
 */
.topbar-search {
    position: relative;
    width: min(46ch, 100%);
}

/*
 * Der Rahmen liegt hier, nicht an den Teilen darin.
 *
 * Vorher trugen Eingabefeld und Schaltfläche je einen eigenen Rahmen. Beim Überfahren wechselte
 * nur einer die Farbe, an der Naht traf hell auf dunkel, und es sah aus, als fiele der Rahmen
 * weg. Ein Bedienelement, ein Rahmen — dann kann auch nur eines reagieren.
 */
.search-field {
    display: flex;
    align-items: center;
    gap: var(--space-xs);
    padding-inline: var(--space-m);
    min-height: 36px;

    /* Weiße Pille auf grauer Kopfzeile, wie die Suche in Microsoft 365 — ohne dunklen Rahmen.
       Erkennbar bleibt sie an Lupe und Platzhalter (Lupe ≥ 3:1, WCAG 1.4.11); der zarte Rahmen
       gibt nur die Kante. Beim Überfahren hebt ein Schatten sie an, im Fokus der Akzentring. */
    border: 1px solid var(--color-stroke);
    border-radius: var(--radius-pill);
    background: var(--color-surface);
}

.search-field:hover {
    box-shadow: var(--shadow-4);
}

/* focus-within statt :focus am Feld: Der Rahmen gehört dem Behälter, der Fokus dem Feld darin. */
.search-field:focus-within {
    border-color: var(--color-accent);
    box-shadow: 0 0 0 1px var(--color-accent);
}

.search-icon {
    display: inline-flex;
    color: var(--color-text-secondary);
}

/* Das Eingabefeld selbst ist rahmenlos — es füllt nur den Behälter aus. */
.search-field input,
.search-field input:hover,
.search-field input:focus {
    flex: 1;
    min-width: 0;
    height: var(--control-height);
    min-height: 0;
    padding: 0;
    border: 0;
    background: transparent;
    box-shadow: none;
    outline: none;
}

/* Die Suchlupe blendet in Chrome ein eigenes Kreuz ein — es doppelt sich mit dem Feldrahmen. */
.search-field input::-webkit-search-cancel-button {
    cursor: pointer;
}

.search-go {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: var(--control-height);
    height: var(--control-height);
    padding: 0;
    border: 0;
    border-radius: var(--radius-pill);
    background: transparent;
    color: var(--color-text-secondary);
    cursor: pointer;
    font-size: var(--font-size-body);
}

.search-go:hover {
    background: var(--color-surface-hover);
    color: var(--color-text);
}

.search-go:focus-visible {
    outline: 2px solid var(--color-accent);
    outline-offset: 2px;
}

/* ── Vorschläge unter dem Suchfeld ──────────────────────────────────────────────────────────── */

/*
 * Nur sichtbar, wenn etwas drinsteht: ':empty' erspart ein Skript, das ein leeres Feld ein- und
 * ausblendet — und damit eine Stelle, an der die Anzeige und der Inhalt auseinanderlaufen können.
 */
.search-panel {
    position: absolute;
    inset-inline: 0;
    z-index: 30;
    margin-top: var(--space-xs);
    background: var(--color-surface);
    border: 1px solid var(--color-stroke);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-8);
    overflow: hidden;
}

.search-panel:empty {
    display: none;
}

.search-suggestions {
    margin: 0;
    padding: var(--space-xs);
    list-style: none;
}

.search-suggestions a {
    display: block;
    padding: var(--space-xs) var(--space-s);
    border-radius: var(--radius-sm);
    color: var(--color-text);
    text-decoration: none;
}

.search-suggestions a:hover,
.search-suggestions a:focus-visible {
    background: var(--color-accent-subtle);
}

.search-suggestion-title {
    display: block;
}

.search-suggestion-meta {
    display: block;
    color: var(--color-text-secondary);
    font-size: var(--font-size-caption);
}

.search-hint {
    margin: 0;
    padding: var(--space-s) var(--space-m);
    color: var(--color-text-secondary);
    font-size: var(--font-size-caption);
}

.search-all {
    display: block;
    padding: var(--space-s) var(--space-m);
    border-top: 1px solid var(--color-stroke);
    color: var(--color-link);
    font-size: var(--font-size-caption);
}

/*
 * Auf schmalen Bildschirmen verschwindet sie. Nicht aus Platznot allein: Eine Suche, die neben
 * Namen, Rolle und drei Schaltflächen auf 360 Pixel gequetscht wird, ist für niemanden bedienbar.
 * Erreichbar bleibt sie über die Seite /suche.
 */
@media (max-width: 900px) {
    .topbar-search {
        display: none;
    }

    /* Ohne die Suche hat das Dreispaltenraster der Kopfzeile kein Mittelstück mehr: Die
       Schaltflächen rutschten in die mittlere Spalte und lagen über der Wortmarke. Eine Reihe
       mit den beiden Enden außen trägt dasselbe ohne Lücke. */
    .topbar {
        display: flex;
        justify-content: space-between;
    }
}

/* Trefferliste: Zeilen mit Abstand, damit Titel und Einordnung nicht verschmelzen. */
.search-hits > li {
    padding: var(--space-s) var(--space-m);
    border-bottom: 1px solid var(--color-stroke);
}

.search-hits > li:last-child {
    border-bottom: 0;
}

/* ── Nachrichten ────────────────────────────────────────────────────────────────────────────── */

.message-link {
    position: relative;
}

.message-link svg {
    width: 20px;
    height: 20px;
}

/*
 * Zähler ungelesener Vorgänge. Die Zahl selbst trägt die Bedeutung — Farbe allein dürfte es nicht
 * (WCAG 1.4.1), und für Screenreader steht der Text ausgeschrieben im visually-hidden-Bereich.
 */
.message-count {
    position: absolute;
    top: 0;
    inset-inline-end: 0;
    min-width: 16px;
    padding: 0 4px;
    border-radius: var(--radius-pill);
    background: var(--color-accent-bg);
    color: var(--color-on-accent);
    font-size: 11px;
    line-height: 16px;
    text-align: center;
    font-weight: 600;
}

/*
 * Gesprächsverlauf als Chat: eigene Nachrichten rechts in zartem Markenlila, alle anderen links in
 * Grau — wie in Teams (ADR 0049, Daniel 2026-10-08).
 *
 * Früher stand hier bewusst eine durchgehende Spalte ohne Blasen, weil der Verlauf auch ein
 * Nachweis ist und gedruckt wird. Das bleibt erfüllt, nur an anderer Stelle: Im Druck wird der
 * Verlauf wieder eine Spalte über die volle Breite (Druckblock). Wer etwas geschrieben hat, steht
 * in jeder Blase als Text (Name, Seite, Zeit) — die Seite des Bildschirms ist nur ein zweites
 * Merkmal, nie das einzige (WCAG 1.4.1).
 *
 * „Eigen" heißt: vom angemeldeten Konto geschrieben. Kollegen derselben Seite stehen links, mit
 * Namen — wie in einem Gruppenchat.
 */
.thread {
    display: flex;
    flex-direction: column;
    gap: var(--space-s);
    margin-bottom: var(--space-xl);
}

.message {
    align-self: flex-start;
    max-width: min(68ch, 85%);
    padding: var(--space-m) var(--space-l);
    border-radius: var(--radius-md) var(--radius-md) var(--radius-md) var(--space-xs);
    background: var(--color-nachricht-fremd);
}

/* Die Ecke zum Absender hin ist spitzer — das Zeichen einer Sprechblase, ohne Zipfel-Grafik. */
.message-eigen {
    align-self: flex-end;
    border-radius: var(--radius-md) var(--radius-md) var(--space-xs) var(--radius-md);
    background: var(--color-nachricht-eigen);
}

.message-meta {
    margin: 0 0 var(--space-xs);
    color: var(--color-text-secondary);
    font-size: var(--font-size-caption);
}

.message .mehrzeilig {
    margin: 0;
}

/*
 * Von wem stammt, was auf dieser Seite steht? Nur sichtbar, wenn jemand bei mehreren Anbietern
 * Kunde ist. Ruhig gehalten — es ist eine Ortsangabe, keine Warnung: dieselbe Zeilenhöhe wie die
 * Brotkrumen darüber, Sekundärtext, und der Name als einziges Fettes.
 *
 * Der Balken links trägt keine Bedeutung allein: Der Satz daneben sagt dasselbe in Worten
 * (MANIFEST §5).
 */
/*
 * Die Karte eines Anbieters auf der Auswahl.
 *
 * Als Spalte mit der Aktion am unteren Rand: Zwei Anbieter beschreiben sich unterschiedlich lang,
 * und ohne diesen Anschlag stuenden die Schaltflaechen auf verschiedenen Hoehen — die Reihe sieht
 * dann aus wie ein Fehler, nicht wie eine Wahl.
 */
.betreuungskarte {
    display: flex;
    flex-direction: column;
    gap: var(--space-s);
}

.betreuungskarte > h2 {
    margin: 0;
    font-size: var(--font-size-subtitle);
}

.betreuungskarte > p {
    margin: 0;
}

.betreuungskarte-aktion {
    margin-top: auto;
    padding-top: var(--space-s);
}

/*
 * Die Fläche für das Firmenzeichen — in jeder Karte gleich hoch, mit Logo oder ohne.
 *
 * Feste Höhe, Breite nach Bedarf: Logos kommen in jedem Seitenverhältnis, und eine feste Breite
 * verzerrte das eine oder ließe das andere winzig. 'object-fit: contain' hält das Bild
 * vollständig und unverzerrt, links bündig zum Namen darunter.
 */
.betreuungskarte-zeichen {
    display: flex;
    align-items: center;
    height: 48px;
}

.betreuungskarte-zeichen img {
    width: auto;
    max-width: 200px;
    height: 48px;
    object-fit: contain;
    object-position: left center;
}

/* Ohne hinterlegtes Logo: die Anfangsbuchstaben, wie beim Konto in der Kopfzeile. */
.betreuungskarte-kuerzel {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 48px;
    height: 48px;
    border-radius: var(--radius-md);
    background: var(--color-accent-subtle);
    color: var(--color-text);
    font-size: var(--font-size-subtitle);
    font-weight: 600;
}

/*
 * Der eigene Betriebsraum in der Karte: ein Raumsymbol statt Logo oder Anfangsbuchstaben —
 * die Kennung ist kein Name, aus dem sich Buchstaben nehmen liessen. Dieselbe Flaeche, dieselben
 * Farben wie das Kuerzel, damit die Reihe eine Reihe bleibt.
 */
.betreuungskarte-raumsymbol svg {
    display: block;
}

/*
 * Die Betriebskennung (ADR 0030): gross, mit Zeichenabstand, in der Textfarbe (AAA gegen die
 * Flaeche). Verwechslungen wie 0/O oder 1/I verhindert nicht die Schrift, sondern der
 * Zeichenvorrat — er enthaelt diese Zeichen gar nicht (Kennungszeichen.Vorrat). Der weite
 * Zeichenabstand erleichtert das Abtippen, die Ziffernfestbreite haelt die Gruppen gleich breit.
 * Kein eigener Farbwert: Token wie ueberall. Angezeigt nur ueber das Partial '_Betriebskennung'.
 */
.kennung {
    margin: var(--space-s) 0;
    font-size: var(--font-size-title);
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    letter-spacing: 0.12em;
    color: var(--color-text);
    overflow-wrap: anywhere;
}

.kennung-inline {
    font-variant-numeric: tabular-nums;
    letter-spacing: 0.08em;
}

/*
 * Die zeichenweise Vorleseform fuer Bildschirmleser gehoert nicht in die Zwischenablage: Wer die
 * sichtbare Kennung markiert und kopiert, soll sie einmal bekommen, nicht zusaetzlich buchstabiert.
 */
.kennung .visually-hidden,
.kennung-inline .visually-hidden {
    user-select: none;
}

/* Die Vorschau auf der Mandantenseite benutzt dieselbe Flaeche. */
.logovorschau {
    width: auto;
    max-width: 200px;
    height: 48px;
    object-fit: contain;
    object-position: left center;
}

.anbieterhinweis {
    margin: 0 0 var(--space-l);
    padding: var(--space-s) var(--space-m);
    border-left: 4px solid var(--color-accent);
    background: var(--color-accent-subtle);
    border-radius: 0 var(--radius-md) var(--radius-md) 0;
    color: var(--color-text-secondary);
    font-size: var(--font-size-caption);
}

.anbieterhinweis strong {
    color: var(--color-text);
}

/*
 * Was an einem Standort ansteht: drei bis fünf Zeilen aus Datum, Thema und Terminart. Bewusst
 * keine Tabelle — eine Tabelle mit fünf Zeilen und drei Spalten trägt mehr Rahmen als Inhalt,
 * und auf einem Telefon bricht sie in Spalten um, die niemand liest.
 */
.terminliste {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    gap: var(--space-m);
}

.terminliste li {
    display: grid;
    gap: var(--space-xs);
}

/* Das Datum führt die Zeile: Danach sucht das Auge, nicht nach dem Thema. */
.termin-zeit {
    font-weight: 600;
}

/* ── Kalender (Monat, Woche, Tag) ──────────────────────────────────────────────────────────────
 *
 * Ein Raster aus Kästchen — wie in Outlook, und aus demselben Grund: Wer wissen will, was diese
 * Woche ansteht, liest keine Jahresliste. Das Raster ist eine Tabelle in der <liste>-Hülle;
 * die Wochentage sind Spalten, die Wochen Zeilen, und die Kalenderwoche steht als Zeilenkopf.
 *
 * Kein Zeitstrahl mit Stunden: Er bräuchte je Termin eine Höhe aus Minuten, und die stünde als
 * style="…" im Markup — das lässt die CSP nicht zu (MANIFEST §5). Die Einträge stapeln sich
 * stattdessen in der Reihenfolge ihres Beginns, mit der Uhrzeit davor. Das ist die Ansicht,
 * die auch ohne Skript vollständig ist.
 */
.kalender table {
    table-layout: fixed;
}

.kalender thead th {
    text-align: center;
}

.kalender tbody td,
.kalender tbody th {
    padding: var(--space-xs) var(--space-xs) var(--space-s);
    vertical-align: top;
}

/* Die Höhe wirkt in einer Tabellenzelle wie eine Mindesthöhe: Ein leerer Tag bleibt ein
   Kästchen, ein voller wächst. */
.kalender-monat tbody td {
    height: 104px;
}

.kalender-woche tbody td {
    height: 280px;
}

/* Eine Mindestbreite an der TABELLE, nicht an der Zelle: Bei 'table-layout: fixed' teilt die
   Tabelle ihre Breite auf, was eine Zelle sich wünscht, zählt nicht. Auf einem Telefon
   quetschten sich sieben Tage auf 40 Pixel und jedes Wort brach nach jedem Buchstaben um.
   So scrollt die Hülle waagerecht — wie bei jeder anderen Liste. */
.kalender-monat table {
    min-width: 900px;
}

.kalender-woche table {
    min-width: 980px;
}

/* Zeilen sind hier keine Datensätze — kein Hoverton über sieben Kästchen zugleich. */
.kalender tbody tr:hover {
    background: transparent;
}

.kalender-kw {
    width: 44px;
    color: var(--color-text-secondary);
    font-size: var(--font-size-caption);
    font-weight: 600;
    text-align: center;
    background: var(--color-surface);
}

.kalender-tag-nummer {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 24px;
    height: 24px;
    padding: 0 var(--space-xs);
    border-radius: var(--radius-pill);
    font-size: var(--font-size-caption);
    font-weight: 600;
}

/* Heute: die Zahl auf Akzentfläche — dazu das Wort "heute" für die Vorleseanwendung und, in
   der Kopfzeile der Woche, der Akzentstrich wie am aktiven Reiter. */
.kalender-heute .kalender-tag-nummer {
    background: var(--color-accent-bg);
    color: var(--color-on-accent);
}

.kalender thead th.kalender-heute {
    color: var(--color-text);
    box-shadow: inset 0 -2px 0 var(--color-accent);
}

/* Tage des Nachbarmonats: gedämpfte Fläche, gedämpfte Zahl. Der Sekundärtext hält AAA auf der
   Arbeitsfläche (nachgerechnet in scripts/pruefe-kontrast.py) — "disabled" wäre zu blass für
   eine Zahl, die man lesen soll. */
.kalender-fremd {
    background: var(--color-canvas);
}

.kalender-fremd .kalender-tag-nummer {
    color: var(--color-text-secondary);
    font-weight: 400;
}

.kalender-termine {
    list-style: none;
    margin: var(--space-xs) 0 0;
    padding: 0;
    display: grid;
    gap: 2px;
}

/* Der Verweis füllt das Kästchen — ein Ziel von voller Breite und mindestens 24 px Höhe
   (WCAG 2.5.8). Der Akzentstrich links ist Wiedererkennung; die Bedeutung trägt der Text. */
.kalender-eintrag a {
    display: block;
    min-height: 24px;
    padding: 2px var(--space-s);
    border-left: 3px solid var(--color-accent);
    border-radius: var(--radius-sm);
    background: var(--color-accent-subtle);
    color: var(--color-text);
    font-size: var(--font-size-caption);
    line-height: 18px;
    text-decoration: none;
    /* Nur an Wortgrenzen — ein Wort, das nicht passt, bricht; ein Satz bricht nicht nach
       jedem Buchstaben. */
    overflow-wrap: break-word;
}

.kalender-eintrag a:hover {
    background: var(--color-surface-hover);
    text-decoration: underline;
}

.kalender-zeit {
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}

.kalender-monat .kalender-zeit::after {
    content: " ";
}

/* In Woche und Tag stehen Zeit, Thema und Nebenangabe untereinander. */
.kalender-woche .kalender-zeit,
.kalender-woche .kalender-thema,
.kalender-tagesliste .kalender-zeit,
.kalender-tagesliste .kalender-thema,
.kalender-eintrag .caption {
    display: block;
}

/* Abgesagt: durchgestrichen UND als Wort im Verweis — Form und Text, nie nur Farbe. */
.kalender-abgesagt a {
    border-left-color: var(--color-stroke-accessible);
    background: var(--color-surface-hover);
    color: var(--color-text-secondary);
}

.kalender-abgesagt .kalender-thema {
    text-decoration: line-through;
}

/* Intern: gestrichelter Rand — der Betrieb sieht diesen Termin nicht. Das Wort dazu steht im
   Verweis. */
.kalender-intern a {
    border-left-style: dashed;
}

/* Die Tagesansicht: dieselben Einträge, größer und untereinander. */
.kalender-tagesliste {
    margin: 0;
    gap: var(--space-s);
}

.kalender-tagesliste .kalender-eintrag a {
    padding: var(--space-s) var(--space-m);
    font-size: var(--font-size-body);
    line-height: 20px;
}

/* Die Leiste über dem Raster: Zurück/Heute/Weiter, die Überschrift des Zeitraums, daneben der
   Standort. Auf einem schmalen Fenster bricht sie um — die Überschrift zuerst. */
.kalender-leiste {
    align-items: center;
}

.kalender-titel {
    flex: 1 1 200px;
    margin: 0;
    font-size: var(--font-size-subtitle);
}

.kalender-filter {
    display: flex;
    align-items: flex-end;
    flex-wrap: wrap;
    gap: var(--space-m);
}

.kalender-filter .field {
    min-width: 200px;
    flex: 1 1 200px;
}

/*
 * Text, in dem die Zeilenumbrüche des Verfassers etwas bedeuten: eine Nachricht, eine
 * Tagesordnung. Sie bleiben erhalten, ohne dass HTML erlaubt wäre — der Text wird von Razor
 * escaped, 'pre-wrap' macht nur die Umbrüche sichtbar. 'overflow-wrap' verhindert, dass eine
 * lange Zeichenkette ohne Leerzeichen die Seite in die Breite zieht.
 */
.mehrzeilig {
    margin: 0;
    white-space: pre-wrap;
    overflow-wrap: anywhere;
}

/*
 * Breitere Karten für die Übersicht: Ein Betrieb mit mehreren Standorten braucht mehr Platz als
 * eine Kennzahlenkachel, sonst bricht jede Zeile um.
 */
.card-grid-wide {
    grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
}

.card-title {
    margin-top: 0;
    margin-bottom: var(--space-xs);
    font-size: var(--font-size-subtitle);
}

/*
 * Die Merkliste unter dem Suchfeld der Startseite.
 *
 * .card-title nimmt den oberen Abstand weg, weil eine Kartenüberschrift üblicherweise das erste
 * Element der Karte ist. Hier steht sie hinter einem Formular und braucht ihn zurück — sonst
 * klebt "Zuletzt geöffnet" an der Schaltfläche "Suchen" und liest sich wie deren Beschriftung.
 */
.zuletzt-ueberschrift {
    margin-top: var(--space-l);
}

/*
 * Auswahlfeld und Schaltfläche nebeneinander innerhalb einer Tabellenzelle.
 * Umbruch erlaubt (wrap), damit die Zelle auf schmalen Bildschirmen nicht die Tabelle sprengt.
 */
.field-row-tight {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-xs);
    align-items: center;
}

.field-row-tight select {
    width: auto;
    min-width: 12ch;
}

/*
 * Aufzählung ohne Punkte und Einzug — für kurze Listen innerhalb einer Tabellenzelle.
 * Bewusst eine Liste und kein <br>-getrennter Text: Screenreader kündigen die Anzahl der Einträge
 * an, was bei Mandantenzugehörigkeiten die eigentliche Information ist (WCAG 1.3.1).
 */
.plain-list {
    margin: 0;
    padding: 0;
    list-style: none;
}

.plain-list > li + li {
    margin-top: var(--space-xs);
}

/*
 * Die Standorte eines Betriebs, aufklappbar in der Betriebsliste.
 *
 * Dasselbe Zeichen und dieselbe Drehung wie bei den Gruppen der Seitenleiste und in den
 * Brotkrumen: Die Anwendung führt für „hier lässt sich etwas aufklappen" genau eine Formsprache.
 * Die Aussage hängt nicht am Zeichen — 'details' trägt 'aria-expanded' von sich aus (WCAG 1.4.1).
 *
 * Die Zeile wächst beim Aufklappen nach unten. Das stört die übrigen Spalten nicht, weil
 * 'tbody td' nach oben ausrichtet; sie bleiben auf Höhe des Betriebsnamens stehen.
 */
.standortgruppe > summary {
    display: flex;
    align-items: center;
    gap: var(--space-xs);

    /* 24 px hoch: das geforderte Mindestziel (WCAG 2.5.8). Nicht breiter als nötig, damit der
       Klick auf die freie Fläche der Zelle nicht ins Aufklappen läuft. */
    min-height: 24px;
    width: fit-content;
    margin-top: var(--space-xs);
    color: var(--color-text-secondary);
    font-size: var(--font-size-caption);
    cursor: pointer;
}

/* Safari zeigt sein eigenes Dreieck auch dann noch, wenn 'display: flex' das Listenzeichen der
   übrigen Browser längst entfernt hat. Sonst stünden dort zwei Zeichen nebeneinander. */
.standortgruppe > summary::-webkit-details-marker {
    display: none;
}

.standortgruppe > summary::before {
    content: "›";
    flex: 0 0 auto;
}

.standortgruppe[open] > summary::before {
    transform: rotate(90deg);
}

.standortgruppe > summary:hover {
    color: var(--color-text);
}

/* Eingerückt auf die Fluchtlinie hinter dem Aufklappzeichen: Die Standorte gehören sichtbar zum
   Betrieb darüber und nicht in dieselbe Spalte wie er. */
.standortgruppe > ul {
    margin: var(--space-xs) 0 var(--space-xs) var(--space-m);
}

/* ── Dokumentenablage ───────────────────────────────────────────────────────────────────────── */

/*
 * Die Einrückung der Ordnerebenen.
 *
 * Über ein Datenattribut und feste Regeln statt über ein 'style'-Attribut: Die CSP verbietet
 * Inline-Stile, und eine berechnete Einrückung im Markup wäre genau das. Die Tiefe ist auf fünf
 * begrenzt — fünf Regeln genügen.
 *
 * Die Einrückung ist Gestaltung, nicht Bedeutung: Die Ebene steht zusätzlich als Text in der
 * Zelle. Wer die Seite vorgelesen bekommt, verliert die Struktur sonst.
 */
.ordner-name {
    display: inline-block;
}

.ordner-name[data-ebene="2"] { padding-left: var(--space-l); }
.ordner-name[data-ebene="3"] { padding-left: calc(var(--space-l) * 2); }
.ordner-name[data-ebene="4"] { padding-left: calc(var(--space-l) * 3); }
.ordner-name[data-ebene="5"] { padding-left: calc(var(--space-l) * 4); }

/* ── Bestätigung in zwei Schritten ──────────────────────────────────────────────────────────── */

/*
 * Der QR-Code steht auf eigener weißer Fläche.
 *
 * Kein Schmuck: Ein QR-Code braucht Kontrast zwischen Modulen und Grund. Im dunklen Modus
 * mitzuwandern machte ihn unlesbar — die Kamera sieht dann hell auf hell.
 */
.qr-flaeche {
    display: inline-block;
    padding: var(--space-m);
    background: var(--color-qr-grund);
    border-radius: var(--radius-sm);
    border: 1px solid var(--color-stroke);
}

/* Der Aushang am Verbandkasten (ADR 0034): groß genug, um aus einem Schritt Abstand gelesen zu
   werden, und die Adresse darunter umbrechbar — sie ist lang und muss notfalls abgetippt werden. */
.aushang {
    max-width: 40rem;
}

.aushang h1 {
    font-size: var(--font-size-display);
}

.aushang-adresse code {
    overflow-wrap: anywhere;
}

/* Der Datenschutzhinweis auf dem Aushang: zugeklappt, damit das Formular vorne steht — aber vor
   dem Absenden erreichbar, als natives <details> mit Tastatur und Bildschirmleser bedienbar. */
.datenschutzhinweis {
    margin: var(--space-m) 0;
}

.datenschutzhinweis h3 {
    font-size: inherit;
    margin: var(--space-m) 0 var(--space-xs);
}

/* Wiederherstellungscodes: nebeneinander, damit die Liste nicht zehn Zeilen hoch wird. */
.code-liste {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-s) var(--space-l);
    margin: var(--space-m) 0 0;
    padding: 0;
    list-style: none;
}


/* ── Darstellung: was der Leser selbst einstellt ────────────────────────────────────────────────
 *
 * NUR auf der öffentlichen Prüfabfrage. Im Portal gibt es das bewusst nicht: Dort arbeiten
 * Fachkräfte täglich stundenlang, und die Einstellung gehört dann ins Betriebssystem und in den
 * Browser, nicht in jede einzelne Anwendung. Hier ist die Lage umgekehrt — jemand steht mit einem
 * fremden Telefon in einer Werkhalle, liest einmal etwas ab und kommt vielleicht nie wieder.
 *
 * WAS ES NICHT GIBT, UND WARUM
 *
 * „Weniger Kontrast" fehlt mit Absicht. Es ist die einzige der gewünschten Einstellungen, die die
 * Seite messbar schlechter macht: Der Fließtext erfüllt heute AAA (7:1), und jede Absenkung
 * führte darunter. Wer es blasser braucht, hat dafür die Systemeinstellung — die respektiert die
 * Seite bereits.
 *
 * „Kleiner" gibt es nur bis zur Vorgabe zurück. Unter 14 px verlöre der Fließtext seine
 * Lesbarkeit, und eine Einstellung, die die Seite unbrauchbar macht, ist keine Hilfe.
 */

/*
 * Größere Schrift: die Größen-Token, nicht die Wurzelschrift.
 *
 * 'font-size' am ':root' wäre der kürzere Weg und der falsche: Die Token dieser Anwendung sind
 * px (app.css oben), und px wächst nicht mit. Es sähe aus, als täte der Knopf nichts.
 *
 * Die Zeilenhöhen wachsen mit — sonst rücken die Zeilen bei 20-px-Schrift auf 20 px Höhe
 * zusammen (WCAG 1.4.12).
 */
:root[data-schrift="gross"] {
    --font-size-caption: 14px;
    --font-size-body: 16px;
    --font-size-subtitle: 18px;
    --font-size-title: 22px;
    --font-size-display: 32px;
}

:root[data-schrift="sehr-gross"] {
    --font-size-caption: 16px;
    --font-size-body: 19px;
    --font-size-subtitle: 21px;
    --font-size-title: 26px;
    --font-size-display: 36px;
}

:root[data-schrift="gross"] body,
:root[data-schrift="sehr-gross"] body {
    line-height: 1.5;
}

/*
 * Hoher Kontrast auf Wunsch — dieselben Werte, die auch 'prefers-contrast: more' setzt.
 *
 * Zwei Stellen mit denselben vier Werten, und das ist hier nicht zu vermeiden: CSS kann „das
 * System verlangt es ODER der Leser hat es gewählt" in einer Regel nicht ausdrücken. Wer einen
 * Wert ändert, ändert ihn im Block weiter oben mit — die beiden verweisen deshalb aufeinander.
 */
:root[data-kontrast="hoch"] {
    --color-stroke: #767676;
    --color-stroke-strong: #4d4d4d;
    --color-stroke-accessible: #242424;
    --color-text-secondary: #242424;
}

:root[data-kontrast="hoch"][data-theme="dark"] {
    --color-stroke: #8f8f8f;
    --color-stroke-strong: #c7c7c7;
    --color-stroke-accessible: #f5f5f5;
    --color-text-secondary: #f5f5f5;
}

/*
 * Die Leiste steht am Fuß des Blattes, über den Rechtsverweisen.
 *
 * Nicht oben vor der Überschrift: Die Einstellung wird einmal getroffen, die Frage der Seite bei
 * jedem Aufruf gestellt. Wer mit der Tastatur oder einem Vorleseprogramm arbeitet, träfe sonst
 * bei jedem Besuch zuerst auf die Darstellungswahl und erst danach auf das Eingabefeld.
 *
 * Ohne Skript bleibt sie verborgen ('hidden' im Markup, entfernt vom Skript): Schalter, die
 * nichts tun, sind schlimmer als keine.
 */
.darstellung {
    margin-top: var(--space-xl);
    padding-top: var(--space-l);
    border-top: 1px solid var(--color-stroke);
}

.darstellung > summary {
    display: flex;
    align-items: center;
    gap: var(--space-s);
    min-height: 32px;
    padding: 0 var(--space-s);
    border-radius: var(--radius-sm);
    color: var(--color-text-secondary);
    font-size: var(--font-size-body);
    cursor: pointer;
}

.darstellung > summary:hover {
    background: var(--color-surface-hover);
    color: var(--color-text);
}

.darstellung > summary::-webkit-details-marker {
    display: none;
}

/* Das Zeichen dreht sich beim Aufklappen — die Bewegung ist die Rückmeldung, dass etwas
   aufgegangen ist. Bei 'prefers-reduced-motion' entfällt sie (Block weiter unten). */
.darstellung > summary::before {
    content: "▸";
    transition: transform 120ms ease-out;
}

.darstellung[open] > summary::before {
    transform: rotate(90deg);
}

.darstellung-gruppen {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-l);
    margin-top: var(--space-m);
    padding: 0 var(--space-s);
}

.darstellung-gruppe {
    margin: 0;
    padding: 0;
    border: 0;
}

.darstellung-gruppe > legend {
    padding: 0;
    color: var(--color-text-secondary);
    font-size: var(--font-size-caption);
    font-weight: 600;
}

/*
 * Die Schaltflächen einer Gruppe stehen nebeneinander wie ein Segmentschalter.
 *
 * Echte Schaltflächen und keine Radioknöpfe: Es wird nichts abgeschickt, die Wirkung tritt sofort
 * ein. 'aria-pressed' sagt einem Vorleseprogramm, welche gerade gilt — Farbe allein trüge die
 * Bedeutung nicht (WCAG 1.4.1).
 */
.darstellung-wahl {
    display: flex;
    gap: var(--space-xs);
    margin-top: var(--space-xs);
}

.darstellung-wahl > button {
    min-width: 44px;
    min-height: 32px;
}

.darstellung-wahl > button[aria-pressed="true"] {
    background: var(--color-accent-subtle);
    border-color: var(--color-accent);
    color: var(--color-text);
    font-weight: 600;
}

/* ── Zuletzt abgefragt ─────────────────────────────────────────────────────────────────────────
 *
 * Der Verlauf liegt im Browser des Lesers und nirgendwo sonst. Er steht unter dem Ergebnis, nicht
 * darüber: Gesucht wird die Antwort auf die eben gestellte Frage; was vorher war, ist Beiwerk.
 */
.verlauf {
    margin-top: var(--space-xl);
}

.verlauf-kopf {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--space-m);
}

/* ── Senkrechter Rhythmus zwischen Blöcken ──────────────────────────────────────────────────── */

/*
 * Was auf einen Block folgt, bekommt Abstand nach oben — an EINER Stelle für alle.
 *
 * Vorher trugen die Blöcke nur einen Abstand nach UNTEN, und 'card' und 'list-surface' gar
 * keinen. Ein Hinweis direkt hinter einer Tabelle klebte deshalb daran, und der nächste Block
 * hinter einer Karte ebenso. Der Fehler trat an vielen Stellen auf, weil er keine Stelle hatte:
 * Er entstand aus der Abwesenheit einer Regel.
 *
 * Der Nachbarschaftsselektor greift nur zwischen Geschwistern und nur NACH einem dieser Blöcke.
 * Abschnittsüberschriften ('h2', '.section-header') nimmt er aus: Sie bringen ihren eigenen,
 * größeren Abstand mit (32 px, docs/design.md §5). Vorher überstimmte diese Regel ihn mit höherer
 * Spezifität — eine 'h2' hinter einer Liste stand 24 px tief, eine hinter dem Untertitel 32 px.
 * ':where' hält die Ausnahme ohne Gewicht, die Regel wiegt so viel wie zuvor.
 *
 * Auf '.content' eingeengt, und das ist keine Vorsicht: Ohne die Einengung traf 'form + *' auch
 * das Suchfeld in der Navigation, und die Einträge darunter rutschten weg. Eine Regel für den
 * Lesefluss der Seite hat in der Navigationsspalte nichts zu suchen.
 */
.content .card + :where(:not(h2, .section-header)),
.content .list-surface + :where(:not(h2, .section-header)),
.content .notice + :where(:not(h2, .section-header)),
.content .command-bar + :where(:not(h2, .section-header)),
.content .empty-state + :where(:not(h2, .section-header)),
.content .pager + :where(:not(h2, .section-header)),
.content .ablagepfad + :where(:not(h2, .section-header)),
.content .nebenaktionen + :where(:not(h2, .section-header)),
.content form + :where(:not(h2, .section-header)) {
    margin-top: var(--space-xl);
}

/*
 * ... und unter der Hauptüberschrift, sobald dort kein Untertitel steht.
 *
 * 'h1' gibt nach unten nur '--space-xs' ab, also vier Pixel. Das ist richtig, solange der
 * Untertitel folgt: '.lead' gehört zur Überschrift und soll an ihr hängen — so steht es auf 46
 * der 69 Seiten. Auf den übrigen 23 beginnt direkt darunter ein Block, eine Karte, ein Formular,
 * ein Hinweis, und der klebte an der Überschrift. Die größte Überschrift der Seite hatte damit
 * den kleinsten Abstand nach unten: weniger als 'h2' (12 px) und weniger als 'h3' (8 px).
 *
 * Der Abstand sitzt deshalb am Nachbarn und nicht an der Überschrift. Am Untertitel ändert sich
 * dadurch nichts, und alles andere bekommt Luft. Sechzehn Pixel führen kein neues Maß ein,
 * sondern setzen die Reihe fort: h3 8, h2 12, h1 16.
 */
.content h1 + *:not(.lead) {
    margin-top: var(--space-l);
}

/*
 * ... aber NICHT innerhalb eines Rasters oder einer Flex-Reihe.
 *
 * Dort macht 'gap' den Abstand. Ein zusätzlicher Außenabstand am Rasterkind verschiebt es nach
 * unten UND verkürzt es um denselben Betrag — die Karten einer Reihe stehen dann auf
 * verschiedenen Höhen. Sichtbar wurde das erst bei zwei Karten ungleicher Höhe (die
 * Anbieterauswahl); bei den gleich hohen Kennzahlkacheln fiel es jahrelang nicht auf.
 *
 * Die Regel oben gilt dem Lesefluss der Seite. Ein Raster ist keiner.
 */
.content .card-grid > *,
.content .nebenaktionen > *,
.content .command-bar-actions > * {
    margin-top: 0;
}

/* ── Karten ─────────────────────────────────────────────────────────────────────────────────── */

.card {
    padding: var(--space-l);
    background: var(--color-surface);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-2);
}

/* Die erste Überschrift einer Karte bringt ihren Abschnittsabstand nicht mit hinein: Über ihr
   steht schon der Innenabstand der Karte. Sonst stünde „Antworten" 48 px unter der Kante. */
.card > :is(h2, h3, .section-header):first-child {
    margin-top: 0;
}

/*
 * Absätze auf dem Blatt und in Karten: Abstand nur nach unten, aus der Tokenreihe. Ohne diese
 * Regel galt die Vorgabe des Browsers (1 em oben und unten, also 14 px) — ein Maß außerhalb der
 * Reihe, und eine Karte mit einem Absatz hatte oben 30 px Luft und unten 30 px statt 16.
 * ':where' wiegt nichts: '.lead', '.notice p' und die übrigen Bausteine behalten ihren Abstand.
 */
:where(.content, .card) > p {
    margin-block: 0 var(--space-m);
}

.card > :last-child {
    margin-bottom: 0;
}

.card-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
    gap: var(--space-l);
}

.kpi {
    font-size: var(--font-size-display);
    font-weight: 600;
    line-height: 36px;
}

.kpi-label {
    margin-top: var(--space-xs);
    color: var(--color-text-secondary);
    font-size: var(--font-size-caption);
}

/* ── Der Betrieb auf einen Blick (ADR 0051) ─────────────────────────────────────────────────────
 *
 * Kacheln, die als Ganzes in ihren Reiter führen: Titel mit Symbol, eine große Zahl, ein Satz
 * darunter, ein Hinweis. Auf dem Blatt mit feinem Rahmen wie jede Karte, beim Überfahren
 * leicht eingefärbt wie eine Listenzeile — sie sind Wege, keine Anzeigen. Ein Schatten hob sie
 * vorher an; auf dem Blatt schwebt aber nichts (docs/design.md §2). Die große Zahl ist Schrift, nicht Farbe;
 * was dringlich ist, sagt ein Abzeichen mit Wort (WCAG 1.4.1).
 */
.blick {
    margin-bottom: var(--space-xl);
}

.kachelreihe {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
    gap: var(--space-m);
}

.kachel {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--space-xs);
    padding: var(--space-l);
    border: 1px solid var(--color-stroke);
    border-radius: var(--radius-md);
    background: var(--color-surface);
    color: var(--color-text);
    text-decoration: none;
}

.kachel:hover {
    color: var(--color-text);
    text-decoration: none;
    border-color: var(--color-stroke-strong);
    background: var(--color-surface-hover);
}

.kachel-titel {
    display: inline-flex;
    align-items: center;
    gap: var(--space-s);
    color: var(--color-text-secondary);
    font-size: var(--font-size-caption);
    font-weight: 600;
}

.kachel-titel .nav-symbol {
    width: 16px;
    height: 16px;
}

.kachel-wert {
    margin-top: var(--space-xs);
    font-size: var(--font-size-display);
    font-weight: 600;
    line-height: 1;
    letter-spacing: -0.01em;
    font-variant-numeric: tabular-nums;
}

.kachel-text {
    font-weight: 600;
}

.kachel-hinweis {
    color: var(--color-text-secondary);
    font-size: var(--font-size-caption);
}

/* Darunter: was als Nächstes zu tun ist und ansteht — zwei kurze Listen nebeneinander. */
.blick-listen {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
    gap: var(--space-xl);
    margin-top: var(--space-xl);
}

.blick-liste h3 {
    margin-top: 0;
}

.blick-liste ul {
    margin: 0;
    padding: 0;
    list-style: none;
}

.blick-liste li {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: var(--space-xs) var(--space-s);
    padding: var(--space-s) 0;
    border-bottom: 1px solid var(--color-stroke);
}

.blick-liste li:last-child {
    border-bottom: none;
}

/* ── Verlauf: eine Zahl über die Zeit (docs/design.md §7) ──────────────────────────────────────
 *
 * Eine einzige Linie in der Verweisfarbe, feines Raster, die Skala links und die Zeitachse darunter
 * als HTML in der Hausschrift. Das SVG wird in der Breite gestreckt ('preserveAspectRatio="none"');
 * 'vector-effect' hält die Striche dabei gleich dick. Keine Fläche unter der Linie, kein Verlauf,
 * keine Punkte — es geht um die Richtung (§10).
 */
/* In der Kachel: nur die Linie, über die ganze Breite, unter dem Hinweis. */
.verlauf-spur {
    display: block;
    align-self: stretch;
    margin-top: var(--space-s);
}

.verlauf-spur .verlauf-bild {
    height: 32px;
}

.verlauf {
    margin: 0;
}

.verlauf-flaeche {
    display: grid;
    grid-template-columns: auto 1fr;
    gap: var(--space-s);
}

.verlauf-skala {
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    align-items: flex-end;
    color: var(--color-text-secondary);
    font-size: var(--font-size-caption);
    font-variant-numeric: tabular-nums;
    line-height: 1;
}

.verlauf-bild {
    display: block;
    width: 100%;
    height: 120px;
    overflow: visible;
}

.verlauf-raster {
    stroke: var(--color-stroke);
    stroke-width: 1;
}

.verlauf-grundlinie {
    stroke: var(--color-stroke-accessible);
    stroke-width: 1;
}

.verlauf-linie {
    fill: none;
    stroke: var(--color-link);
    stroke-width: 2;
    stroke-linejoin: round;
    stroke-linecap: round;
}

.verlauf-achse {
    display: flex;
    justify-content: space-between;
    margin-top: var(--space-xs);
    color: var(--color-text-secondary);
    font-size: var(--font-size-caption);
}

.verlauf-werte {
    margin-top: var(--space-s);
}

.verlauf-werte summary {
    cursor: pointer;
    color: var(--color-link);
    font-size: var(--font-size-caption);
}

@media (forced-colors: active) {
    .verlauf-linie {
        stroke: CanvasText;
    }

    .verlauf-raster,
    .verlauf-grundlinie {
        stroke: GrayText;
    }
}

/* ── Posteingang (Nachrichten) ──────────────────────────────────────────────────────────────────
 *
 * Je Vorgang eine Zeile wie in Teams oder Outlook: Kreis mit den Anfangsbuchstaben des Betriebs,
 * Betreff und Zeit, darunter Ort und Thema, darunter eine Zeile Vorschau. Die ganze Zeile öffnet
 * den Vorgang (der Betreff ist der Verweis, '::after' zieht seine Fläche auf die Zeile).
 *
 * Ungelesen: fetter Betreff, Punkt davor, Zeit in der Markenfarbe, Kreis zart getönt — und das
 * Wort „neu". Die Farbe ist nie das einzige Merkmal (WCAG 1.4.1).
 */
.posteingang {
    margin: 0;
    padding: 0;
    list-style: none;
    border: 1px solid var(--color-stroke);
    border-radius: var(--radius-md);
    background: var(--color-surface);
}

.posteingang-eintrag {
    position: relative;
    display: flex;
    gap: var(--space-m);
    padding: var(--space-m) var(--space-l);
    border-bottom: 1px solid var(--color-stroke);
}

.posteingang-eintrag:first-child {
    border-radius: var(--radius-md) var(--radius-md) 0 0;
}

.posteingang-eintrag:last-child {
    border-bottom: none;
    border-radius: 0 0 var(--radius-md) var(--radius-md);
}

.posteingang-eintrag:hover {
    background: var(--color-surface-hover);
}

.posteingang-zeichen {
    display: grid;
    flex: none;
    place-items: center;
    width: 40px;
    height: 40px;
    border-radius: 50%;
    background: var(--color-accent-subtle);
    color: var(--color-text);
    font-size: var(--font-size-caption);
    font-weight: 600;
}

.ist-neu .posteingang-zeichen {
    background: var(--color-accent-tint);
    color: var(--color-accent);
}

.posteingang-inhalt {
    flex: 1;
    min-width: 0;
}

.posteingang-kopf {
    display: flex;
    align-items: baseline;
    gap: var(--space-s);
    min-width: 0;
}

/* Der Betreff in Textfarbe, nicht als blauer Verweis: In einem Posteingang ist die ganze Zeile
   der Verweis, und die Zeile zeigt das beim Überfahren. */
.posteingang-betreff,
.posteingang-kopf .raumverweis button {
    overflow: hidden;
    min-width: 0;
    padding: 0;
    border: 0;
    background: none;
    color: var(--color-text);
    font: inherit;
    font-weight: 400;
    text-align: start;
    text-overflow: ellipsis;
    white-space: nowrap;
    cursor: pointer;
}

.posteingang-betreff:hover,
.posteingang-kopf .raumverweis button:hover {
    color: var(--color-text);
    text-decoration: underline;
}

.posteingang-kopf .raumverweis {
    display: contents;
}

.posteingang-kopf .raumverweis button::after {
    content: "";
    position: absolute;
    inset: 0;
}

.posteingang-eintrag .badge {
    position: relative;
    z-index: 1;
}

.ist-neu .posteingang-betreff,
.ist-neu .posteingang-kopf .raumverweis button {
    font-weight: 600;
}

.ist-neu .posteingang-kopf::before {
    content: "";
    flex: none;
    align-self: center;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--color-accent);
}

.posteingang-zeit {
    flex: none;
    margin-left: auto;
    color: var(--color-text-secondary);
    font-size: var(--font-size-caption);
    font-variant-numeric: tabular-nums;
}

.ist-neu .posteingang-zeit {
    color: var(--color-accent);
    font-weight: 600;
}

.posteingang-ort {
    margin: 2px 0 0;
    color: var(--color-text-secondary);
    font-size: var(--font-size-caption);
}

.posteingang-vorschau {
    overflow: hidden;
    margin: 2px 0 0;
    color: var(--color-text-secondary);
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Abgeschlossene Vorgänge treten zurück; lesbar bleiben sie vollständig. */
.ist-abgeschlossen .posteingang-betreff {
    color: var(--color-text-secondary);
}

/* ── Werkzeugleiste ─────────────────────────────────────────────────────────────────────────── */

.command-bar {
    display: flex;
    align-items: flex-end;
    flex-wrap: wrap;
    gap: var(--space-m);
    margin-bottom: var(--space-l);
    padding: var(--space-m) var(--space-l);
    background: var(--color-surface);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-2);
}

.command-bar .field {
    margin-bottom: 0;
    min-width: 240px;
    flex: 1 1 240px;
}

/* Ein Feld mit kurzem Inhalt (Jahr, Monat) wächst nicht über die Leiste: Allein in der Leiste
   stünde sonst eine Auswahl von vier Ziffern über 1200 px. */
.command-bar .field-kurz {
    flex-grow: 0;
}

/*
 * Eine Leiste ohne Bedienelement verschwindet. Viele Seiten füllen sie nach Recht ('@if' um jede
 * Schaltfläche); ohne Recht blieb ein leerer Flex-Behälter stehen. Weil er einen eigenen
 * Formatierungskontext bildet, fallen die Außenabstände darüber und darunter nicht durch ihn
 * hindurch zusammen — unter dem Untertitel standen dann 48 statt 24 px. An EINER Stelle statt
 * auf über 80 Seiten je eine Bedingung um die Leiste.
 */
.command-bar:not(:has(a, button, input, select, textarea, summary)) {
    display: none;
}

/*
 * Die Leiste bricht um, statt über den Rand zu laufen (WCAG 1.4.10). Ohne 'flex-wrap' schob das
 * Verbandbuch mit acht Knöpfen schon bei 1440 px den letzten aus dem Bild — und bei 400 % Zoom
 * (320 CSS-Pixel) wären die meisten nur noch per Seitwärtsscrollen erreichbar gewesen.
 * Die Regel steht hier und nicht je Seite: Über 80 Seiten tragen diese Leiste.
 */
.command-bar-actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-s);

    /* Eine Schaltfläche und ein Verweis daneben teilen sich die Mitte, nicht die Oberkante. Für
       Schaltflächen allein ändert das nichts — sie sind gleich hoch. */
    align-items: center;
}

/* ── Reiter (Fluent-2-Pivot) ────────────────────────────────────────────────────────────────── */

/*
 * Verweise, die wie Reiter aussehen — keine ARIA-Reiterrollen.
 *
 * Jeder Reiter hat eine eigene Adresse und laedt eine eigene Seite. 'role="tab"' verspraeche
 * einer Vorleseanwendung ein Umschalten ohne Seitenwechsel samt Pfeiltastenbedienung; hier ist
 * es eine Verweisliste, und als solche wird sie angesagt. Der aktive Reiter traegt
 * 'aria-current="page"' — dieselbe Auszeichnung wie in der Seitenleiste und in den Brotkrumen.
 *
 * Der Unterstrich traegt die Bedeutung NICHT allein: Der aktive Reiter ist zusaetzlich dunkler
 * und halbfett (MANIFEST §5.2 — Farbe traegt nie allein Bedeutung), und 'aria-current' sagt es
 * ohne jede Darstellung.
 */
.reiter {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-xs);
    margin-bottom: var(--space-l);
    border-bottom: 1px solid var(--color-stroke);
}

.reiter a {
    padding: var(--space-s) var(--space-m);
    border-radius: var(--radius-sm) var(--radius-sm) 0 0;
    color: var(--color-text-secondary);
    text-decoration: none;
    white-space: nowrap;

    /* Der Streifen ist immer da, nur meist unsichtbar: Ohne ihn spraenge die Zeile beim
       Wechseln um zwei Pixel. */
    border-bottom: 2px solid transparent;
    margin-bottom: -1px;

    /*
     * Der Hintergrund endet an der Innenkante, nicht am Rahmen.
     *
     * Ein Hintergrund reicht in der Vorgabe ('border-box') bis unter den EIGENEN Rahmen — auch
     * unter einen durchsichtigen. Der Reiter liegt durch 'margin-bottom: -1px' genau auf der
     * Linie von '.reiter', und weil das Kind nach dem Elternteil gemalt wird, strich der
     * Hoverton beim Zeigen die Linie unter dem Reiter weg: Sie war an dieser Stelle
     * unterbrochen, solange der Zeiger darauf stand.
     *
     * Mit 'padding-box' bleibt der durchsichtige Streifen wirklich durchsichtig, die Linie steht
     * durchgehend, und der aktive Reiter behaelt seinen Akzentstrich auch beim Zeigen.
     */
    background-clip: padding-box;
}

/*
 * 'background-color' und NICHT die Kurzschreibweise 'background'.
 *
 * Die Kurzschreibweise setzt jede nicht genannte Hintergrundeigenschaft auf ihren Ausgangswert
 * zurueck — auch das 'background-clip: padding-box' von '.reiter a' darueber. Damit galt der Fix
 * genau dort nicht, wo er gebraucht wird: beim Zeigen. Der Hoverton lief wieder unter den
 * durchsichtigen 2-px-Rahmen und strich die Linie der Reiterleiste an dieser Stelle weg.
 *
 * Nachgemessen statt vermutet: 'getComputedStyle' meldete am Reiter 'border-box', obwohl zwei
 * Regeln hoeher 'padding-box' steht.
 */
.reiter a:hover {
    color: var(--color-text);
    background-color: var(--color-surface-hover);
}

.reiter a[aria-current="page"] {
    color: var(--color-text);
    font-weight: 600;
    border-bottom-color: var(--color-accent);
}

/*
 * Reiter und ein Menü in einer Zeile (Betriebsakte: „Weiteres"). Die Grundlinie gehört der Zeile,
 * nicht der Reiterleiste, damit sie unter dem Menü weiterläuft. Das Menü sieht aus wie ein
 * Reiter — es ist der Weg zu den selteneren Bereichen der Akte. '.aktionsmenue.reiter-menue'
 * (0,2,1), weil '.aktionsmenue > summary' weiter unten in der Datei steht und sonst gewönne.
 */
.reiterzeile {
    display: flex;
    align-items: flex-end;
    gap: var(--space-xs);
    margin-bottom: var(--space-l);
    border-bottom: 1px solid var(--color-stroke);
}

.reiterzeile > .reiter {
    border-bottom: 0;

    /*
     * Nur seitlich rollen. Der aktive Reiter liegt mit 'margin-bottom: -1px' auf der Linie der
     * Zeile, damit sein Strich sie überdeckt — in einem Behälter mit 'overflow-x: auto' zählt
     * dieses Pixel als Überlauf, und die Leiste ließ sich senkrecht um ein Pixel rollen. Der
     * Innenabstand gibt dem Pixel Platz, der negative Außenabstand legt die Leiste wieder auf die
     * Linie; 'overflow-y: hidden' hält die zweite Achse still.
     */
    padding-bottom: 1px;
    margin-bottom: -1px;
    overflow-y: hidden;

    /* Neben dem Menü in einer Zeile bleiben: Reicht der Platz nicht, rollen die Reiter seitlich,
       statt dass einer allein in eine zweite Zeile rutscht und die Leiste zerreißt. */
    flex: 1 1 auto;
    min-width: 0;
    flex-wrap: nowrap;
    overflow-x: auto;
    scrollbar-width: none;
}

.reiterzeile > .reiter::-webkit-scrollbar {
    display: none;
}

.aktionsmenue.reiter-menue > summary {
    height: auto;
    padding: var(--space-s) var(--space-m);
    border: 0;
    border-bottom: 2px solid transparent;
    border-radius: 0;
    background: transparent;
    color: var(--color-text-secondary);
}

.aktionsmenue.reiter-menue > summary:hover,
.aktionsmenue.reiter-menue[open] > summary {
    background: var(--color-surface-hover);
    color: var(--color-text);
}

/*
 * Auf schmalen Geraeten laeuft die Leiste seitlich statt umzubrechen: Sieben umgebrochene
 * Reiter fuellten sonst den halben Bildschirm, bevor der Inhalt anfaengt.
 */
@media (max-width: 640px) {
    .reiter {
        flex-wrap: nowrap;
        overflow-x: auto;

        /* Nur seitlich rollen (Begründung an '.reiterzeile > .reiter'). Die Linie ist hier der
           eigene Rahmen der Leiste; der Strich des aktiven Reiters steht deshalb direkt auf ihr
           statt über ihr. */
        overflow-y: hidden;
        padding-bottom: 1px;

        /* Ohne sichtbare Leiste: Sie stand als grauer Balken auf der Grundlinie der Reiter. Man
           wischt die Reiter, und mit der Tastatur rollt der Browser den fokussierten Reiter selbst
           ins Bild. */
        scrollbar-width: none;
    }

    .reiter::-webkit-scrollbar {
        display: none;
    }
}

/* ── Listen (SharePoint-Anmutung) ───────────────────────────────────────────────────────────── */

.list-surface {
    background: var(--color-surface);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-2);

    /* Waagerecht scrollen statt abschneiden: Eine Ablageliste traegt Name, zwei Datumsangaben,
       Groesse und Sichtbarkeit — auf einem schmalen Fenster passt das nicht, und eine
       abgeschnittene Spalte ist schlechter als eine, die man erreicht. Die Seite selbst scrollt
       dabei nie waagerecht; nur dieser Kasten tut es. */
    overflow-x: auto;
    overflow-y: hidden;
}

table {
    width: 100%;
    border-collapse: collapse;
    background: var(--color-surface);

    /* Ziffern gleicher Breite in jeder Tabelle: Datumsangaben, Mengen und Kennungen stehen
       untereinander, statt zu flattern. */
    font-variant-numeric: tabular-nums;
}

.list-surface table {
    box-shadow: none;
}

thead th {
    position: sticky;
    top: 0;
    padding: var(--space-s) var(--space-m);
    text-align: left;
    background: var(--color-surface);
    border-bottom: 1px solid var(--color-stroke);
    color: var(--color-text-secondary);
    font-size: var(--font-size-caption);
    font-weight: 600;
    white-space: nowrap;
}

tbody td {
    padding: var(--space-m);
    border-bottom: 1px solid var(--color-stroke);
    vertical-align: middle;
}

tbody tr:last-child td {
    border-bottom: none;
}

tbody tr:hover {
    background: var(--color-surface-hover);
}

.numeric {
    text-align: right;
    font-variant-numeric: tabular-nums;
}

/* Eine Anschrift ist Text, keine Zahlenspalte: Gleich breite Ziffern sperren „13, 70565" sichtbar
   gegenüber derselben Anschrift in den Stammdaten. Die Tabelle setzt sie sonst für alle Zellen. */
td.anschrift {
    font-variant-numeric: normal;
}

/*
 * Die ganze Zeile ist der Verweis — wenn ihr Hauptverweis die Klasse 'zeilenverweis' trägt.
 *
 * Wer in einer Liste einen Betrieb öffnen will, zielt auf die Zeile, nicht auf das Wort. Der
 * Verweis bleibt ein echter <a> (Tastatur, Mittelklick, Bildschirmleser), nur seine Trefferfläche
 * wird über '::after' auf die Zeile gezogen. Weitere Bedienelemente in derselben Zeile liegen
 * darüber und bleiben einzeln treffbar. Opt-in: Eine Zeile mit mehreren gleichrangigen Zielen
 * bekommt die Klasse nicht.
 */
tbody tr:has(.zeilenverweis) {
    position: relative;
    cursor: pointer;
}

.zeilenverweis::after {
    content: "";
    position: absolute;
    inset: 0;
}

tbody tr:has(.zeilenverweis) :is(a, button, input, select, textarea, summary, label):not(.zeilenverweis) {
    position: relative;
    z-index: 1;
}

/* Zeilen mit langem Text sollen umbrechen, Zahlenspalten nicht — und eine E-Mail-Adresse oder ein
   Kontoname auch nicht: Am Bindestrich getrennt las sich „d.kohout@itc-" / „graf.de" wie zwei
   Angaben. Die Liste rollt dafür lieber seitlich (.list-surface). Nicht '.kennung': Die Klasse
   gehört der Betriebskennung (groß, gesperrt), und der Name lief in sie hinein. */
td.numeric,
th.numeric,
td.ungebrochen {
    white-space: nowrap;
}

/* ── Abzeichen ──────────────────────────────────────────────────────────────────────────────── */

.badge {
    display: inline-flex;
    align-items: center;
    height: 20px;
    padding: 0 var(--space-s);
    border-radius: var(--radius-pill);
    background: var(--color-surface-hover);
    color: var(--color-text-secondary);
    font-size: var(--font-size-caption);
    font-weight: 600;
    white-space: nowrap;
}

.badge-accent {
    background: var(--color-accent-subtle);
    color: var(--color-text);
}

/* Statusabzeichen tragen einen Punkt in ihrer Farbe vor dem Wort: Der Zustand ist so auch in
   einer langen Spalte mit einem Blick erfassbar. Die Bedeutung trägt weiter das Wort (WCAG 1.4.1). */
.badge-success::before,
.badge-warning::before,
.badge-danger::before {
    content: "";
    flex: none;
    width: 6px;
    height: 6px;
    margin-right: 6px;
    border-radius: 50%;
    background: currentColor;
}

.badge-success {
    background: var(--color-success-subtle);
    color: var(--color-success);
}

.badge-warning {
    background: var(--color-warning-subtle);
    color: var(--color-warning);
}

.badge-danger {
    background: var(--color-danger-subtle);
    color: var(--color-danger);
}

/* ── Schaltflächen ──────────────────────────────────────────────────────────────────────────── */

.button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-s);
    min-height: var(--control-height);
    padding: 0 var(--space-m);
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    background: var(--color-accent-bg);
    color: var(--color-on-accent);
    font-family: inherit;
    font-size: var(--font-size-body);
    font-weight: 600;
    white-space: nowrap;
    cursor: pointer;
}

.button:hover {
    background: var(--color-accent-bg-hover);
    color: var(--color-on-accent);
    text-decoration: none;
}

.button:active {
    background: var(--color-accent-bg-pressed);
}

/* Standardschaltfläche: Fläche mit Rahmen, wie in Fluent. */
.button-default {
    background: var(--color-surface);
    border-color: var(--color-stroke-accessible);
    color: var(--color-text);
}

.button-default:hover {
    background: var(--color-surface-hover);
    color: var(--color-text);
}

.button-default:active {
    background: var(--color-surface-pressed);
}

/* Gesperrt — etwa „Teilen" über der Ablage, solange nichts ausgewählt ist. Ohne diese Regel sah
   eine gesperrte Schaltfläche aus wie eine bedienbare. Neutral wie in Fluent; gesperrte
   Bedienelemente sind von WCAG 1.4.3 ausgenommen. */
.button:disabled,
.button:disabled:hover {
    background: var(--color-surface-hover);
    border-color: var(--color-stroke);
    color: var(--color-text-disabled);
    cursor: not-allowed;
}

/* Dezente Schaltfläche: ohne Rahmen, für Aktionen in Listen und Kopfzeile. */
.button-subtle {
    background: transparent;
    border-color: transparent;
    color: var(--color-text);
    font-weight: 400;
}

.button-subtle:hover {
    background: var(--color-surface-hover);
    color: var(--color-text);
}

/* Eine Schaltfläche, die wie ein Verweis aussieht: Sie öffnet etwas und gehört deshalb in die
   Optik eines Verweises, löst dabei aber einen Wechsel der Sitzung aus und muss ein Formular sein
   (ADR 0047, Schritt 3a — „im Betriebsraum öffnen“). Farben und Hover wie bei 'a'. */
.button-verweis {
    background: none;
    border: 0;

    /* 2 px oben und unten machen aus 20 px Zeilenhöhe 24 px Trefferfläche (WCAG 2.5.8). Der
       negative Außenabstand nimmt dieselben 2 px wieder heraus, damit die Zeile im Textfluss
       nicht höher wird als die eines Verweises daneben. */
    padding: 2px 0;
    margin-block: -2px;
    min-height: 0;
    font: inherit;
    font-weight: inherit;
    color: var(--color-link);
    text-align: start;
    cursor: pointer;
}

.button-verweis:hover {
    color: var(--color-link-hover);
    text-decoration: underline;
}

/* Das Formular darum steht im Fluss wie ein Verweis: Abzeichen und Umbruch dahinter verhalten
   sich wie bei einem <a>. */
.raumverweis {
    display: inline;
    margin: 0;
}

.button-icon {
    width: var(--control-height);
    padding: 0;
}

.button-icon svg {
    width: 20px;
    height: 20px;
    fill: currentColor;
}

/*
 * Eine Schaltfläche über die volle Breite ihres Behälters.
 *
 * Für Formulare mit genau EINER Hauptaktion und ohne Nebenaktion daneben — heute die vier Seiten
 * vor der Anmeldung. Dort gibt es nichts zu wählen: Wer die Karte ausgefüllt hat, will sie
 * abschicken. Eine schmale Schaltfläche an der rechten Kante lässt danach suchen, eine breite
 * ist das Ziel.
 *
 * Ausdrücklich ein Zusatz und keine neue Sorte Schaltfläche (MANIFEST §3): Farbe, Höhe, Radius
 * und Schrift bleiben '.button'. In Listen, Werkzeugleisten und Dialogen mit mehreren Aktionen
 * hat sie nichts zu suchen — dort behauptete sie einen Vorrang, den es nicht gibt.
 */
.button-block {
    width: 100%;
}

/* ── Formulare ──────────────────────────────────────────────────────────────────────────────── */

/* Feldgruppen. fieldset/legend statt Überschriften, damit ein Screenreader die Zugehörigkeit
   ansagt („Anschrift, Postleitzahl, Eingabefeld") — eine <h2> davor leistet das nicht
   (WCAG 1.3.1). Der Browser-Standardrahmen wird entfernt; die Gliederung tragen Abstand und
   Beschriftung. */
.field-group {
    margin: 0 0 var(--space-xl);
    padding: 0;
    border: 0;
}

.field-group > legend {
    margin: 0 0 var(--space-m);
    padding: 0;
    font-size: var(--font-size-subtitle);
    font-weight: 600;
    line-height: 22px;
}

/* Eine Gruppe, die zu einer Wahl in der äußeren Gruppe gehört (etwa „Angaben für die neue Akte"),
   rückt unter diese Wahl ein: Die Zugehörigkeit trägt fieldset/legend für Bildschirmleser, der
   Einzug zeigt sie auch sehend (WCAG 1.3.1). Die Beschriftung ist eine Stufe kleiner als die äußere. */
.field-group .field-group {
    margin-inline-start: var(--space-xl);
    margin-bottom: var(--space-l);
}

.field-group .field-group > legend {
    font-size: inherit;
}

.field {
    margin-bottom: var(--space-l);
}

.field-row {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: var(--space-l);
}

/*
 * Ein Feld, das allein in einer Zeile steht, füllt die Karte nicht bis zum Rand.
 *
 * Der Grund ist nicht Geschmack: Bei einem Eingabefeld über die halbe Bildschirmbreite verliert
 * das Auge auf dem Rückweg vom Ende der Eingabe die Zuordnung zur Beschriftung links. Dieselbe
 * Regel gilt für Fließtext seit dem Buchdruck.
 *
 * Felder in einem Raster sind ausdrücklich ausgenommen — dort teilt das Raster die Breite bereits
 * auf, und ein zusätzlicher Deckel ließe die Spalten ausgefranst enden.
 */
.field > input,
.field > select {
    max-width: 60ch;
}

.field > textarea {
    max-width: 90ch;
}

/*
 * Die Ausnahme, und der Grund für die Reihenfolge: Im Raster teilt bereits die Spalte die Breite
 * auf. Ein zweiter Deckel darin ließe die Spalten unterschiedlich weit enden — die Felder stünden
 * nebeneinander, ihre rechten Kanten aber nicht.
 */
.field-row .field > input,
.field-row .field > select,
.field-row .field > textarea {
    max-width: none;
}

label {
    display: block;
    margin-bottom: var(--space-xs);
    font-size: var(--font-size-body);
    font-weight: 600;
}

/* Eingabefelder füllen ihre Zeile — Kästchen und Radioknöpfe ausdrücklich NICHT.
   Ohne diesen Ausschluss war jedes Kästchen ein bildschirmbreiter, 32 Pixel hoher Kasten mit
   Rahmen, in dessen Mitte das Häkchen schwebte, und die Beschriftung wurde in eine schmale
   Spalte daneben gequetscht. Das betraf jede Stelle mit einem Kästchen: Addons, zweiter Faktor,
   Import. Ein Fehler ohne eigenen Ort — er entstand aus einem zu weit gefassten Selektor.

   Der Ausschluss steht in ':where()', und das ist kein Schönheitsfehler: ':where()' zählt bei
   der Spezifität nicht mit. Mit einem nackten ':not()' stiege sie von (0,0,1) auf (0,2,1), und
   jede Komponentenregel, die dieses Grundmuster überschreibt — etwa das rahmenlose Suchfeld in
   der Kopfzeile —, verlöre plötzlich. Genau das ist beim ersten Anlauf passiert. */
input:where(:not([type="checkbox"], [type="radio"])),
select,
textarea {
    width: 100%;
    min-height: var(--control-height);
    padding: 0 var(--space-s);
    border: 1px solid var(--color-stroke-accessible);
    border-radius: var(--radius-sm);
    background: var(--color-surface);
    color: var(--color-text);
    font-family: inherit;
    font-size: var(--font-size-body);
}

textarea {
    padding: var(--space-s);
    line-height: 20px;
    resize: vertical;
}

input:hover,
select:hover,
textarea:hover {
    border-color: var(--color-text);
}

input:focus,
select:focus,
textarea:focus {
    border-color: var(--color-accent);
    outline: 1px solid var(--color-accent);
    outline-offset: -2px;
}

input::placeholder,
textarea::placeholder {
    color: var(--color-text-disabled);
}

/*
 * Das Farbfeld — schmal, nicht bildschirmbreit.
 *
 * Die Grundregel gibt jedem Eingabefeld volle Breite; bei einem Farbfeld ergaebe das eine
 * handtellergrosse Flaeche in der gewaehlten Farbe, die aussieht wie ein Fehler. Die Hoehe
 * bleibt '--control-height', damit es in einer Zeile mit anderen Feldern steht.
 */
.farbfeld {
    width: 5rem;
    padding: 2px;
    cursor: pointer;
}

.field-hint {
    display: block;
    margin-top: var(--space-xs);
    color: var(--color-text-secondary);
    font-size: var(--font-size-caption);
}

/*
 * Ein Kontrollkästchen mit Beschriftung daneben.
 *
 * Kästchen und Text sind GESCHWISTER, nicht ineinander verschachtelt: Ein Blockelement (der
 * Hinweistext) innerhalb einer Beschriftung bricht deren Ausrichtung, und der erste Versuch sah
 * genau so aus. Die Verknüpfung läuft über 'for' — das ist ohnehin die verlässlichere Zuordnung
 * für Bildschirmleseprogramme.
 *
 * Das Kästchen darf nicht schrumpfen: Bei langem Text bliebe sonst ein Strich übrig, und
 * WCAG 2.5.8 verlangt 24 × 24 px.
 */
.field-checkbox {
    display: flex;
    align-items: flex-start;
    gap: var(--space-s);
    margin-bottom: var(--space-m);
}

.field-checkbox input[type="checkbox"] {
    flex: 0 0 auto;
    /* Auf die Höhe der ersten Textzeile gesetzt, nicht an den oberen Rand des Kastens. */
    margin-top: 2px;
}

.field-checkbox-text {
    display: flex;
    flex-direction: column;
    gap: var(--space-xs);
}

.field-checkbox-text label {
    margin: 0;
    cursor: pointer;
}

.field-checkbox-text .field-hint {
    margin-top: 0;
}

/* ── Codefeld (zweiter Schritt der Anmeldung) ───────────────────────────────────────────────────
 *
 * Sechs Kästchen, in die man Ziffer für Ziffer tippt — das Bild, das man von einem Anmeldecode
 * kennt. Darunter liegt aber GENAU EIN echtes Eingabefeld, und das ist der ganze Trick.
 *
 * WARUM NICHT SECHS FELDER
 *
 * Sechs <input> wären das Naheliegende und in jeder Hinsicht schlechter:
 *  — Ein Bildschirmleseprogramm sagt sechs unbeschriftete Felder an statt „Code, Eingabefeld".
 *  — 'autocomplete="one-time-code"' füllt genau ein Feld. Der Code aus der Mail oder von iOS
 *    landete in Kästchen eins, die restlichen fünf blieben leer.
 *  — Einfügen aus der Zwischenablage müsste von Hand auf sechs Felder verteilt werden, und
 *    Rücktaste, Pfeiltasten und Fokus müssten nachgebaut werden — alles Verhalten, das ein
 *    einzelnes Feld mitbringt.
 *  — Ein Wiederherstellungscode ist elf Zeichen lang und passt in kein Sechserraster.
 *
 * Deshalb: ein Feld, unsichtbarer Text, und die Kästchen liegen als reine Anzeige darüber
 * ('pointer-events: none' — jeder Klick trifft das Feld darunter). Das Skript spiegelt die
 * eingetippten Zeichen hinein. Ohne Skript, mit Wiederherstellungscode und im
 * Windows-Kontrastmodus bleibt schlicht das gewöhnliche Feld stehen: Die Kästchen sind eine
 * Zutat, keine Bedingung.
 */
.codefeld {
    position: relative;
}

/* Ohne Skript gibt es die Zellen gar nicht; im Freimodus (Wiederherstellungscode) werden sie
   ausgeblendet und das Feld ist wieder ein normales Feld. */
.codefeld-zellen {
    display: none;
}

.codefeld[data-codefeld-modus="zellen"] .codefeld-zellen {
    display: grid;
    grid-template-columns: repeat(6, 1fr);
    gap: var(--space-s);
    position: absolute;
    inset: 0;

    /* Die Anzeige nimmt keine Klicks an — sie liegt nur darüber. */
    pointer-events: none;
}

.codefeld[data-codefeld-modus="zellen"] .codefeld-zelle {
    display: flex;
    align-items: center;
    justify-content: center;
    border: 1px solid var(--color-stroke-accessible);
    border-radius: var(--radius-sm);
    background: var(--color-surface);
    color: var(--color-text);
    font-size: var(--font-size-title);
    font-variant-numeric: tabular-nums;
}

/* Wo die nächste Ziffer hingeht. Der Einfügestrich selbst ist unsichtbar (er säße im Feld
   darunter), also übernimmt der Rahmen seine Aufgabe — ohne Blinken und ohne Bewegung. */
.codefeld[data-codefeld-modus="zellen"] .codefeld-zelle[data-aktiv] {
    border-color: var(--color-accent);
    box-shadow: inset 0 0 0 1px var(--color-accent);
}

/*
 * Das echte Feld: durchsichtig, aber vorhanden — es trägt den Wert, den Fokus, die Beschriftung
 * und die Fehlerverknüpfung. Die Höhe ist die der Kästchen, damit der Fokusring des Browsers um
 * die Gruppe läuft und nicht quer durch sie.
 */
.codefeld[data-codefeld-modus="zellen"] .codefeld-eingabe {
    min-height: 48px;
    padding: 0;
    border-color: transparent;
    background: transparent;
    color: transparent;
    caret-color: transparent;
}

.codefeld[data-codefeld-modus="zellen"] .codefeld-eingabe:hover {
    border-color: transparent;
}

/*
 * Der Fokusring liegt AUSSEN um die Gruppe, nicht innen.
 *
 * Die Vorgabe für Felder ist 'outline-offset: -2px' — der Ring liegt dann innen, und innen ist
 * hier kein Platz: Dort stehen die Kästchen, und ein Ring quer durch sie sähe aus wie ein
 * siebenter Rahmen. Zwei Pixel außen sind zugleich der deutlichere Hinweis (WCAG 2.4.11).
 */
.codefeld[data-codefeld-modus="zellen"] .codefeld-eingabe:focus {
    outline: 2px solid var(--color-accent);
    outline-offset: 2px;
}

.inline-form {
    display: inline;
    margin: 0;
}

/* Mindestgröße von Bedienelementen: 24 × 24 px (WCAG 2.2, 2.5.8). Die Steuerelemente hier sind
   mit 32 px größer; die Regel sichert ab, dass eine künftige Verkleinerung nicht darunter fällt. */
button,
[role="button"],
/* Kästchen und Radioknöpfe: eigene Größe, kein Rahmen der Anwendung — den zeichnet der
   Browser. 24 Pixel sind die Mindestgröße eines Bedienziels (WCAG 2.2, 2.5.8); 'accent-color'
   färbt den Haken in der Akzentfarbe, die gegen die Karte 5,4:1 erreicht (WCAG 1.4.11). */
input[type="checkbox"],
input[type="radio"] {
    width: auto;
    min-width: 24px;
    min-height: 24px;
    padding: 0;
    accent-color: var(--color-accent);
}

/* Formulare in Listenzellen: Steuerelemente nebeneinander, ohne Blockumbruch. */
.cell-form {
    display: flex;
    align-items: center;
    gap: var(--space-s);
    margin: 0;
}

.cell-form select {
    width: auto;
    min-width: 180px;
}

/* Mehrere Bedienelemente in einer Tabellenzelle: nebeneinander, mit Umbruch bei wenig Platz.
   Ohne diese Regel steht jedes Element auf einer eigenen Zeile, weil ein <select> als Blockelement
   die volle Breite nimmt — die Zelle wird dreimal so hoch wie die daneben, und die Zeile faellt
   auseinander. */
.cell-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-s);
}

/* Der einheitliche Blockabstand (`.content form + *`) gilt dem Seitenfluss: Was auf ein Formular
   folgt, steht darunter und braucht Luft. In einer Tabellenzelle steht es daneben — dort schob
   die Regel jede zweite Schaltfläche um 24 px nach unten, und die Zeile saß schief. Die Ausnahme
   steht hier und nicht als `!important` am Formular: Sie ist eine Aussage über den Ort, nicht
   über die Dringlichkeit. */
.content .cell-actions > * {
    margin-top: 0;
}

/* ── Ablage: Ordner und Dateien in einer Liste ──────────────────────────────────────────────
 *
 * Wie eine Dokumentbibliothek: Symbol, Name, darunter die Nebenangaben. Ordner stehen oben und
 * führen weiter, Dateien führen auf ihre Seite. Der wichtigste Unterschied in einer Ablage ist
 * der zwischen „hier geht es weiter" und „hier ist etwas" — deshalb ist das Ordnersymbol
 * gefüllt und das Dateisymbol umrissen.
 */
.ablage-symbol {
    display: inline-flex;
    flex: 0 0 auto;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
}

.ablage-symbol svg {
    width: 24px;
    height: 24px;
}

.art-ordner { color: var(--color-link); }
.art-pdf { color: var(--color-datei-pdf); }
.art-word { color: var(--color-datei-word); }
.art-excel { color: var(--color-datei-excel); }
.art-powerpoint { color: var(--color-datei-powerpoint); }
.art-bild { color: var(--color-datei-bild); }
.art-text,
.art-sonstige { color: var(--color-text-secondary); }

/* Symbol und Beschriftung als eine Einheit — das Symbol gehört zum Namen, nicht in eine
   eigene Spalte, die bei schmalen Fenstern als erstes zusammenfällt. */
.ablage-eintrag {
    display: flex;
    align-items: center;
    gap: var(--space-m);
    min-width: 0;
}

.ablage-eintrag-text {
    min-width: 0;
}

/* Der Name ist der Verweis, und er füllt die Zeile: Das Ziel ist damit so groß wie der Text und
   nicht so klein wie ein Symbol (WCAG 2.5.8). */
.ablage-eintrag a {
    font-weight: 600;
}

/* ── Dichte einer Ablageliste ──────────────────────────────────────────────────────────────────
 *
 * Eine Ablage wird überflogen, nicht gelesen: eine Zeile je Sache, alle gleich hoch, das Auge
 * springt die Namensspalte hinunter. Ungleich hohe Zeilen machen genau das unmöglich.
 *
 * Die Regeln stehen an dieser Klasse und nicht an `tbody td`, wo sie für alle dreißig Tabellen
 * der Anwendung gälten: Eine Vorgangs- oder Maßnahmenliste trägt mehrzeilige Zellen — dort ist
 * die Ausrichtung nach oben richtig, und ein unterdrückter Umbruch wäre ein Fehler. */
.ablage-liste tbody td {
    padding-top: var(--space-s);
    padding-bottom: var(--space-s);
    vertical-align: middle;
}

/* Kein Umbruch im Namen — und bewusst auch keine Auslassungspunkte. Ein abgeschnittener
   Dateiname ist unbrauchbar, gerade dort, wo Namen sich in der Endung unterscheiden
   ("Begehung 2026-03 final.pdf"). Stattdessen wird die Tabelle breiter, und `.list-surface`
   scrollt waagerecht; seit die Fläche einen Tabstopp trägt, ist sie auch mit der Tastatur
   erreichbar. */
.ablage-liste .ablage-eintrag-text {
    white-space: nowrap;
}

/* Die Sichtbarkeitsangabe ist zugleich der Weg, sie zu ändern. Kein Unterstrich: Das Abzeichen
   ist die Fläche, und ein Strich darunter läse sich wie ein zweites, leeres Element. Dass es
   ein Verweis ist, zeigt der Zeiger, die Fokusumrandung und — für Vorlesegeräte — der Zusatz
   „Sichtbarkeit von … ändern". */
.ablage-freigabe {
    display: inline-block;
    text-decoration: none;
}

/* Ein Ring, keine Umfärbung: Das Abzeichen trägt den Zustand — grün für freigegeben, grau für
   verborgen. Färbte der Zeiger es um, verlöre die Zeile beim Darüberfahren genau die Auskunft,
   wegen der jemand hinsieht. */
.ablage-freigabe:hover .badge {
    box-shadow: 0 0 0 1px var(--color-accent);
}

/* Mehrere Empfänger in einer Zelle: Abstand und Umbruch, sonst nichts.

   KEINE eigene Farbe — die Abzeichen darin tragen ihre eigene, und eine Farbe ausserhalb von
   ':root' pruefte 'pruefe-kontrast.py' gar nicht erst. Umbrechen duerfen sie, weil ein Betrieb bis
   zu vier Betreuungen haben kann und ihre Namen keine feste Laenge haben; die Zeilenhoehe der
   Liste ist damit nicht mehr streng gleich, und das ist hier richtig: Die Auskunft, WER liest,
   darf nicht abgeschnitten werden. */
.ablage-empfaenger {
    display: inline-flex;
    flex-wrap: wrap;
    gap: var(--space-xs);
}

/* Das Vorschaubild an der Stelle des Symbols. Feste Kantenlänge, damit die Zeilen gleich hoch
   bleiben — eine Liste, in der jede Zeile eine andere Höhe hat, liest sich nicht. */
.ablage-vorschau {
    flex: 0 0 auto;
    width: 32px;
    height: 32px;
    object-fit: cover;
    border: 1px solid var(--color-stroke);
    border-radius: var(--radius-sm);
    background: var(--color-surface-hover);
}

/* Die große Vorschau auf der Dateiseite. 'contain' statt 'cover': Ein Beweisfoto darf nicht
   beschnitten werden, nur weil es hochkant ist. */
.vorschau-flaeche {
    display: flex;
    align-items: center;
    justify-content: center;
    max-height: 60vh;
    padding: var(--space-l);
    background: var(--color-surface-hover);
    border: 1px solid var(--color-stroke);
    border-radius: var(--radius-md);
}

.vorschau-flaeche img {
    max-width: 100%;
    max-height: 56vh;
    object-fit: contain;
}

/* Ein Dokument braucht Hoehe statt Zentrierung: Ein PDF wird gelesen, nicht betrachtet. */
.vorschau-flaeche.ist-dokument {
    display: block;
    max-height: none;
    padding: 0;
    overflow: hidden;
}

.vorschau-rahmen {
    display: block;
    width: 100%;
    height: 70vh;

    /* Mindesthoehe fuer kleine Fenster: Unter dieser Hoehe zeigt jede eingebaute PDF-Anzeige
       mehr Werkzeugleiste als Seite. */
    min-height: 24rem;
    border: 0;
    background: var(--color-surface);
}

/* Ohne Vorschau: das Typsymbol groß, damit die Seite nicht leer wirkt. */
.vorschau-ersatz {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--space-m);
    color: var(--color-text-secondary);
}

.vorschau-ersatz .ablage-symbol {
    width: 64px;
    height: 64px;
}

.vorschau-ersatz .ablage-symbol svg {
    width: 56px;
    height: 56px;
}

/* Das Zahnradmenü am rechten Rand der Befehlsleiste. Selten gebrauchte Vorgänge liegen darin
   statt daneben: Eine Reihe gleich aussehender Knöpfe sagt „alles gleich wichtig", und dann
   sucht man den einen, den man täglich braucht, zwischen denen, die man einmal im
   Vertragsleben anfasst.

   <details>/<summary> und kein Skriptmenü: Es klappt ohne JavaScript auf, ist mit der Tastatur
   bedienbar und trägt seinen Zustand selbst. Das Skript schließt es nur, wenn man daneben
   klickt oder Escape drückt. */
.aktionsmenue {
    position: relative;
    margin-inline-start: auto;
}

.aktionsmenue > summary {
    display: inline-flex;
    align-items: center;
    gap: var(--space-xs);
    height: var(--control-height);
    padding: 0 var(--space-m);
    border: 1px solid var(--color-stroke-accessible);
    border-radius: var(--radius-sm);
    background: var(--color-surface);
    color: var(--color-text);
    cursor: pointer;
    list-style: none;
}

.aktionsmenue > summary::-webkit-details-marker {
    display: none;
}

.aktionsmenue > summary:hover {
    background: var(--color-surface-hover);
}

.aktionsmenue > summary:focus-visible {
    outline: 2px solid var(--color-accent);
    outline-offset: 2px;
}

.aktionsmenue svg {
    width: 16px;
    height: 16px;
}

.aktionsmenue-panel {
    position: absolute;
    inset-inline-end: 0;
    z-index: 20;
    min-width: 16rem;
    margin-top: var(--space-xs);
    padding: var(--space-s);
    background: var(--color-surface);
    border: 1px solid var(--color-stroke);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-8);
}

/* Jeder Eintrag füllt die Breite des Menüs — ein Ziel, das so groß ist wie seine Zeile. */
.aktionsmenue-panel a,
.aktionsmenue-panel button,
.aktionsmenue-panel .verweisknopf {
    display: block;
    width: 100%;
    padding: var(--space-s);
    border-radius: var(--radius-sm);
    color: var(--color-text);
    text-align: start;
    text-decoration: none;
}

.aktionsmenue-panel a:hover,
.aktionsmenue-panel button:hover {
    background: var(--color-surface-hover);
    color: var(--color-text);
}

.aktionsmenue-panel form {
    margin: 0;
}

/* Selten gebrauchte Vorgänge unter der Befehlsleiste: als Verweise, nicht als Schaltflächen.
   Eine Reihe gleich aussehender Knöpfe sagt „alles gleich wichtig" — und dann sucht man den
   einen, den man täglich braucht, zwischen denen, die man einmal im Vertragsleben anfasst. */
.nebenaktionen {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-l);
    margin-top: var(--space-m);
    font-size: var(--font-size-caption);
}

/* Ein Knopf, der wie ein Verweis aussieht — für Vorgänge, die ein Formular brauchen (POST mit
   Antiforgery-Token), aber nicht wie eine Hauptaktion wirken sollen. Er bleibt ein <button>:
   Ein Verweis, der etwas ändert, wäre für Vorlesegeräte und für den Browserverlauf falsch. */
.verweisknopf {
    padding: 0;
    background: none;
    border: none;
    color: var(--color-link);
    font: inherit;
    text-decoration: underline;
    cursor: pointer;
}

.verweisknopf:hover {
    color: var(--color-link-hover);
}

/* Ablagefläche zum Hineinziehen. Ohne JavaScript ein gewöhnliches Formular mit Auswahlfeld;
   der gestrichelte Rahmen und der Hinweis erscheinen erst, wenn das Skript sie eingerichtet
   hat (data-dropzone-bereit). Ein Hinweis „hierher ziehen" ohne Skript wäre ein Versprechen,
   das die Seite nicht hält. */
/* ── Die Ablageliste als Ablageflaeche ───────────────────────────────────────────────────────
 *
 * Gezogen wird auf die Liste selbst — oder auf eine Ordnerzeile darin. Sichtbar wird das erst,
 * wenn wirklich etwas darueber schwebt; im Ruhezustand sieht die Liste aus wie eine Liste.
 * Ein dauerhaft gestrichelter Rahmen um die halbe Seite waere Laerm.
 */

.ablage-flaeche {
    position: relative;
}

/* Die ganze Flaeche als Ziel: Was hier faellt, landet an dieser Stelle der Ablage.
 * 'outline' und nicht 'border': Ein Rahmen verschoebe die Liste um zwei Pixel, und die Zeilen
 * ruckten unter dem Zeiger weg, waehrend man zielt. */
.ablage-flaeche.ist-ziel {
    outline: 2px dashed var(--color-accent);
    outline-offset: 4px;
    border-radius: var(--radius-md);
}

/* Die einzelne Ordnerzeile als Ziel — sie gewinnt gegen die Flaeche, wenn man genau auf sie
 * zielt. Der Rahmen liegt INNEN ('inset'), damit die Tabellenzeile ihre Hoehe behaelt.
 *
 * Farbe traegt die Bedeutung nicht allein (WCAG 1.4.1): Der Rahmen ist das zweite Merkmal. */
.ablage-liste tr[data-ablage-ordner].ist-ziel {
    background: var(--color-accent-subtle);
    box-shadow: inset 0 0 0 2px var(--color-accent);
}

/* ── Auswahl in der Ablage ──────────────────────────────────────────────────────────────────────
 *
 * Die Leiste ueber der Liste: links der Stand („3 Dateien ausgewaehlt"), rechts die Schaltflaeche.
 * Sie gehoert zur Liste und nicht in die Befehlsleiste der Seite: Sie handelt von dem, was
 * darunter angekreuzt ist, und steht deshalb unmittelbar darueber — wie in jeder Dateiablage.
 *
 * Der Stand ist eine Skriptangabe und bleibt ohne Skript verborgen ('hidden'); die Schaltflaeche
 * ist ein gewoehnlicher Absendeknopf und funktioniert immer. */
.ablage-auswahl {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    flex-wrap: wrap;
    gap: var(--space-s) var(--space-m);
    margin-bottom: var(--space-s);
}

.ablage-auswahl-stand {
    margin: 0;
    margin-right: auto;
}

/* Die Kaestchenspalte ist so schmal wie das Kaestchen. 'width: 1px' laesst die Tabelle die
 * Spalte auf den Inhalt zusammenziehen; das Kaestchen selbst behaelt seine 24 px (WCAG 2.5.8). */
.ablage-liste .ablage-auswahl-spalte {
    width: 1px;
    white-space: nowrap;
}

.ablage-liste td.ablage-auswahl-spalte input[type="checkbox"] {
    display: block;
}

/* Das Kaestchen fuer alle im Kopf bleibt ohne Skript verborgen — ausdruecklich, damit keine
 * Regel mit hoeherer Spezifitaet das 'hidden' des Browsers ueberstimmt. */
.ablage-liste th.ablage-auswahl-spalte input[type="checkbox"][hidden] {
    display: none;
}

/* Der Wartezustand nach dem Fallenlassen. Gleiche Form wie auf der Ablageseite — es ist
 * dieselbe Aussage, und sie soll nicht an zwei Orten verschieden aussehen. */
.ablage-warten[hidden] {
    display: none;
}

.ablage-warten {
    margin: var(--space-m) 0 0;
    padding: var(--space-s);
    background: var(--color-surface);
    border: 1px solid var(--color-stroke);
    border-radius: var(--radius-md);
    color: var(--color-text);
}

/* Die Zeile mit Kreisel und Text — darunter, wenn das Skript ihn fuellt, der Balken. */
.ablage-warten-zeile,
.ablagefeld-pruefung-zeile {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-s);
    margin: 0;
}

/* ── Fortschritt beim Hochladen ───────────────────────────────────────────────────────────────
 *
 * Ein <progress>, kein nachgebauter Balken: Das Element traegt seinen Wert selbst, Vorlese-
 * programme sagen ihn an, und der Windows-Kontrastmodus zeichnet es mit Systemfarben. Die
 * Akzentfarbe kommt ueber 'accent-color' — dieselbe wie bei Kaestchen und Schaltern.
 *
 * Er erscheint erst, wenn das Skript den ersten Fortschritt meldet; bis dahin steht nur der
 * Kreisel. Ein leerer Balken saehe aus wie ein haengender Upload. */
.ablage-fortschritt[hidden] {
    display: none;
}

.ablage-fortschritt {
    display: block;
    width: 100%;
    height: 8px;
    margin-top: var(--space-s);
    accent-color: var(--color-accent);
}

/* Der Fehler an Ort und Stelle — dieselbe Farbe wie eine Feldmeldung, denn es ist eine. */
.ablage-fehler[hidden] {
    display: none;
}

.ablage-fehler {
    margin: var(--space-s) 0 0;
}

/* ── Ablagefeld ──────────────────────────────────────────────────────────────────────────────
 *
 * Das Feld zum Hochladen. Vorher stand hier eine Zeile Text neben dem nackten
 * '<input type="file">' des Browsers — Systemschaltfläche, „Keine Datei ausgewählt", nichts
 * davon gestaltbar. Jetzt trägt ein <label> die Schaltfläche, und das Eingabefeld ist
 * versteckt, aber weiterhin erreichbar (siehe _Ablagefeld.cshtml).
 */

.ablagefeld {
    display: block;
    padding: var(--space-xl) var(--space-l);
    background: var(--color-surface);
    border: 1px solid var(--color-stroke);
    border-radius: var(--radius-md);
    text-align: center;
}

/* Gestrichelt erst, wenn Ziehen ueberhaupt geht — das Skript setzt das Attribut. Ein
 * gestrichelter Rahmen verspricht eine Ablageflaeche; ohne Skript gaebe es sie nicht. */
.ablagefeld[data-dropzone-bereit] {
    border-style: dashed;
    border-color: var(--color-stroke-accessible);
}

/* Dieselbe Falle wie unten beim Wartezustand, und hier waere sie schlimmer gewesen: Ohne
   diese Regel schlaegt 'display: flex' das 'hidden'-Attribut, das Skript setzt es beim
   Absenden vergeblich, und Auswahl und Kreisel staenden nebeneinander. */
.ablagefeld-wahl[hidden] {
    display: none;
}

.ablagefeld-wahl {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--space-s);
}

.ablagefeld-symbol {
    width: 2.5rem;
    height: 2.5rem;
    color: var(--color-text-secondary);
}

.ablagefeld-titel {
    margin: 0;
    font-size: var(--font-size-body);
    color: var(--color-text);
}

/* Der Ziehhinweis nur, wenn Ziehen geht. Ohne Skript bleibt "auswählen" allein stehen und
 * der Satz ergibt trotzdem Sinn. */
.ablagefeld-ziehen {
    display: none;
}

.ablagefeld[data-dropzone-bereit] .ablagefeld-ziehen {
    display: inline;
}

/* Das <label> IST die Schaltflaeche. Es sieht aus wie ein Verweis, weil es mitten im Satz
 * steht — eine zweite geraenderte Schaltflaeche neben "Ablegen" waere eine Frage zu viel. */
.ablagefeld-knopf {
    /* Ausdruecklich inline: Formularbeschriftungen sind in diesem Blatt 'display: block' —
       ohne diese Zeile faellt "auswaehlen" in eine eigene Zeile und der Satz zerreisst. */
    display: inline;
    color: var(--color-link);
    font-weight: 600;
    text-decoration: underline;
    cursor: pointer;
}

.ablagefeld-knopf:hover {
    color: var(--color-link-hover);
}

/* Versteckt, aber erreichbar: kein 'display: none', sonst verschwindet das Feld aus der
 * Tabulatorfolge und die Auswahl ist ohne Maus nicht mehr zu oeffnen (WCAG 2.1.1). */
.ablagefeld-eingabe {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* Der Fokus steht am Feld, sichtbar wird er am <label> — sonst umrandet der Browser einen
 * Punkt von einem Pixel, und niemand sieht, wo er ist (WCAG 2.4.7). */
.ablagefeld-eingabe:focus-visible + span {
    outline: 2px solid var(--color-accent);
    outline-offset: 2px;
    border-radius: var(--radius-sm);
}

/* Als Block mittig, im Text aber linksbuendig: Ein zentrierter Absatz ueber mehrere Zeilen
   zwingt das Auge, den Zeilenanfang jedes Mal neu zu suchen. Die Breitenbegrenzung haelt ihn
   ausserdem bei lesbaren Zeilenlaengen — auf der Ablageseite steht dort ein ganzer Satz. */
.ablagefeld-hinweis {
    max-width: 52ch;
    margin: 0 auto;
    font-size: var(--font-size-caption);
    color: var(--color-text-secondary);
    text-align: left;
}

/* Die gewaehlten Dateien. Erscheint erst, wenn etwas gewaehlt wurde. */
.ablagefeld-liste[hidden] {
    display: none;
}

.ablagefeld-liste {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: var(--space-xs);
    margin: var(--space-xs) 0 0;
    padding: 0;
    list-style: none;
}

.ablagefeld-liste li {
    padding: 0.125rem var(--space-xs);
    background: var(--color-surface-hover);
    border: 1px solid var(--color-stroke);
    border-radius: var(--radius-sm);
    font-size: var(--font-size-caption);
    color: var(--color-text);
}

/* Beim Ueberziehen: Rahmen und Flaeche in der Akzentfarbe — die Rueckmeldung, dass hier etwas
 * ankommt. Der Rahmen traegt sie, nicht nur die Farbe der Flaeche (WCAG 1.4.1). */
.ablagefeld.ist-ziel {
    border-color: var(--color-accent);
    border-width: 2px;
    background: var(--color-accent-subtle);
}

/* ── Der Wartezustand ───────────────────────────────────────────────────────────────────── */

/* Verborgen heisst verborgen: 'display: flex' unten schlaegt sonst das 'hidden'-Attribut,
   und der Wartezustand steht schon da, bevor jemand etwas abgeschickt hat. Die Regel mit dem
   Attribut ist spezifischer und gewinnt. */
.ablagefeld-pruefung[hidden] {
    display: none;
}

.ablagefeld-pruefung {
    margin: 0;
    padding: var(--space-s) 0;
    color: var(--color-text);
}

.ablagefeld-pruefung-text {
    text-align: left;
}

/*
 * Der Kreisel.
 *
 * Zweck, nicht Schmuck (MANIFEST §5.1): Zwischen dem Klick und der Antwort liegt eine
 * Virenpruefung, und ohne Bewegung sieht eine Seite, die wartet, aus wie eine Seite, die
 * haengt. Genau dann drueckt jemand ein zweites Mal.
 *
 * Bei 'prefers-reduced-motion' kuerzt der Block weiter oben jede Dauer auf 0,01 ms. Der Kreisel
 * steht dann still — der Satz daneben sagt trotzdem, was geschieht. Deshalb traegt der Text die
 * Aussage und nicht die Bewegung.
 */
.ablagefeld-kreisel {
    flex: none;
    width: 1.25rem;
    height: 1.25rem;
    border: 2px solid var(--color-stroke);
    border-top-color: var(--color-accent);
    border-radius: 50%;
    animation: kreisel-drehen 700ms linear infinite;
}

@keyframes kreisel-drehen {
    to {
        transform: rotate(360deg);
    }
}

/* Der Ordnerpfad über der Liste. Dieselbe Form wie die Brotkrumen der Seite, aber ein eigener
   Bereich — er führt innerhalb der Ablage, nicht aus ihr heraus. */
.ablagepfad ol {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-xs);
    margin: 0;
    padding: 0;
    list-style: none;
}

.ablagepfad li:not(:first-child)::before {
    content: "›";
    margin-inline-end: var(--space-xs);
    color: var(--color-text-secondary);
}

.ablagepfad [aria-current="page"] {
    font-weight: 600;
}

/* Beschreibungsliste für Stammdaten: Bezeichnung und Wert in zwei Spalten. Semantisch dl/dt/dd
   statt einer Tabelle — es sind Name-Wert-Paare, keine tabellarischen Daten (WCAG 1.3.1). */
.detail-list {
    display: grid;
    grid-template-columns: minmax(180px, 240px) 1fr;
    gap: var(--space-s) var(--space-l);
    margin: 0;
}

.detail-list dt {
    color: var(--color-text-secondary);
    font-weight: 600;
}

.detail-list dd {
    margin: 0;
}

.detail-list dd .caption {
    display: block;
}

@media (max-width: 600px) {
    .detail-list {
        grid-template-columns: 1fr;
        gap: var(--space-xs);
    }

    .detail-list dd {
        margin-bottom: var(--space-s);
    }

    /* Kein neuer Haltepunkt: app.css hat vier (1100, 900, 800, 600), ein fuenfter waere eine
       fuenfte Wahrheit ueber "schmal". Bei 400 % Zoom auf 1280 px (= 320 px, WCAG 1.4.10) greift
       dieser Zweig ebenfalls: 320 - 2x12 - 2x16 = 256 px Inhaltsbreite in der Karte. */
    .schlicht-inhalt {
        padding: var(--space-xl) var(--space-m);
    }

    .schlicht .card {
        padding: var(--space-l);
    }
}

/* Kopfzeile einer Betriebskarte: Name links, Nutzerzahl rechts. */
.company-header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--space-m);
    margin-bottom: var(--space-m);
}

.company-header h3 {
    margin: 0;
}

.company-header p {
    margin: var(--space-xs) 0 0;
}

/* Zuordnungsformular am Fuß einer Betriebskarte. */
.assign-form {
    display: flex;
    align-items: flex-end;
    gap: var(--space-m);
    margin-top: var(--space-l);
    padding-top: var(--space-l);
    border-top: 1px solid var(--color-stroke);
}

.assign-form .field {
    margin-bottom: 0;
    min-width: 280px;
    max-width: 420px;
}

/* Mehrere Aktionen in einer Tabellenzelle. */
.row-actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-xs);
    margin-top: var(--space-xs);
}

/* ── Hinweise (Fluent MessageBar) ───────────────────────────────────────────────────────────── */

.notice {
    display: flow-root;
    margin-bottom: var(--space-l);
    padding: var(--space-m) var(--space-l);
    border-radius: var(--radius-sm);
    border-left: 3px solid var(--color-info);
    background: var(--color-info-subtle);
    color: var(--color-text);
}

.notice p {
    margin: 0 0 var(--space-s);
}

.notice p:last-child {
    margin-bottom: 0;
}

.notice-warning {
    border-left-color: var(--color-warning);
    background: var(--color-warning-subtle);
}

.notice-error {
    border-left-color: var(--color-danger);
    background: var(--color-danger-subtle);
}

.notice-success {
    border-left-color: var(--color-success);
    background: var(--color-success-subtle);
}

/* Leere Validierungszusammenfassung nicht als leeren Kasten zeigen. */
.notice:empty,
.validation-summary-valid {
    display: none;
}

/* ── Fortschrittsbalken (Prüfstandsimport) ──────────────────────────────────────────────────
   Das native <progress>: barrierefrei von Haus aus (Rolle, Wert, Maximum), gestaltet ueber
   Token. Die Beschriftung mit den Zahlen steht als <label> daneben — der Balken traegt die
   Bedeutung nicht allein (WCAG 1.4.1). */
progress.fortschritt {
    display: block;
    width: 100%;
    height: 8px;
    margin-top: var(--space-xs);
    appearance: none;
    -webkit-appearance: none;
    border: none;
    border-radius: var(--radius-pill);
    background: var(--color-surface-pressed);
    overflow: hidden;
}

progress.fortschritt::-webkit-progress-bar {
    background: var(--color-surface-pressed);
    border-radius: var(--radius-pill);
}

progress.fortschritt::-webkit-progress-value {
    background: var(--color-accent-bg);
    border-radius: var(--radius-pill);
}

progress.fortschritt::-moz-progress-bar {
    background: var(--color-accent-bg);
    border-radius: var(--radius-pill);
}

@media (forced-colors: active) {
    progress.fortschritt::-webkit-progress-value,
    progress.fortschritt::-moz-progress-bar {
        background: Highlight;
    }
}

.field-validation-error {
    display: block;
    margin-top: var(--space-xs);
    color: var(--color-danger);
    font-size: var(--font-size-caption);
}

/* Umgebungsbanner — verhindert, dass Preview für Produktion gehalten wird. */
.env-banner {
    padding: var(--space-xs) var(--space-l);
    text-align: center;
    background: var(--color-warning-subtle);
    color: var(--color-warning);
    font-size: var(--font-size-caption);
    font-weight: 600;
    border-bottom: 1px solid var(--color-stroke);
}

/* ── Leerer Zustand ─────────────────────────────────────────────────────────────────────────── */

.empty-state {
    padding: var(--space-xxl);
    text-align: center;
    background: var(--color-surface);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-2);
}

/*
 * 'margin-inline: auto' ist hier nicht kosmetisch: Der Absatz erbt weiter oben ein
 * 'max-width: 90ch'. Ohne automatischen Außenabstand steht der schmalere Block linksbündig in der
 * zentrierten Fläche — der Text darin ist zentriert, der Block aber nicht, und genau das sieht
 * schief aus.
 */
.empty-state p {
    margin: 0 auto var(--space-l);
    color: var(--color-text-secondary);
}

/* Das Symbol über der Aussage (LeererZustandTagHelper): ein leeres Fach, neutral und klein —
   es zeigt „hier ist Platz für etwas", ohne zur Illustration zu werden. */
.empty-state-symbol {
    display: block;
    box-sizing: content-box;
    width: 24px;
    height: 24px;
    margin: 0 auto var(--space-m);
    padding: var(--space-m);
    border-radius: 50%;
    background: var(--color-accent-tint);
    color: var(--color-accent);
}

.empty-state p:last-child {
    margin-bottom: 0;
}

/* Hinweis mit Bezug zur Akzentfarbe — für Dinge, die warten, nicht für Fehler. */
.notice-info {
    border-inline-start: 3px solid var(--color-info);
    background: var(--color-info-subtle);
}

/* ── Seitenweise Navigation ─────────────────────────────────────────────────────────────────── */

.pager {
    display: flex;
    align-items: center;
    gap: var(--space-m);
    margin-top: var(--space-l);
}

.pager-status {
    color: var(--color-text-secondary);
    font-size: var(--font-size-caption);
}

/* ── Theme-Umschalter ───────────────────────────────────────────────────────────────────────── */

/* Ein Symbol für beide Zustände. Der Zustand steckt in aria-pressed — verlässlich für
   Screenreader — und wird visuell durch die Akzentfarbe des gedrückten Zustands gezeigt. */
.theme-toggle svg {
    width: 20px;
    height: 20px;
}

.theme-toggle[aria-pressed="true"] {
    background: var(--color-accent-subtle);
    color: var(--color-text);
}

/* ── Schmale Fenster ────────────────────────────────────────────────────────────────────────── */

@media (max-width: 800px) {
    .shell {
        grid-template-columns: 1fr;

        /* Drei Bereiche brauchen drei Zeilenhöhen. Mit den zwei des Desktops bekam die
           Navigationszeile den ganzen Rest des Fensters, und über dem Inhalt stand eine leere
           Fläche, sobald die Navigation zugeklappt ist. */
        grid-template-rows: var(--topbar-height) auto 1fr;
        grid-template-areas:
            "topbar"
            "nav"
            "main";
    }

    /*
     * Die Navigation klappt hinter den Menüknopf. Vorher stand sie umgebrochen als Reihe von
     * Einträgen über dem Inhalt — mit Einstellungen und Paketen gut ein Drittel des Bildschirms,
     * bevor die Seite anfing, und bei jedem Aufruf wieder. Aufgeklappt ist sie dieselbe senkrechte
     * Liste wie auf dem Desktop: ein Muster, nicht zwei.
     *
     * ':target' ist der Weg ohne Skript (der Knopf ist ein Verweis auf '#hauptnavigation'),
     * '.ist-offen' der mit Skript (preventra.js, mit 'aria-expanded').
     */
    /* Maße ausdrücklich: Das Skript setzt 'role="button"', und die Mindestregel für
       '[role="button"]' (24 px, 'width: auto') machte ihn kleiner als den Knopf daneben. */
    .topbar-actions .nav-schalter {
        display: inline-flex;
        width: var(--control-height);
        min-height: var(--control-height);
    }

    .sidebar {
        display: none;
        border-right: none;
        border-bottom: 1px solid var(--color-stroke);
        padding: var(--space-s);
    }

    .sidebar:target,
    .sidebar.ist-offen {
        display: flex;
    }

    /* Auf dem Telefon reicht das Blatt bis an beide Ränder — mit dem Abstand des Desktops nur
       rechts stand es schief. Oben bleibt die Rundung als Übergang zur Navigation. */
    .content {
        padding: var(--space-l);
        margin: 0;
        border-radius: var(--radius-lg) var(--radius-lg) 0 0;
    }
}

/*
 * Kopfzeile und Navigation stehen fest, nur das Blatt scrollt — wie in Microsoft 365.
 *
 * Vorher scrollte die ganze Seite: Wer in einer langen Liste unten stand, hatte Suche und
 * Navigation aus dem Blick und musste erst zurück nach oben. Jetzt ist das Gerüst genau so hoch
 * wie das Fenster, und Blatt und Navigation scrollen jeweils für sich.
 *
 * Nur auf dem Bildschirm und erst ab 801 px: Darunter stapeln sich Kopfzeile, Navigation und
 * Inhalt (Block darüber), und ein Blatt mit eigenem Scrollbereich auf einem Telefon wäre ein
 * Fenster im Fenster — bei 400 % Zoom (WCAG 1.4.10) gilt dieselbe schmale Fassung.
 *
 * 'body:has(> .shell)' und nicht 'body': Die Seiten vor der Anmeldung haben kein Gerüst und
 * scrollen weiter als Ganzes. 'dvh', damit die Adressleiste mobiler Browser nichts abschneidet.
 * Ein Hinweisband über dem Gerüst (.env-banner) nimmt sich seine Höhe, das Gerüst den Rest.
 */
@media screen and (min-width: 801px) {
    body:has(> .shell) {
        display: flex;
        flex-direction: column;
        height: 100vh;
        height: 100dvh;
        overflow: hidden;
    }

    body:has(> .shell) > .shell {
        flex: 1;
        min-height: 0;
        grid-template-rows: var(--topbar-height) minmax(0, 1fr);
    }

    .sidebar,
    .content {
        min-height: 0;
        overflow-y: auto;
        overscroll-behavior: contain;
    }
}

/* Das Blatt ist Ziel der Sprungmarke und damit fokussierbar (tabindex="-1"), damit es danach mit
   den Pfeiltasten scrollt. Einen Fokusring braucht es nicht: Es ist kein Bedienelement. */
.content:focus {
    outline: none;
}

/* ── Druck (Nachweise, Protokolle) ──────────────────────────────────────────────────────────── */

@media print {
    .topbar,
    .sidebar,
    .skip-link,
    .command-bar-actions,
    .env-banner,
    .nicht-drucken,
    .breadcrumbs {
        display: none;
    }

    .shell {
        display: block;
    }

    /* Das Blatt ist eine Bildschirmebene, auf Papier ist alles Blatt: kein Rand, kein Schatten. */
    .content {
        padding: 0;
        max-width: none;
        margin: 0;
        border-radius: 0;
        box-shadow: none;
    }

    .content .empty-state {
        border: 1px solid var(--color-stroke);
    }

    /* Der Verlauf ist ein Nachweis: auf Papier eine durchgehende Spalte, jede Nachricht gerahmt. */
    .message,
    .message-eigen {
        align-self: stretch;
        max-width: none;
        border: 1px solid var(--color-stroke);
        border-radius: 0;
        background: none;
    }

    /* '.schlicht .card' muss ausdruecklich dabeistehen: Es hat 0,2,0 und schluege '.card'
       (0,1,0) hier. Ohne diese Zeile wuerde die Anmeldekarte mit '--shadow-8' gedruckt — auf
       Papier ein grauer Schmier. Mit gleicher Spezifitaet und weiter unten in der Datei gewinnt
       die Druckregel wieder. */
    .card,
    .schlicht .card,
    .list-surface,
    .empty-state {
        box-shadow: none;
        border: 1px solid var(--color-stroke);
    }
}

/* ── Bewegungsreduzierung ───────────────────────────────────────────────────────────────────── */

@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
    }
}

/* ── Erzwungene Farben (Windows-Kontrastmodus) ──────────────────────────────────────────────────
 *
 * Im Kontrastmodus ersetzt das Betriebssystem alle Farben und entfernt Hintergründe und Schatten.
 * Karten, Listen und Statusmeldungen wären dann nicht mehr voneinander abgegrenzt. Deshalb hier
 * ausdrückliche Rahmen aus Systemfarben — und der Fokusring bekommt eine Systemfarbe, weil eigene
 * Farben ignoriert werden.
 */

@media (forced-colors: active) {
    /* Derselbe Spezifitaetsfall wie im Druck, und dieser ist der gefaehrlichere: Im
       Windows-Kontrastmodus entfernt das System Hintergruende und Schatten. Dieser Block gibt der
       Karte deshalb eine Kante aus CanvasText. '.schlicht .card' (0,2,0) haette die Schattenregel
       (0,1,0) ueberstimmt, und die einzige verlaessliche Abgrenzung der Anmeldekarte haette an
       einer Erhebung gehangen, die dort niemand sieht. */
    .card,
    .schlicht .card,
    .list-surface,
    .empty-state,
    .command-bar,
    .notice {
        border: 1px solid CanvasText;
        box-shadow: none;
    }

    .badge {
        border: 1px solid CanvasText;
    }

    .message {
        border: 1px solid CanvasText;
    }

    /* Das Blatt verliert im Kontrastmodus Schatten und Fläche — die Kante grenzt es ab. */
    .content {
        border: 1px solid CanvasText;
    }

    /* Die Tönung des aktiven Punkts entfernt das System. Ein Rahmen in der Systemfarbe für
       Auswahl zeigt ihn stattdessen. */
    .sidebar a[aria-current] {
        outline: 2px solid Highlight;
        outline-offset: -2px;
    }

    .kalender-eintrag a {
        border: 1px solid LinkText;
        border-left-width: 3px;
    }

    .button {
        border: 1px solid ButtonText;
    }

    .sidebar a[aria-current] {
        /* Die Hervorhebung über Hintergrundfarbe entfällt; Unterstreichung tritt an ihre Stelle. */
        text-decoration: underline;
        text-underline-offset: 3px;
    }

    :focus-visible {
        outline: 3px solid Highlight;
        box-shadow: none;
    }

    .theme-toggle svg {
        fill: ButtonText;
    }

    /*
     * Das Codefeld faellt auf das gewoehnliche Feld zurueck.
     *
     * Im Kontrastmodus ersetzt das System jede Farbe durch eine Systemfarbe — auch 'transparent'
     * am Text des darunterliegenden Feldes. Der Code stuende dann ZWEIMAL da: einmal im Feld und
     * einmal in den Kaestchen darueber, gegeneinander versetzt. Wer diesen Modus benutzt, braucht
     * Lesbarkeit und keine Kaestchen.
     */
    .codefeld[data-codefeld-modus="zellen"] .codefeld-zellen {
        display: none;
    }

    .codefeld[data-codefeld-modus="zellen"] .codefeld-eingabe {
        padding: 0 var(--space-s);
        border: 1px solid CanvasText;
        color: CanvasText;
        caret-color: CanvasText;
    }
}

/* ── Verstärkter Kontrast (Systemeinstellung) ───────────────────────────────────────────────────
 *
 * Wenn das System mehr Kontrast anfordert, werden Trennlinien und Umrisse kräftiger. Die
 * Textfarben erfüllen bereits AAA und bleiben unverändert.
 */

@media (prefers-contrast: more) {
    :root {
        --color-stroke: #767676;
        --color-stroke-strong: #4d4d4d;
        --color-stroke-accessible: #242424;
        --color-text-secondary: #242424;
    }

    :root[data-theme="dark"] {
        --color-stroke: #8f8f8f;
        --color-stroke-strong: #c7c7c7;
        --color-stroke-accessible: #f5f5f5;
        --color-text-secondary: #f5f5f5;
    }
}

/* ── Öffentliche Prüfabfrage (ADR 0017) ──────────────────────────────────────────────────────
 *
 * Eine einzige Seite unter der eigenen Domäne eines Mandanten, ohne Anmeldung und ohne
 * Navigation. Sie wird auf einem Telefon benutzt, in einer Werkhalle, oft bei schlechtem Licht
 * und mit Handschuhen — deshalb große Schrift, große Berührflächen und ein Ergebnis, das man
 * aus einem Meter Abstand erkennt.
 *
 * Alle Farben kommen aus Token. Haken und Kreuz tragen die Bedeutung nie allein: Daneben steht
 * der Klartext, und das Zeichen trägt sie in der Form (WCAG 1.4.1). Die verwendeten Paare
 * (Erfolgstext auf Erfolgsfläche, Fehlertext auf Fehlerfläche) sind in
 * scripts/pruefe-kontrast.py nachgerechnet. */

/*
 * Eine Spalte, nicht eine Zeile.
 *
 * Hier stand 'display: flex' ohne Richtung — solange <main> das einzige Kind war, sah das aus wie
 * eine Zentrierung. Seit die Rechtsfusszeile aus <main> heraus ist (sie ist sonst kein
 * 'contentinfo'), ist sie ein zweites Kind und stand daneben statt darunter. Dieselbe Falle wie
 * seinerzeit beim Umgebungsbanner in '.schlicht'.
 */
body.oeffentlich {
    background: var(--color-canvas);
    display: flex;
    flex-direction: column;
    align-items: center;
}

/* Die Fusszeile teilt die Blattbreite, damit ihre Verweise unter dem Blatt stehen und nicht am
   Fensterrand. */
.oeffentlich-fuss {
    width: 100%;
    max-width: 34rem;
    padding: 0 var(--space-m) var(--space-xl);
}

.oeffentlich-blatt {
    width: 100%;
    max-width: 34rem;
    padding: var(--space-l) var(--space-m) var(--space-xl);
}

.oeffentlich-kopf {
    display: flex;
    justify-content: center;
    margin-bottom: var(--space-l);
}

.oeffentlich-logo {
    max-height: 3.5rem;
    max-width: 100%;
    object-fit: contain;
}

.oeffentlich-anbieter {
    font-size: var(--font-size-subtitle);
    font-weight: 600;
    color: var(--color-text);
    margin: 0;
}

.oeffentlich-blatt h1 {
    text-align: center;
}

.oeffentlich-blatt > .lead {
    text-align: center;
    margin-bottom: var(--space-l);
}

/* Das Eingabefeld ist der Zweck der Seite — entsprechend groß.
 *
 * 1,25rem Schriftgröße ist kein Geschmack: Unterhalb von 16px zoomt Safari auf dem iPhone beim
 * Hineintippen die ganze Seite heran, und der Nutzer landet in einer verschobenen Ansicht. */
.oeffentlich-blatt .field input {
    font-size: var(--font-size-subtitle);
    padding: var(--space-s) var(--space-m);
}

.oeffentlich-blatt .button {
    width: 100%;
    justify-content: center;
    min-height: 3rem;
    font-size: var(--font-size-body);
}

.oeffentlich-ergebnis {
    margin-top: var(--space-l);
}

.oeffentlich-geraet {
    font-size: var(--font-size-subtitle);
    font-weight: 600;
    color: var(--color-text);
    text-align: center;
    margin: 0 0 var(--space-m);
}

.oeffentlich-status {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-s);

    font-size: var(--font-size-display);
    font-weight: 600;

    padding: var(--space-l) var(--space-m);
    border-radius: var(--radius-md);

    /* Ohne Aussage: Für „mehrdeutig" und „nichts gefunden" gibt es kein Grün und kein Rot —
       beides wäre eine Antwort, die wir nicht geben. */
    background: var(--color-surface);
    color: var(--color-text);
    margin: 0 0 var(--space-m);
    text-align: center;
}

.oeffentlich-status.ist-geprueft {
    background: var(--color-success-subtle);
    color: var(--color-success);
}

.oeffentlich-status.nicht-geprueft {
    background: var(--color-danger-subtle);
    color: var(--color-danger);
}

.oeffentlich-zeichen {
    width: 2.5rem;
    height: 2.5rem;
    flex: none;
}

/*
 * Haken und Kreuz zeichnen sich, statt einfach dazustehen.
 *
 * Es ist die Antwort auf die einzige Frage dieser Seite, und sie kommt nach einem Formularabsenden
 * — ohne Bewegung erscheint sie einfach, und das Auge findet sie nicht zuverlaessig. Das Zeichnen
 * fuehrt den Blick genau dorthin. Zweck, nicht Schmuck (MANIFEST §5.1).
 *
 * WARUM DER STARTZUSTAND IM KEYFRAME STEHT UND NICHT AM ELEMENT
 *
 * Am Element stuende 'stroke-dashoffset: 1' — also ein unsichtbares Zeichen, das erst die
 * Animation hervorholt. Laeuft sie aus irgendeinem Grund nicht, bliebe die Antwort unsichtbar:
 * Die Seite haette dann genau das verloren, wofuer es sie gibt. So herum ist der Grundzustand das
 * fertige Zeichen, und die Animation nimmt es nur kurz weg.
 *
 * Bei 'prefers-reduced-motion' kuerzt der Block weiter unten jede Dauer auf 0,01 ms; mit
 * 'forwards' steht danach der Endzustand — das fertige Zeichen. Wer keine Bewegung will, bekommt
 * keine und sieht trotzdem die Antwort.
 *
 * 'pathLength="1"' im Markup normiert die Strichlaenge, damit hier keine gerechnete Laenge steht,
 * die bei jeder Formaenderung nachgezogen werden muesste (MANIFEST §3).
 */
@keyframes zeichen-zeichnen {
    from {
        stroke-dasharray: 1;
        stroke-dashoffset: 1;
    }

    to {
        stroke-dasharray: 1;
        stroke-dashoffset: 0;
    }
}

.oeffentlich-zeichen path {
    animation: zeichen-zeichnen 500ms ease-out forwards;
}

.oeffentlich-ergebnis .caption {
    text-align: center;
    display: block;
}

.oeffentlich-fuss {
    margin-top: var(--space-xl);
    padding-top: var(--space-m);
    border-top: 1px solid var(--color-stroke);
    text-align: center;
}

/* ── Anmeldung mit Markenfläche (ADR 0053) ──────────────────────────────────────────────────────
 *
 * Links Dunkel-Lila mit Logo, Satz und drei Punkten, rechts das Formular — wie Microsoft Entra
 * oder Linear. Die Fläche ist Marke, kein Inhalt: Sie trägt nichts, was man zum Anmelden braucht,
 * und entfällt unter 801 px. Das große Signet unten rechts ist Zierde, kaum heller als der Grund.
 */
.schlicht-geteilt {
    display: grid;
    grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
    grid-template-rows: auto 1fr;
}

.schlicht-geteilt > .env-banner {
    grid-column: 1 / -1;
}

.schlicht-geteilt > .markenflaeche {
    grid-row: 2;
    grid-column: 1;
}

.schlicht-geteilt > .schlicht-inhalt {
    grid-row: 2;
    grid-column: 2;
    align-self: center;
}

/* Das Formular ohne Schatten (Daniel, 2026-10-08): Neben der Markenfläche ist eine schwebende
   Karte ein Effekt zu viel. Eine feine Linie grenzt sie vom Grund ab. '.schlicht-geteilt .card'
   (0,2,0) steht nach '.schlicht .card' und gewinnt damit. */
.schlicht-geteilt .card {
    box-shadow: none;
    border: 1px solid var(--color-stroke);
}

/* Das Logo steht auf der Fläche; über dem Formular wäre es das zweite. */
.schlicht-geteilt .schlicht-marke {
    display: none;
}

.markenflaeche {
    position: relative;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: var(--space-xl);
    padding: 4rem 3.5rem;
    background: var(--color-markenflaeche);
    color: var(--color-auf-markenflaeche);

    /* Logo in Weiß: Die Token des Logos gelten hier anders. */
    --color-marke-signet: var(--color-auf-markenflaeche);
    --color-marke-schrift: var(--color-auf-markenflaeche);
}

.markenflaeche-logo .brand-logo {
    height: 2.5rem;
}

/* Alles mit Inhalt liegt über dem Wasserzeichen. */
.markenflaeche > :not(.marken-signet) {
    position: relative;
    z-index: 1;
}

.markenflaeche-satz {
    position: relative;
    margin: var(--space-l) 0 0;
    font-size: var(--font-size-display);
    font-weight: 600;
    line-height: 40px;
    letter-spacing: -0.01em;
}

.markenflaeche-punkte {
    position: relative;
    display: grid;
    gap: var(--space-m);
    margin: 0;
    padding: 0;
    list-style: none;
    color: var(--color-auf-markenflaeche-neben);
}

.markenflaeche-punkte li {
    display: flex;
    gap: var(--space-m);
    align-items: baseline;
}

.markenflaeche-punkte li::before {
    content: "";
    flex: none;
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--color-auf-markenflaeche);
    transform: translateY(-2px);
}

/* Das große Signet als Wasserzeichen — kaum heller als der Grund, ohne Bedeutung. */
.marken-signet {
    position: absolute;
    z-index: 0;
    right: -4rem;
    bottom: -7rem;
    height: 22rem;
    width: auto;
    pointer-events: none;
    --color-marke-signet: var(--color-markenflaeche-zeichen);
}

/* Der Weg für Neue, unter der Karte: ein Satz, der Verweis darin unterstrichen wie im Fließtext. */
.registrierhinweis {
    margin: var(--space-l) 0 0;
    text-align: center;
}

.registrierhinweis a {
    font-weight: 600;
    text-decoration: underline;
}

/* Die Vertrauenszeile unter dem Formular: drei Tatsachen, klein, mit Punkt getrennt. */
.vertrauenszeile {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: var(--space-xs) var(--space-m);
    margin: var(--space-l) 0 0;
    padding: 0;
    list-style: none;
    color: var(--color-text-secondary);
    font-size: var(--font-size-caption);
}

.vertrauenszeile li + li::before {
    content: "·";
    margin-right: var(--space-m);
}

@media (max-width: 800px) {
    .schlicht-geteilt {
        display: flex;
        flex-direction: column;
    }

    .schlicht-geteilt > .markenflaeche {
        display: none;
    }

    .schlicht-geteilt .schlicht-marke {
        display: block;
    }
}

/* ── Wort-Bild-Marke ─────────────────────────────────────────────────────────────────────────
 *
 * Eingebettetes SVG aus EINER Quelle (Pages/Shared/_Logo.cshtml), nicht mehr als Hintergrundbild
 * zweier Dateien: Nur so lässt sich das Signet auf der Anmeldeseite nachzeichnen (ADR 0053), und
 * der dunkle Modus braucht keine zweite Datei — er ändert die Token '--color-marke-*'. Die Wahl
 * steht in 'data-theme' (ThemePreference), nicht in der Systemeinstellung.
 *
 * Den Namen trägt der umgebende Verweis bzw. Behälter (aria-label); das SVG ist aria-hidden.
 *
 * Breite aus dem Seitenverhältnis der Vorlage (643,76 × 168,55), damit die Fläche genau so groß ist
 * wie das Zeichen und der Fokusrahmen des Verweises nicht ins Leere ragt.
 *
 * Eigene Dateien, eigener Ursprung — die CSP erlaubt keine fremden Quellen (MANIFEST §2). */

.brand-logo {
    display: block;
    height: 1.5rem;
    width: auto;
    aspect-ratio: 643.76 / 168.55;
}

.logo-signet {
    fill: var(--color-marke-signet);
}

.logo-schrift {
    fill: var(--color-marke-schrift);
}

/*
 * Das Signet zeichnet sich nach — nur auf der Anmeldeseite (_Logo mit true, ADR 0053).
 *
 * Erst ziehen beide Formen ihre Kontur ('pathLength="1"' macht die Strichlänge zu 1, unabhängig
 * von der wirklichen Länge), dann füllen sie sich, dann blendet der Schriftzug ein. Zusammen gut
 * eine Sekunde, einmal — keine Schleife. Bei 'prefers-reduced-motion' kürzt der Block am
 * Dateiende jede Dauer auf nahezu null; wegen 'forwards' steht das Logo dann sofort fertig da.
 */
.logo-zeichnen .logo-signet {
    fill: transparent;
    stroke: var(--color-marke-signet);

    /* In Einheiten der Vorlage (168,55 hoch): 10 ergeben bei 36 px Logohöhe gut 2 px Strich. */
    stroke-width: 10;
    stroke-linejoin: round;
    stroke-dasharray: 1;
    stroke-dashoffset: 1;
    animation:
        signet-ziehen 800ms ease-in-out forwards,
        signet-fuellen 350ms ease-out 750ms forwards;
}

/* Auf der Anmeldeseite eine Stufe größer — sonst ist das Zeichnen bei 24 px kaum zu sehen. */
.schlicht-marke .logo-zeichnen {
    height: 2.25rem;
}

.logo-zeichnen .logo-signet:nth-child(2) {
    animation-delay: 180ms, 900ms;
}

.logo-zeichnen .logo-schrift {
    opacity: 0;
    animation: schrift-einblenden 400ms ease-out 950ms forwards;
}

@keyframes signet-ziehen {
    to {
        stroke-dashoffset: 0;
    }
}

@keyframes signet-fuellen {
    to {
        fill: var(--color-marke-signet);
        stroke-width: 0;
    }
}

@keyframes schrift-einblenden {
    to {
        opacity: 1;
    }
}

/* Reduzierte Bewegung: sofort das fertige Logo. Der allgemeine Block am Dateiende kürzt nur die
   DAUER, nicht die Verzögerung — der Schriftzug stünde sonst knapp eine Sekunde unsichtbar da. */
@media (prefers-reduced-motion: reduce) {
    .logo-zeichnen .logo-signet {
        animation: none;
        fill: var(--color-marke-signet);
        stroke-width: 0;
    }

    .logo-zeichnen .logo-schrift {
        animation: none;
        opacity: 1;
    }
}

/* Vor der Anmeldung dieselbe Fassung in derselben Größe, nur mittig (siehe .schlicht-marke). */
.schlicht-marke .brand-logo {
    margin: 0 auto;
}

/* Die Auswahlspalte in Zuordnungslisten: so schmal wie das Kästchen, damit die Spalte daneben
 * nicht verrutscht. */
.spalte-auswahl {
    width: 2.5rem;
    text-align: center;
}

/* ── QR-Code einlesen (öffentliche Prüfabfrage) ──────────────────────────────────────────────
 *
 * Das Symbol steht unter dem Eingabefeld und nicht darin: In einem Feld hätte es keine
 * Berührfläche von 44 px, die eine Hand mit Handschuh trifft (WCAG 2.5.5). */

.nummer-kamera {
    display: inline-flex;
    align-items: center;
    gap: var(--space-xs);
    min-height: 2.75rem;
    margin-top: var(--space-xs);
}

.nummer-kamera svg {
    width: 1.25rem;
    height: 1.25rem;
    flex: none;
}

.qr-sucher {
    margin-top: var(--space-m);
    text-align: center;
}

.qr-sucher video {
    width: 100%;
    max-width: 100%;
    border-radius: var(--radius-md);
    background: var(--color-canvas);

    /* Ein hohes Bild fuellt sonst den Bildschirm, und die Schaltflaeche zum Abbrechen liegt
       unterhalb des sichtbaren Bereichs — ausgerechnet die, die man dann sucht. */
    max-height: 60vh;
    object-fit: cover;
}

/* Die rechtliche Fußzeile. Unaufdringlich, aber auf jeder Seite — § 5 DDG verlangt „ständig
 * verfügbar", nicht „auffällig". */
.rechtsfuss {
    margin-top: var(--space-xl);
    padding-top: var(--space-m);
    border-top: 1px solid var(--color-stroke);
    display: flex;
    gap: var(--space-s);
    justify-content: center;
    font-size: var(--font-size-caption);
    color: var(--color-text-secondary);
}

.rechtsfuss a {
    color: var(--color-text-secondary);
}
