/* App Factory — global styles (self-hosted, no CDN; FR-023).
   f18 (T002): design-token fundament per contracts/design-system.md —
   token values 1:1 from mockups/version-4/styles.css:5-29 plus the generic
   building blocks (page head, cards, badges/tags/chips, buttons, inputs,
   empty-hint, toast/modal basics).
   f18 (T027, US6): light token set as [data-theme="light"] — same structure,
   light color world (dark stays the leading design and the default). */

/* ===== Design tokens (dark = leading design, :root; values 1:1 mockup) ===== */

:root {
    /* Surfaces */
    --bg: #0d1017;
    --bg-2: #12161f;
    --bg-3: #1a2029;
    --bg-4: #222a37;
    /* Borders */
    --border: #2a3342;
    --border-light: #354052;
    /* Text levels */
    --text: #e4e9f2;
    --text-2: #9aa5b8;
    --text-3: #68738a;
    /* Accent */
    --accent: #6c8cff;
    --accent-2: #4da3ff;
    /* Signal colors */
    --green: #3fce8b;
    --yellow: #ffb020;
    --red: #ff5c5c;
    /* f41 T012 [DESIGN] (038 R1): Dunkelrot als eigener Signal-Token —
       „blockiert" muss neben „fehlgeschlagen" (--red) klar unterscheidbar
       bleiben; tiefes Karmin statt Rot-Ableitung je Nutzungsort. */
    --red-dark: #a3263c;
    /* 171 B5 (karten-markierung §2, FR01 A4): Orange = „wartet“ (Antwort
       oder Vorgänger). Liegt im Farbton zwischen --red (Störung) und
       --yellow (Hinweis), damit es von beiden getrennt bleibt. */
    --orange: #ff8a3d;
    --purple: #b57bff;
    --pink: #ff7bc1;
    --cyan: #38d9c4;
    --lime: #9fd44a;
    /* Signal text on signal tints (badges/chips): lighter than the plain
       signal color on dark surfaces (mockup badge text values 1:1) —
       f18 (T027): the light set swaps them for dark, contrast-strong
       counterparts; structure and building blocks stay untouched. */
    --red-text: #ff8080;
    --yellow-text: #ffc45e;
    --orange-text: #ffae70;
    --blue-text: #7cb9ff;
    --violet-text: #b57bff;
    /* Shape */
    --radius: 10px;
    --radius-sm: 7px;
    --shadow: 0 8px 30px rgba(0, 0, 0, .45);
    /* Fonts (system mapping — CDN ban, contracts/design-system.md) */
    --font: "Segoe UI", system-ui, -apple-system, sans-serif;
    --mono: "Cascadia Code", "JetBrains Mono", Consolas, monospace;
    /* Layout-Konstanten. 162 B5 (T018; seitenleiste §2; research R11): der
       Rahmen ist die Seitenleiste links (voll 240 px, Zeichen-Leiste 60 px),
       unter 700 px eine Kopfzeile (50 px) mit Schublade. Über dem Inhalt
       steht die Brotkrumen-Zeile. --kopf-höhe ist weiter „die Höhe des
       Rahmens über dem Inhalt“: ab 700 px die Brotkrumen-Zeile, darunter
       Kopfzeile + Brotkrumen-Zeile. Seiten, die ihre Höhe aus der
       Fensterhöhe rechnen, ziehen --kopf-höhe ab und bleiben unverändert
       (vorher: die Höhe der beiden Kopf-Stöcke 072). */
    --leiste-breite: 240px;
    --zeichenleiste-breite: 60px;
    --kopfzeile-höhe: 50px;
    --brotkrumen-höhe: 34px;
    --kopf-höhe: var(--brotkrumen-höhe);
    --page-padding: 22px 26px 60px;
    /* 149 T001 (contracts/werkbank-ui.md §1): getönte Flächen und die feste
       Listenbreite der Werkbank, 1:1 aus mockups/masken-look-and-feel/
       gemeinsam/basis.css. Die Tönungen gelten in beiden Themes (Vorlage). */
    --tint-green: rgba(63, 206, 139, .13);
    --tint-yellow: rgba(255, 176, 32, .13);
    --tint-red: rgba(255, 92, 92, .13);
    --tint-orange: rgba(255, 138, 61, .14);
    --tint-accent: rgba(108, 140, 255, .14);
    --tint-grey: rgba(154, 165, 184, .13);
    /* 156 Nachtrag M5 (Vertrag transkript-werkbank §10 M5): Fundstellen der
       Lauf-Suche wie im Browser — jedes Vorkommen leicht hinterlegt, das
       aktuelle kräftig mit eigenem Text-Kontrast (::highlight unten). */
    --such-fund: rgba(255, 176, 32, .24);
    --such-fund-aktiv: #ffb020;
    --such-fund-aktiv-text: #0d1017;
    --liste-breite: 380px;
    /* Was die Werkbank von der Fensterhöhe abzieht: Seitenabstand oben und
       unten (--page-padding 22 + 60) plus MaskenKopf (49 px hoch mit dem
       h1-Reset unten, + 20 px Abstand) = 151, 1 px Reserve. Masken mit
       Hinweisleiste bekommen den Zuschlag über .af-hinweisleiste +
       .af-werkbank. Gemessen 2026-09-25 (Chromium, 1440×900, 149 Batch 2):
       Kopf 49 px, Leiste 37 px ohne und 48 px mit Knopf. */
    --werkbank-abzug: 152px;
    /* 172 B3 (Mockup A, variante-a-kapitälchen-leiste.html:29–30): weicher
       Schatten unter einem klebenden Gruppenkopf der Listen nach Alter. */
    --ag-kante: 0 8px 14px -10px rgba(0, 0, 0, .55);
    /* Seitliches Polster des Scroll-Behälters, bis an das der klebende
       Gruppenkopf reicht (.af-liste .af-liste-scroll: 8 px). Behälter mit
       anderem Polster setzen den Wert selbst (Chats: 6 px). */
    --af-ag-rand: 8px;
}

/* ===== Light token set (f18 T027, US6; F01 C2: both themes cover the
   entire app — same structure, light color world only; shape, fonts and
   layout constants carry over unchanged). Surfaces follow the inverted
   mockup level logic (page < card < inset < control), signal colors are
   readable as text AND usable as dot/edge/fill on light surfaces. ===== */

/* 162 B5 (research R11): unter 700 px trägt der Rahmen die Kopfzeile ⑥ über
   der Brotkrumen-Zeile — beide zählen zur Höhe über dem Inhalt. */
@media (max-width: 699.98px) {
    :root {
        --kopf-höhe: calc(var(--kopfzeile-höhe) + var(--brotkrumen-höhe));
    }
}

[data-theme="light"] {
    /* Surfaces */
    --bg: #f2f4f9;
    --bg-2: #ffffff;
    --bg-3: #eaeef6;
    --bg-4: #dfe5f0;
    /* Borders */
    --border: #d6dce9;
    --border-light: #c2cbdd;
    /* Text levels */
    --text: #1c2536;
    --text-2: #49566f;
    --text-3: #6d7889;
    /* Accent */
    --accent: #3d62d8;
    --accent-2: #1e63c4;
    /* Signal colors */
    --green: #0e8a52;
    --yellow: #a35d00;
    --red: #d33636;
    /* f41 T012 [DESIGN] (038 R1): dunkles, kontraststarkes Gegenstück für
       helle Flächen — Maroon neben dem hellen Rot (dunkel = Leitdesign). */
    --red-dark: #8c1f2f;
    /* 171 B5: Orange auf hellen Flächen — Kontrast zur Karte (--bg-3) ≥ 3:1. */
    --orange: #c4520a;
    --purple: #7c46d6;
    --pink: #c02d76;
    --cyan: #0b9486;
    --lime: #5c8a1e;
    /* Signal text on signal tints — dark, contrast-strong counterparts. */
    --red-text: #b3222b;
    --yellow-text: #8a5300;
    --orange-text: #9a3f06;
    --blue-text: #1e5cae;
    --violet-text: #7c46d6;
    /* Shape — subtler shadow on light surfaces. */
    --shadow: 0 8px 30px rgba(23, 32, 56, .14);
    /* 156 Nachtrag M5: Fundstellen der Lauf-Suche auf hellen Flächen. */
    --such-fund: rgba(255, 176, 32, .30);
    --such-fund-aktiv: #ff9f1a;
    --such-fund-aktiv-text: #1c2536;
    /* 172 B3: Kante des klebenden Gruppenkopfs, leiser auf hellem Grund. */
    --ag-kante: 0 8px 14px -10px rgba(23, 32, 56, .25);
}

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

html,
body {
    margin: 0;
    padding: 0;
    height: 100%;
}

/* f18 US5 (T022, F01 C1): dark mockup-4 base look — the page scrolls
   inside the layout's .page area, not the window (mockup styles.css
   body rule); 14px base size per contracts/design-system.md. */

body {
    font-family: var(--font);
    font-size: 14px;
    line-height: 1.5;
    color: var(--text);
    background-color: var(--bg);
    overflow: hidden;
}

h1,
h2,
h3 {
    line-height: 1.25;
}

/* QA-Nacharbeit (Befund B, verfeinert nach Re-Verifikation): app.js setzt
   programmatisch den Fokus auf die Seitenüberschrift (Screenreader kündigen
   die neue Seite an) — der Browser-Standardrahmen (outline: auto) war danach
   sichtbar. Die :focus-visible-Heuristik matcht hier trotz programmatischem
   Fokus, daher scopes diese Regel auf das runtime-gesetzte tabindex="-1":
   Solche Überschriften sind per Tastatur-Tab NICHT erreichbar — der Rahmen
   dient keinem Tastaturnutzer und kann gefahrlos entfallen. */
h1[tabindex="-1"]:focus {
    outline: none;
}

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

a:hover {
    text-decoration: underline;
}

button,
input,
select,
textarea {
    font: inherit;
}

label {
    display: block;
    margin-bottom: 0.25rem;
    font-weight: 500;
    color: var(--text-2);
}

/* Inputs follow the mockup element style (styles.css:59-71). */
input,
select,
textarea {
    padding: 8px 11px;
    font-size: 13.5px;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background-color: var(--bg-3);
    color: var(--text);
    outline: none;
    transition: border-color .15s;
}

input:focus,
select:focus,
textarea:focus {
    border-color: var(--accent);
}

textarea {
    resize: vertical;
    line-height: 1.5;
}

/* Buttons follow the mockup .btn base (styles.css:209-225) so plain
   stock buttons adopt the dark look without per-page classes. */
button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 7px;
    padding: 8px 15px;
    border: 1px solid var(--border-light);
    border-radius: var(--radius-sm);
    background-color: var(--bg-4);
    color: var(--text);
    font-size: 13px;
    font-weight: 600;
    cursor: pointer;
    transition: filter .12s, background .12s;
}

button:hover {
    filter: brightness(1.15);
}

button:disabled {
    opacity: .5;
    cursor: not-allowed;
}

.validation-message {
    color: var(--red);
}

::-webkit-scrollbar {
    width: 10px;
    height: 10px;
}

::-webkit-scrollbar-track {
    background: transparent;
}

::-webkit-scrollbar-thumb {
    background: var(--border-light);
    border-radius: 5px;
}

::-webkit-scrollbar-thumb:hover {
    background: var(--text-3);
}

/* ===== Generic building blocks (contracts/design-system.md; both themes
   use the same structure — pages adopt them in the design lane) ===== */

/* Page head: title, sub line, action slot. */
.af-page-head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 16px;
    margin-bottom: 20px;
    flex-wrap: wrap;
}

.af-page-title {
    font-size: 21px;
    font-weight: 700;
}

.af-page-sub {
    color: var(--text-2);
    font-size: 13px;
    margin-top: 3px;
}

/* Card. */
.af-card {
    background: var(--bg-2);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 16px 18px;
}

.af-card-title {
    font-size: 14px;
    font-weight: 700;
    margin-bottom: 12px;
    display: flex;
    align-items: center;
    gap: 8px;
}

/* Buttons: base + primary/green/danger/sm. */
.af-btn {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 8px 15px;
    border-radius: var(--radius-sm);
    font-size: 13px;
    font-weight: 600;
    background: var(--bg-4);
    border: 1px solid var(--border-light);
    color: var(--text);
    cursor: pointer;
    transition: filter .12s, background .12s;
}

.af-btn:hover {
    filter: brightness(1.15);
}

.af-btn:disabled {
    opacity: .5;
    cursor: not-allowed;
}

.af-btn-primary {
    background: var(--accent);
    border-color: var(--accent);
    color: #fff;
}

.af-btn-green {
    background: var(--green);
    border-color: var(--green);
    color: #06251a;
}

.af-btn-danger {
    background: rgba(255, 92, 92, .15);
    border-color: rgba(255, 92, 92, .4);
    color: var(--red);
}

.af-btn-sm {
    padding: 5px 10px;
    font-size: 12px;
}

/* Inputs on token surfaces. */
.af-input {
    background: var(--bg-3);
    border: 1px solid var(--border);
    color: var(--text);
    border-radius: var(--radius-sm);
    padding: 8px 11px;
    font-size: 13.5px;
    outline: none;
    transition: border-color .15s;
}

.af-input:focus {
    border-color: var(--accent);
}

/* Badges: pill-shaped uppercase; signal variants per priority/state. */
.af-badge {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-size: 10.5px;
    font-weight: 700;
    padding: 2.5px 8px;
    border-radius: 999px;
    text-transform: uppercase;
    letter-spacing: .4px;
}

.af-badge-red {
    background: rgba(255, 92, 92, .18);
    color: var(--red-text);
}

.af-badge-yellow {
    background: rgba(255, 176, 32, .16);
    color: var(--yellow-text);
}

/* 171 B5 (karten-markierung §2): „Wartet“ in Listen — Orange, eigener Farbton. */
.af-badge-orange {
    background: var(--tint-orange);
    color: var(--orange-text);
}

.af-badge-blue {
    background: rgba(77, 163, 255, .16);
    color: var(--blue-text);
}

/* 144 R B3 (MOCK .b-violett :140): die violette Familie der Richtungs-Marke
   „⬊ eingehend" im Nachrichten-Detail. */
.af-badge-violet {
    background: rgba(181, 123, 255, .15);
    color: var(--violet-text);
}

.af-badge-neutral {
    background: rgba(154, 165, 184, .15);
    color: var(--text-2);
}

/* Tags/chips. */
.af-tag {
    font-size: 11px;
    padding: 2px 8px;
    border-radius: 999px;
    background: var(--bg-4);
    color: var(--text-2);
    border: 1px solid var(--border);
}

/* 144 D (agenten-austausch, MOCK .punkt :168/.schalter :179): die zwei
   Atome der Kanal-Stände — der an/aus-Punkt (reine Anzeige, nie bedienbar)
   und der Schalter der Ausgangs-Freigabe (40×22, grün im AN-Stand, im
   Lauf inaktiv). Familie-Bausteine, weil Karte (links) und Gesprächskopf
   (rechts) dieselben tragen — eine Gestalt, eine Stelle. */
.af-punkt {
    display: inline-block;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    flex: none;
    background: var(--text-3);
    opacity: .5;
}

.af-punkt-an {
    background: var(--green);
    opacity: 1;
}

.af-schalter {
    position: relative;
    width: 40px;
    height: 22px;
    flex: none;
    border-radius: 999px;
    background: var(--bg-4);
    border: 1px solid var(--border-light);
    padding: 0;
    cursor: pointer;
    transition: background .15s, border-color .15s;
}

.af-schalter::after {
    content: "";
    position: absolute;
    top: 2px;
    left: 2px;
    width: 16px;
    height: 16px;
    border-radius: 50%;
    background: var(--text-3);
    transition: transform .15s, background .15s;
}

.af-schalter.af-schalter-an {
    background: rgba(63, 206, 139, .22);
    border-color: rgba(63, 206, 139, .55);
}

.af-schalter.af-schalter-an::after {
    transform: translateX(18px);
    background: var(--green);
}

.af-schalter:disabled {
    opacity: .55;
    cursor: progress;
}

/* Honest empty state. */
.af-empty-hint {
    color: var(--text-3);
    font-size: 12.5px;
    text-align: center;
    padding: 14px 8px;
    border: 1px dashed var(--border-light);
    border-radius: var(--radius-sm);
}

/* Toast basics: bottom right, never covering interactive elements. */
.af-toasts {
    position: fixed;
    right: 16px;
    bottom: 16px;
    display: flex;
    flex-direction: column;
    gap: 8px;
    z-index: 300;
}

.af-toast {
    background: var(--bg-3);
    border: 1px solid var(--border);
    border-left: 3px solid var(--accent);
    border-radius: var(--radius-sm);
    padding: 10px 14px;
    color: var(--text);
    box-shadow: var(--shadow);
    max-width: 360px;
}

.af-toast-success {
    border-left-color: var(--green);
}

.af-toast-error {
    border-left-color: var(--red);
}

.af-toast-warning {
    border-left-color: var(--yellow);
}

/* Screen-reader-only: Standard-Utility, 1:1 mockups/masken-look-and-feel/
   gemeinsam/basis.css. Befund 156 Pixel-Treue (Gate 20260930T041248): der
   Baum-Statustext (TranscriptLaufBaum „, Erfolgreich") und das Suchlabel
   (TranscriptVerlauf „Im Lauf suchen") nutzen die Klasse, sie war aber in
   keinem geladenen Stylesheet definiert — der Text renderte sichtbar. */
.sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* ======================================================================
   Die Dialog-Familie (Modals in Mockup-Gestalt).

   Hausregel (Zusammenführung 2026-09-13, PRODUCTION-CHECKLIST
   „Rest-Inkonsistenzen der Dialog-Familie"): JEDER Dialog der App baut auf
   genau diesen Bausteinen auf — Overlay, Panel, Überschrift (h2),
   Aktionszeile, Knopf-Rollen, Einblenden. Was ein einzelner Dialog eigenes
   braucht (Breite, Feldsprache), steht in seinem Scoped-CSS; Fläche,
   Rahmen, Radius, Innenabstand und die Knopf-Farben kommen NUR von hier.
   Vorher trugen drei Scoped-Dateien je eine eigene Kopie derselben Werte —
   und liefen darüber auseinander.

   Knopf-Reihenfolge ist Hausregel, nicht Geschmack: neutral links
   („Abbrechen"), Akzent rechts (der bestätigende Weg). Die Farben dazu
   sind .af-modal-cancel und .af-modal-confirm.
   ====================================================================== */
.af-modal-overlay {
    position: fixed;
    inset: 0;
    background: rgba(5, 8, 14, .62);
    display: grid;
    place-items: center;
    z-index: 200;
}

.af-modal {
    background: var(--bg-2);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
    padding: 18px 20px;
    width: min(520px, calc(100vw - 32px));
}

.af-modal h2 {
    font-size: 17px;
    margin: 0 0 16px;
    /* Befund 118 (2026-09-19, Fachperson wörtlich: „Überlauf darf es nicht
       geben. ‚…' anzeigen und Tooltip mit dem gesamten Text."): Titel mit
       Datenanteil („Aufgabe archivieren: <Titel>") laufen einzeilig in den
       Auslassungspunkt; der volle Text bleibt im title-Attribut lesbar
       (Tooltip). Der Schutz sitzt hier am Familien-Baustein und gilt damit
       für JEDEN Dialog auf .af-modal — nicht nur für eine Schwester.
       min-width: 0 hält die Zeile in Flex-/Grid-Zusammenhängen formatierbar. */
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
}

/* Der erklärende Fließtext eines Dialogs (Bestätigungen). Stand bis zur
   Zusammenführung doppelt in zwei Scoped-Dateien — eine davon ohne jede
   Wirkung (Restbestand des f60-Defekts). */
.af-modal-message {
    margin: 0;
    color: var(--text-2);
    font-size: 13px;
    line-height: 1.55;
}

.af-modal-actions {
    display: flex;
    justify-content: flex-end;
    gap: 10px;
    margin-top: 20px;
    padding-top: 16px;
    border-top: 1px solid var(--border);
}

/* Die beiden Knopf-Rollen der Familie. Der bestätigende Weg trägt den
   Akzent und steht rechts; der neutrale Weg bleibt der ruhige
   Bestandsknopf und steht links. */
.af-modal-confirm {
    background: var(--accent);
    border-color: var(--accent);
    color: #fff;
}

.af-modal-cancel {
    background: var(--bg-4);
    border-color: var(--border);
    color: var(--text-2);
}

.af-modal-cancel:hover {
    filter: none;
    color: var(--text);
}

/* 149 T005 (FR-007; Vorlage basis.css:477-487): der Bestätigungsdialog einer
   zerstörenden Aktion bestätigt ROT — volle Fläche statt des blassen
   .af-btn-danger der Knopfleisten. Eine Nachricht mit Markup (mehrere
   Absätze) behält den Abstand der Vorlage; der Sperrgrund einer gesperrten
   Aktion steht sichtbar unter der Nachricht (Vorlage .warnung). */
.af-modal-confirm.af-btn-danger {
    background: var(--red);
    border-color: var(--red);
    color: #fff;
}

.af-modal-message p {
    margin: 0;
}

.af-modal-message p + p {
    margin-top: 8px;
}

.af-modal-warnung {
    margin: 8px 0 0;
    color: var(--yellow-text);
    font-size: 13px;
    font-weight: 600;
    line-height: 1.55;
}

/* Ruhiges Aufkommen für die GANZE Familie: das Overlay dimmt, das Panel
   steigt leicht auf — und nur, wenn Bewegung erwünscht ist. Vorher hing
   dieselbe Bewegung an zwei einzelnen Dialogen, zwei andere standen
   übergangslos da. */
@media (prefers-reduced-motion: no-preference) {
    .af-modal-overlay {
        animation: af-modal-overlay-in .16s ease-out;
    }

    .af-modal {
        animation: af-modal-in .18s ease-out;
    }

    @keyframes af-modal-overlay-in {
        from {
            opacity: 0;
        }

        to {
            opacity: 1;
        }
    }

    @keyframes af-modal-in {
        from {
            opacity: 0;
            transform: translateY(6px) scale(.985);
        }

        to {
            opacity: 1;
            transform: none;
        }
    }
}

/* Form rows inside modals/cards (mockup .form-row/.form-hint). */
.af-form-row {
    margin-bottom: 14px;
}

.af-form-row label {
    display: block;
    font-size: 12px;
    font-weight: 700;
    color: var(--text-2);
    margin-bottom: 6px;
    text-transform: uppercase;
    letter-spacing: .4px;
}

.af-form-row input,
.af-form-row textarea,
.af-form-row select {
    width: 100%;
}

.af-form-hint {
    font-size: 11.5px;
    color: var(--text-3);
    margin-top: 5px;
    line-height: 1.5;
}

/* Tables on token surfaces (mockup user-/container-/eval-table). */
.af-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 12.5px;
}

.af-table th {
    text-align: left;
    padding: 9px 12px;
    color: var(--text-3);
    font-size: 10.5px;
    text-transform: uppercase;
    letter-spacing: .6px;
    border-bottom: 1px solid var(--border);
}

.af-table td {
    padding: 10px 12px;
    border-bottom: 1px solid var(--border);
    vertical-align: middle;
}

.af-table tr:last-child td {
    border-bottom: none;
}

.af-table tr:hover td {
    background: var(--bg-3);
}

/* ===== 174 Sortierkopf (T007; contracts/sortierkopf-baustein.md §5) =====
   Der Spaltenkopf aller acht Datentabellen — EINE Regel, kein Scoped CSS je
   Fläche. Ruhig wie der übrige Tabellenkopf: der Knopf erbt Schrift, Größe,
   Kapitälchen und Farbe des th. Inaktiv steht nur ein leises ↕ da; erst die
   aktive Spalte wird deutlich (Titel in Textfarbe, Dreieck in Akzent,
   Akzent-Unterkante am th). Die Klickfläche ist der ganze Kopf samt Polster:
   eine leere Schicht (::after) des Knopfs deckt das th. Nur Tokens. */

/* Rückfall ohne Gewicht: QuickGrid positioniert th selbst (scoped). :where()
   lässt jede Flächenregel gewinnen — klebende Spalten bleiben sticky (auch
   sticky trägt die Schicht). Ohne positioniertes th läge die Schicht über
   der ganzen Tabelle. */
:where(th:has(.af-sortkopf)) {
    position: relative;
}

/* QuickGrids Kopf-Hülle ist selbst positioniert und schrumpfte die Schicht
   auf die Inhaltsbreite — für Sortierköpfe tritt sie zurück. */
th > .col-header-content:has(> .af-sortkopf) {
    position: static;
}

/* Hebt die globale Knopfgestalt (Polster, Rahmen, Grund, 13 px fett) auf. */
.af-sortkopf {
    display: inline-flex;
    flex: 1 1 auto;
    min-width: 0;
    align-items: center;
    gap: 5px;
    padding: 0;
    border: 0;
    border-radius: 0;
    background: transparent;
    font: inherit;
    color: inherit;
    letter-spacing: inherit;
    text-transform: inherit;
    white-space: nowrap;
    cursor: pointer;
    transition: color .12s;
}

.af-sortkopf::after {
    content: "";
    position: absolute;
    inset: 0;
}

.af-sortkopf:hover {
    color: var(--text-2);
    filter: none;
}

/* Der Fokusring liegt um den ganzen Kopf, nicht nur um das Wort —
   Ring wie .af-ag-kopf (2 px Akzent, nach innen). */
.af-sortkopf:focus-visible {
    outline: none;
}

.af-sortkopf:focus-visible::after {
    outline: 2px solid var(--accent);
    outline-offset: -2px;
}

.af-sortkopf-text {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Feste Breite: der Wechsel ↕ → ▲/▼ verschiebt keine Spaltenkante. */
.af-sortkopf-zeichen {
    flex: none;
    width: 10px;
    font-size: 10px;
    line-height: 1;
    text-align: center;
    color: var(--text-3);
    opacity: .4;
    transition: opacity .12s, color .12s;
}

.af-sortkopf:not(.af-sortkopf-aktiv):hover .af-sortkopf-zeichen,
.af-sortkopf:not(.af-sortkopf-aktiv):focus-visible .af-sortkopf-zeichen {
    opacity: .8;
}

.af-sortkopf-aktiv {
    color: var(--text);
}

.af-sortkopf-aktiv .af-sortkopf-zeichen {
    font-size: 8px;
    color: var(--accent);
    opacity: 1;
}

/* Rechtsbündige Spalten (QuickGrid Align.End): das Zeichen steht vor dem
   Titel, der Titel schließt bündig mit den Zahlen darunter ab. */
th.col-justify-end .af-sortkopf {
    flex-direction: row-reverse;
}

th[aria-sort="ascending"],
th[aria-sort="descending"] {
    box-shadow: inset 0 -2px 0 var(--accent);
}

@media (prefers-reduced-motion: reduce) {
    .af-sortkopf,
    .af-sortkopf-zeichen {
        transition: none;
    }
}

/* ===== Ende Sortierkopf (174) ===== */

/* Narrow reading width for readability-critical pages (A5/R6): the page
   area itself fills the window; forms and admin lists may opt into this
   measure after the mockup card size. */
.af-narrow {
    width: 100%;
    max-width: 72rem;
    margin: 0 auto;
}

/* Mono ids/kennungen (contracts/design-system.md). */
.af-mono {
    font-family: var(--mono);
}

/* ===== 149 Werkbank-Familie (T001; contracts/werkbank-ui.md §1, §1.1; plan A1)

   Die Bausteine der Masken nach dem Bauplan „Werkbank“. Werte 1:1 aus
   mockups/masken-look-and-feel/gemeinsam/basis.css, Namen mit Präfix af-.
   Global statt Scoped (plan A1): Scoped CSS greift nicht über
   Komponentengrenzen (Befund 140), und die Masken teilen dieselben Regeln.

   Farben NUR über Tokens (beide Themes aus einer Regel, keine hellen
   Sonderfarben — LightRestProbe der DesignSmokeTests). Wo die Vorlage eine
   Tönung als rgba-Wert schreibt, steht sie wie die Bestands-Marken als
   rgba der Token-Farbe.

   Die globale button-Regel oben zentriert, fettet und hinterlegt jeden
   Knopf. Die Vorlage erbt dagegen die Schrift (button { font: inherit }).
   Deshalb heben Listenzeile, Chip, Menüeintrag, Reiter und Segment die
   Knopfgestalt ausdrücklich auf (justify-content, font-weight, filter). ===== */

/* Symbol (Shared/Symbol.razor): Inline-SVG, erbt die Textfarbe. */
.af-i {
    width: 15px;
    height: 15px;
    flex: none;
}

.af-btn-sm .af-i {
    width: 13px;
    height: 13px;
}

/* 150 Batch 2 (FR-020, plan A3): der einheitliche Repo-Indikator — das
   Git-Symbol sitzt unmittelbar vor dem Namen (Karte, Liste, Detail-Kopf). */
.task-card-repository-symbol,
.aufgaben-repository-symbol,
.task-detail-repository-symbol {
    margin-inline-end: 5px;
}

/* 150 Nachtrag N8 (2026-09-30, Vertrag repo-setzen-am-detail §3): das
   Repository-Symbol steht im Auswahlfeld vor dem Namen — Präfix im Wrapper
   um das native select (Muster .af-suche), kein eigenes Listbox-Widget. */
.task-detail-repository-wahl {
    position: relative;
    display: inline-flex;
    align-items: center;
}

.task-detail-repository-wahl > .task-detail-repository-wahl-symbol {
    position: absolute;
    left: 10px;
    top: 50%;
    transform: translateY(-50%);
    color: var(--text-3);
    pointer-events: none;
}

.task-detail-repository-wahl > .task-detail-repository-select {
    padding-left: 32px;
}

/* ① Seitenkopf: der Aktionen-Slot rechts (MaskenKopf). 149 Batch 4 (F8):
   Bricht der Kopf um (Untertitel bis 760 px + Umschalter mit langem
   Organisationsnamen + zwei Knöpfe), bleibt der Slot rechts (FR-002) statt
   auf der zweiten Zeile nach links zu rutschen. */
.af-page-actions {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 10px;
    flex-wrap: wrap;
    margin-left: auto;
}

/* 162 Befund B-1 (SC-003/FR-029): der Bereichsumschalter trägt den Namen der
   Organisation („Organisation: <Name>“) — ein langer Name weitete den Inhalt
   bei 390 px auf 509 px. Der Umschalter passt sich der Breite an, die
   Beschriftung der Organisation bricht in ihrem Segment um (auch ein Name
   aus einem Wort); „Global“ bleibt ganz. Mit Platz bleibt alles einzeilig
   wie bisher. */
.scope-switch {
    max-width: 100%;
}

.scope-switch .af-segment {
    flex: none;
}

.scope-switch .af-segment.scope-seg-org {
    flex: 0 1 auto;
    min-width: 0;
    white-space: normal;
    overflow-wrap: anywhere;
    text-align: left;
}

/* Nur im MaskenKopf (.af-page-text): die Bestands-Köpfe ohne Baustein
   behalten ihren Abstand, bis ihr Masken-Batch sie umstellt.
   149 Batch 2 (Review B1): app.css hat keinen globalen Rand-Reset für
   Überschriften (Vorlage basis.css:50 „h1 … { margin: 0 }“) — die h1 des
   Kopfs trug 0,67em = 14 px oben und unten, und .page rollte mit jeder
   Werkbank-Maske um 24–35 px (zweite Bildlaufleiste). */
.af-page-text .af-page-title {
    margin: 0;
}

.af-page-text .af-page-sub {
    max-width: 760px;
    margin-bottom: 0;
}

/* ② Hinweisleiste — Zustand der ganzen Fläche. */
.af-hinweisleiste {
    flex: none;
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 14px;
    margin-bottom: 14px;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--bg-2);
    font-size: 12.5px;
    color: var(--text-2);
}

.af-hinweisleiste b {
    color: var(--text);
    font-weight: 600;
}

.af-hinweisleiste-rechts {
    margin-left: auto;
    display: flex;
    gap: 8px;
}

/* Knöpfe: Ghost, Symbol, Link (die Basis .af-btn steht oben). */
.af-btn-ghost {
    background: transparent;
    border-color: var(--border);
    color: var(--text-2);
}

.af-btn-ghost:hover {
    background: var(--bg-3);
    color: var(--text);
    filter: none;
}

.af-btn-link {
    background: transparent;
    border: 0;
    padding: 0;
    color: var(--accent-2);
    font-weight: 600;
    font-size: inherit;
}

.af-btn-link:hover {
    text-decoration: underline;
    filter: none;
}

.af-btn-icon {
    width: 29px;
    height: 29px;
    padding: 0;
    flex: none;
    display: inline-grid;
    place-items: center;
    border-radius: var(--radius-sm);
    background: transparent;
    border: 1px solid transparent;
    color: var(--text-2);
    transition: background .12s, color .12s, border-color .12s;
}

.af-btn-icon:hover,
.af-btn-icon[aria-expanded="true"] {
    background: var(--bg-3);
    border-color: var(--border);
    color: var(--text);
    filter: none;
}

/* Marken: die zwei Farben, die der Bestand noch nicht hatte. */
.af-badge-green {
    background: rgba(63, 206, 139, .15);
    color: var(--green);
}

.af-badge-cyan {
    background: rgba(56, 217, 196, .13);
    color: var(--cyan);
}

.af-punkt-gelb {
    background: var(--yellow);
    opacity: 1;
}

.af-punkt-rot {
    background: var(--red);
    opacity: 1;
}

.af-punkt-akzent {
    background: var(--accent);
    opacity: 1;
}

/* 165 B4 (FR-011, contracts/marken-ram-warnung.md §2): DER Warn-Puls — die
   RAM-Warn-Anzeichen (Badge-Punkt der Listenzeile, Chip-Punkt der Filter,
   Detail-Marke; ab 165 B5 auch die Menü-Marke) pulsieren, solange der
   Vorfall im 24-h-Fenster liegt. Global, weil derselbe Punkt in mehreren
   Komponenten-Scopes lebt (FilterChips, Masken); die Farbe trägt der
   Träger, der Puls ist reine Opazität — beide Themes ohne eigene Farbwerte. */
@media (prefers-reduced-motion: no-preference) {
    .af-warn-puls {
        animation: af-warn-puls 1.8s ease-in-out infinite;
    }
}

@keyframes af-warn-puls {
    0%,
    100% {
        opacity: 1;
    }

    50% {
        opacity: .35;
    }
}

/* Filter-Chips (FilterChips; Vorbild InboxFilterBar). */
.af-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    align-items: center;
}

.af-chip-titel {
    font-size: 10px;
    font-weight: 700;
    letter-spacing: .6px;
    text-transform: uppercase;
    color: var(--text-3);
    margin-right: 2px;
}

.af-chip {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    min-height: 24px;
    padding: 3.5px 9px;
    font-size: 11.5px;
    font-weight: 600;
    border-radius: 999px;
    background: var(--bg-3);
    color: var(--text-2);
    border: 1px solid var(--border);
    white-space: nowrap;
}

.af-chip:hover {
    color: var(--text);
    border-color: var(--border-light);
    filter: none;
}

.af-chip.af-chip-an {
    background: var(--tint-accent);
    border-color: var(--accent);
    color: var(--accent);
}

.af-chip-n {
    color: var(--text-3);
    font-family: var(--mono);
    font-size: 10.5px;
}

.af-chip-an .af-chip-n {
    color: var(--accent);
}

/* Suchfeld (MaskenSuche). */
.af-suche {
    position: relative;
    display: block;
}

.af-suche > .af-i {
    position: absolute;
    left: 10px;
    top: 50%;
    transform: translateY(-50%);
    color: var(--text-3);
    pointer-events: none;
}

.af-suche input {
    width: 100%;
    padding: 8px 34px 8px 32px !important;
}

.af-suche-kbd {
    position: absolute;
    right: 9px;
    top: 50%;
    transform: translateY(-50%);
    pointer-events: none;
    min-width: 17px;
    height: 17px;
    display: grid;
    place-items: center;
    font-family: var(--mono);
    font-size: 10.5px;
    color: var(--text-3);
    border: 1px solid var(--border-light);
    border-radius: 4px;
}

.af-suche input:focus + .af-suche-kbd {
    display: none;
}

/* Segment-Umschalter (umgezogen aus EmpfangsDialog.razor.css; der
   Bereichsumschalter baut darauf auf). */
.af-segmente {
    display: inline-flex;
    background: var(--bg-3);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    padding: 3px;
    gap: 3px;
}

.af-segment {
    padding: 5px 11px;
    border-radius: 5px;
    border: 1px solid transparent;
    background: transparent;
    color: var(--text-2);
    font-size: 12.5px;
    font-weight: 600;
    display: inline-flex;
    align-items: center;
    gap: 7px;
    white-space: nowrap;
    transition: background .12s, color .12s;
}

.af-segment:hover {
    color: var(--text);
    filter: none;
}

.af-segment.af-segment-an {
    background: var(--bg-4);
    border-color: var(--border-light);
    color: var(--text);
    box-shadow: 0 1px 4px rgba(0, 0, 0, .2);
}

.af-segmente-klein .af-segment {
    padding: 3px 9px;
    font-size: 11.5px;
}

.af-seg-punkt {
    width: 7px;
    height: 7px;
    border-radius: 50%;
    opacity: .5;
}

.af-segment-an .af-seg-punkt {
    opacity: 1;
}

.af-seg-punkt-global {
    background: var(--cyan);
}

.af-seg-punkt-org {
    background: var(--purple);
}

/* Abschnitt, Reiter, Eigenschaftsliste. */
.af-abschnitt {
    padding: 14px 0 4px;
}

.af-abschnitt + .af-abschnitt {
    border-top: 1px solid var(--border);
}

.af-abschnitt-titel {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 10px;
    font-size: 10.5px;
    font-weight: 700;
    letter-spacing: .6px;
    text-transform: uppercase;
    color: var(--text-3);
}

.af-abschnitt-titel-rechts {
    margin-left: auto;
    display: flex;
    gap: 8px;
    text-transform: none;
    letter-spacing: 0;
}

.af-reiter {
    display: flex;
    gap: 2px;
    padding: 0 4px;
    border-bottom: 1px solid var(--border);
    flex: none;
}

.af-reiter-tab {
    padding: 9px 10px 8px;
    border: 0;
    border-bottom: 2px solid transparent;
    border-radius: 0;
    background: transparent;
    color: var(--text-2);
    font-size: 12.5px;
    font-weight: 600;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    margin-bottom: -1px;
}

.af-reiter-tab:hover {
    color: var(--text);
    filter: none;
}

.af-reiter-tab.af-reiter-tab-aktiv {
    color: var(--accent);
    border-bottom-color: var(--accent);
}

.af-reiter-n {
    font-family: var(--mono);
    font-size: 10.5px;
    color: var(--text-3);
}

.af-eig {
    display: grid;
    grid-template-columns: minmax(150px, 190px) minmax(0, 1fr);
    gap: 9px 18px;
    font-size: 13px;
    margin: 0;
}

.af-eig dt {
    color: var(--text-3);
    font-size: 12px;
    font-weight: 600;
    padding-top: 1px;
}

.af-eig dd {
    margin: 0;
    color: var(--text);
    min-width: 0;
    overflow-wrap: anywhere;
}

/* ③–⑤ Werkbank: Liste | Detail (Werkbank, ListenKarte). Die Seite rollt
   in .page; die Werkbank rechnet ihre Höhe aus dem Fenster, damit Liste und
   Detail je für sich rollen (Scrollposition bleibt beim Neuzeichnen). */
.af-werkbank {
    display: grid;
    grid-template-columns: var(--liste-breite) minmax(0, 1fr);
    gap: 18px;
    height: calc(100dvh - var(--kopf-höhe) - var(--werkbank-abzug));
    min-height: 420px;
}

/* Zuschlag der Hinweisleiste: 48 px Höhe MIT Knopf (af-btn-sm, 30 px) +
   14 px Abstand = 62 px (152 + 62). Eine Leiste nur mit Text ist 37 px hoch;
   die Werkbank endet dann 11 px früher — sie darf kürzer sein, aber .page
   darf nie rollen (vorher 203 px: mit Knopf 10 px Bildlauf). */
.af-hinweisleiste + .af-werkbank {
    --werkbank-abzug: 214px;
}

/* Die Karten schneiden NICHT ab (Review B1): das Menü „Weitere Filter“
   (220 px ab dem Knopf bei 256 px) und das AktionsMenü dürfen über den
   Kartenrand ragen. Gerollt wird nur im Scrollbereich (.af-liste-scroll,
   .af-detail-körper); min-height: 0 hält die Karte trotzdem in ihrer
   Rasterzeile. */
.af-liste,
.af-detail {
    display: flex;
    flex-direction: column;
    min-height: 0;
    padding: 0;
}

.af-liste-filter {
    flex: none;
    padding: 12px 12px 10px;
    border-bottom: 1px solid var(--border);
    display: flex;
    flex-direction: column;
    gap: 9px;
}

.af-liste-scroll {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
}

.af-liste .af-liste-scroll {
    padding: 8px;
}

/* Listenzeile (ListenZeile; Vorbild PersonaListPane/SecretsDesk). */
.af-lz {
    display: flex;
    align-items: flex-start;
    justify-content: flex-start;
    gap: 10px;
    width: 100%;
    text-align: left;
    padding: 9px 10px;
    margin-bottom: 2px;
    border-radius: var(--radius-sm);
    border: 1px solid transparent;
    background: transparent;
    color: var(--text);
    font-size: 14px;
    font-weight: 400;
    transition: background .12s, border-color .12s;
}

.af-lz:hover {
    background: var(--bg-3);
    filter: none;
}

.af-lz.af-lz-an {
    background: var(--bg-3);
    border-color: var(--border);
    box-shadow: inset 2.5px 0 0 var(--accent);
}

.af-lz-symbol {
    width: 28px;
    height: 28px;
    flex: none;
    display: grid;
    place-items: center;
    border-radius: var(--radius-sm);
    background: var(--bg-3);
    color: var(--text-2);
    border: 1px solid var(--border);
}

.af-lz-an .af-lz-symbol {
    color: var(--accent);
    border-color: var(--border-light);
    background: var(--bg-2);
}

.af-lz-text {
    display: block;
    flex: 1;
    min-width: 0;
}

.af-lz-titel {
    font-weight: 600;
    font-size: 13.5px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    display: flex;
    align-items: center;
    gap: 7px;
}

.af-lz-name {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
}

.af-lz-pos {
    font-family: var(--mono);
    font-size: 11px;
    color: var(--text-3);
    font-weight: 600;
}

.af-lz-meta {
    display: block;
    font-size: 11.5px;
    color: var(--text-3);
    margin-top: 1px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.af-lz-marken {
    display: flex;
    gap: 5px;
    flex-wrap: wrap;
    margin-top: 5px;
}

.af-lz-rechts {
    flex: none;
    font-size: 11px;
    color: var(--text-3);
    text-align: right;
    padding-top: 2px;
    white-space: nowrap;
}

.af-lz.af-lz-entwurf {
    border-style: dashed;
    border-color: var(--accent);
    background: var(--tint-accent);
}

/* Gruppenkopf und Listenfuß. */
.af-lg {
    font-size: 10.5px;
    font-weight: 700;
    letter-spacing: .6px;
    text-transform: uppercase;
    color: var(--text-3);
    padding: 12px 10px 6px;
    display: flex;
    align-items: center;
    gap: 7px;
}

.af-lg:first-child {
    padding-top: 4px;
}

.af-lg-hinweis {
    font-size: 11.5px;
    color: var(--text-3);
    padding: 0 10px 6px;
    line-height: 1.45;
}

.af-lf {
    flex: none;
    padding: 7px 13px;
    border-top: 1px solid var(--border);
    font-size: 11.5px;
    color: var(--text-3);
    display: flex;
    gap: 8px;
    align-items: center;
}

.af-lf-rechts {
    margin-left: auto;
}

/* 172 B3 (contracts/altersgruppen-baustein.md §6; Vorlage
   mockups/listen-nach-alter/variante-a-kapitälchen-leiste.html:18–56):
   Listen nach Alter als Kapitälchen-Leiste. Je Gruppe eine schmale
   Trennzeile — Chevron, Titel, Zeitspanne, Haarlinie, rechts die Anzahl in
   einer Kapsel. Sie klebt oben im Scroll-Behälter, bis die nächste Gruppe
   sie wegschiebt; solange sie klebt, setzt werkbank.js .af-ag-klebt, und
   die Zeile bekommt eine feine Kante. Zugeklappt wird sie leiser.

   --af-ag-rand ist das seitliche Polster des Scroll-Behälters: der Kopf
   reicht mit negativem Rand bis an dessen Kante, damit der Grund die ganze
   Breite deckt. Vorgabe 8 px (.af-liste .af-liste-scroll); die Chats-Liste
   (6 px) setzt den Wert in ihrer .razor.css. */
.af-liste .af-liste-scroll:has(> .af-ag-liste) {
    padding-top: 0;
}

.af-ag {
    position: relative;
}

.af-ag + .af-ag {
    margin-top: 4px;
}

.af-ag-kopf-h {
    position: sticky;
    top: 0;
    z-index: 4;
    margin: 0 calc(-1 * var(--af-ag-rand));
    padding: 0 var(--af-ag-rand);
    font-size: inherit;
    font-weight: inherit;
    line-height: inherit;
    background: color-mix(in srgb, var(--bg-2) 90%, transparent);
    -webkit-backdrop-filter: blur(6px);
    backdrop-filter: blur(6px);
    transition: box-shadow .15s ease;
}

/* Chrome hält einen klebenden Kopf unter dem oberen Polster des
   Scroll-Behälters (Chats: 6 px). Dieser Streifen deckt das Polster, damit
   dort keine Zeile durchscheint. In Ruhe liegt er über dem unteren Polster
   der vorigen Gruppe (.af-ag-zeilen 6 px + Abstand 4 px) — dort steht nichts. */
.af-ag-kopf-h::before {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    bottom: 100%;
    height: var(--af-ag-rand);
    background: var(--bg-2);
    pointer-events: none;
}

.af-ag-kopf-h.af-ag-klebt {
    box-shadow: 0 1px 0 var(--border), var(--ag-kante);
}

/* Der Knopf trägt af-lg (Vertrag §2). Beide Klassen im Selektor, damit
   Großschrift und Polster von .af-lg und .af-lg:first-child nicht greifen;
   die globale button-Regel wird ebenfalls aufgehoben. */
.af-lg.af-ag-kopf,
.af-lg.af-ag-kopf:first-child {
    display: flex;
    align-items: center;
    justify-content: flex-start;
    gap: 7px;
    width: 100%;
    height: 30px;
    padding: 0 4px;
    margin: 0;
    border: 0;
    border-radius: 6px;
    background: transparent;
    color: var(--text-2);
    text-align: left;
    font-size: 12.5px;
    font-weight: 700;
    text-transform: none;
    font-variant-caps: all-small-caps;
    letter-spacing: .1em;
    line-height: 1;
    transition: color .15s;
}

.af-ag-kopf:hover {
    color: var(--text);
    filter: none;
}

.af-ag-kopf:hover .af-ag-linie {
    background: var(--border-light);
}

.af-ag-kopf:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: -2px;
}

.af-ag-kopf[aria-expanded="false"] {
    color: var(--text-3);
}

/* Das Symbol „runter“ zeigt offen nach unten; zugeklappt nach rechts. */
.af-ag-chev {
    display: inline-grid;
    place-items: center;
    flex: none;
    width: 11px;
    height: 11px;
    color: var(--text-3);
    transition: transform .18s ease;
}

.af-ag-chev .af-i {
    width: 11px;
    height: 11px;
}

.af-ag-kopf[aria-expanded="false"] .af-ag-chev {
    transform: rotate(-90deg);
}

.af-ag-titel {
    flex: none;
    white-space: nowrap;
}

.af-ag-spanne {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-variant-caps: normal;
    letter-spacing: 0;
    font-weight: 500;
    font-size: 11px;
    color: var(--text-3);
}

.af-ag-linie {
    flex: 1;
    min-width: 12px;
    height: 1px;
    background: var(--border);
    transition: background .15s;
}

.af-ag-n {
    flex: none;
    min-width: 22px;
    padding: 2px 6px;
    border: 1px solid var(--border);
    border-radius: 999px;
    background: var(--bg-3);
    color: var(--text-3);
    font-family: var(--mono);
    font-variant-caps: normal;
    letter-spacing: 0;
    font-size: 10.5px;
    font-weight: 600;
    line-height: 1.2;
    text-align: center;
}

.af-ag-kopf[aria-expanded="false"] .af-ag-n {
    color: var(--text-2);
    border-color: var(--border-light);
}

/* Zugeklappt und mit dem geöffneten Eintrag: ein Akzentpunkt. */
.af-ag-auswahl {
    flex: none;
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--accent);
    box-shadow: 0 0 0 3px var(--tint-accent);
}

.af-ag-zeilen {
    padding: 2px 0 6px;
}

.af-ag-zeilen[hidden] {
    display: none;
}

/* Zählfuß: „· 24 zugeklappt“ leise direkt hinter der Zahl. */
.af-lf-zusatz {
    margin-left: -4px;
    color: var(--text-3);
    white-space: nowrap;
}

@media (prefers-reduced-motion: reduce) {
    .af-ag-kopf-h,
    .af-ag-chev,
    .af-ag-linie,
    .af-lg.af-ag-kopf {
        transition: none;
    }
}

/* Detail: Kopf, Hinweis, Körper, Formular-Fuß (Bausteine ab Batch 2). */
.af-detail > .af-leer {
    flex: 1;
}

.af-detail .af-reiter {
    padding: 0 14px;
}

.af-dk {
    flex: none;
    padding: 16px 18px 14px;
    border-bottom: 1px solid var(--border);
}

.af-dk-zeile {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    /* 162 Befund B-1 (SC-003/FR-029): reicht die Breite nicht für Symbol,
       Titel (mindestens 8rem) und Aktionen, rücken die Aktionen in eine
       eigene Zeile darunter — statt den Inhalt zu weiten (Inferenz-Konten
       bei 390 px: 452 px) oder den Titel auf wenige Zeichen zu quetschen. */
    flex-wrap: wrap;
}

.af-dk-symbol {
    width: 36px;
    height: 36px;
    flex: none;
    display: grid;
    place-items: center;
    border-radius: var(--radius-sm);
    background: var(--bg-3);
    border: 1px solid var(--border-light);
    color: var(--accent);
}

.af-dk-symbol .af-i {
    width: 18px;
    height: 18px;
}

/* 149 Batch 10 (contracts §3.2 ⑤): ein Bild als Symbol (der Avatar der
   Persona) trägt seine eigene Größe und Form — das Feld tritt zurück. */
.af-dk-symbol:has(> img) {
    width: auto;
    height: auto;
    border: 0;
    background: none;
    border-radius: 50%;
    overflow: hidden;
}

/* Nachtrag N14 (Rückmeldung 2026-10-01): das kleine Persona-Bild neben dem
   Persona-Namen (Baustein PersonaBildKlein — Lauf-Baum, Verlauf, Laufliste).
   18 px wie das Symbolmaß des Detail-Kopfs, rund; ohne Bild der
   Erstbuchstabe in derselben Form. */
.af-persona-bild {
    flex: 0 0 auto;
    width: 18px;
    height: 18px;
    border-radius: 50%;
    vertical-align: middle;
}

img.af-persona-bild {
    object-fit: cover;
}

.af-persona-bild-buchstabe {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: var(--bg-4);
    color: var(--text-2);
    font-size: 10px;
    font-weight: 700;
    line-height: 1;
}

.af-persona-bild-buchstabe::before {
    content: attr(data-buchstabe);
}

.af-dk-text {
    /* 162 Befund B-1: die Mindestbreite des Titels, ab der die Aktionen
       umbrechen (flex-basis statt 0 — sonst bräche nie etwas um). */
    flex: 1 1 8rem;
    min-width: 0;
}

.af-dk-titel {
    font-size: 17px;
    font-weight: 700;
    line-height: 1.3;
    margin: 0;
    overflow-wrap: anywhere;
}

.af-dk-titel:focus {
    outline: none;
}

.af-dk-unter {
    font-size: 12.5px;
    color: var(--text-2);
    margin-top: 2px;
}

.af-dk-marken {
    display: flex;
    flex-wrap: wrap;
    gap: 5px;
    margin-top: 7px;
}

.af-dk-aktionen {
    /* 162 Befund B-1: schrumpfbar (die Knöpfe brechen in sich um), in der
       eigenen Zeile weiter rechts (Werkbank: Aktionen rechts im Kopf). */
    flex: 0 1 auto;
    min-width: 0;
    margin-left: auto;
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
}

.af-dk-hinweis {
    display: flex;
    align-items: flex-start;
    gap: 9px;
    margin: 12px 0 0;
    padding: 9px 12px;
    border-radius: var(--radius-sm);
    border: 1px solid var(--border);
    background: var(--bg-3);
    font-size: 12.5px;
    color: var(--text-2);
}

.af-dk-hinweis .af-i {
    color: var(--blue-text);
    margin-top: 2px;
}

.af-dk-hinweis b {
    color: var(--text);
}

/* 156 Nachtrag M3 (Rückmeldung N4; Vorlage mockups/transkript-lauf
   index.html:235-236): die Art des Hinweises färbt sein Symbol —
   Blockade gelb, Fehler rot; ohne Art bleibt es blau (Info). */
.af-dk-hinweis[data-art="block"] .af-i {
    color: var(--yellow-text);
}

.af-dk-hinweis[data-art="fehler"] .af-i {
    color: var(--red-text);
}

.af-detail-körper {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    padding: 4px 20px 22px;
}

.af-formular-fuß {
    flex: none;
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 12px 18px;
    border-top: 1px solid var(--border);
}

.af-formular-fuß-rechts {
    margin-left: auto;
    display: flex;
    gap: 10px;
}

.af-dirty {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    font-size: 12px;
    color: var(--yellow-text);
    font-weight: 600;
}

.af-dirty[hidden] {
    display: none;
}

/* Aktions- und Filtermenü (AktionsMenü ab Batch 2, FilterChips). */
.af-menü-wrap {
    position: relative;
    display: inline-flex;
}

.af-menü-teppich {
    position: fixed;
    inset: 0;
    z-index: 139;
    background: transparent;
}

.af-menü {
    position: absolute;
    top: calc(100% + 5px);
    right: 0;
    z-index: 140;
    min-width: 220px;
    padding: 4px 0;
    border: 1px solid var(--border-light);
    border-radius: var(--radius);
    background: var(--bg-2);
    box-shadow: var(--shadow);
}

.af-menü.af-menü-oben {
    top: auto;
    bottom: calc(100% + 5px);
}

.af-menü.af-menü-links {
    right: auto;
    left: 0;
}

.af-menü button {
    display: flex;
    align-items: center;
    justify-content: flex-start;
    gap: 9px;
    width: 100%;
    padding: 7px 12px;
    border: 0;
    border-radius: 0;
    background: transparent;
    font-size: 12.5px;
    font-weight: 400;
    color: var(--text-2);
    text-align: left;
    white-space: nowrap;
}

.af-menü button:hover,
.af-menü button:focus-visible {
    background: var(--bg-3);
    color: var(--text);
    outline: none;
    filter: none;
}

.af-menü button.af-menü-gefahr {
    color: var(--red-text);
}

.af-menü button.af-menü-gefahr:hover {
    background: var(--tint-red);
    color: var(--red);
}

.af-menü hr {
    border: 0;
    border-top: 1px solid var(--border);
    margin: 4px 0;
}

.af-menü-titel {
    padding: 8px 12px 3px;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: .6px;
    text-transform: uppercase;
    color: var(--text-3);
}

.af-menü-check {
    width: 15px;
    display: inline-grid;
    place-items: center;
    color: var(--accent);
    flex: none;
}

.af-menü-n {
    margin-left: auto;
    padding-left: 14px;
    font-family: var(--mono);
    font-size: 10.5px;
    color: var(--text-3);
}

/* Leer-, Lade-, Fehlerzustände (LeerZustand, LadeZustand, FehlerKasten). */
.af-leer {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 8px;
    text-align: center;
    padding: 30px 22px;
    border: 1px dashed var(--border-light);
    border-radius: var(--radius);
    color: var(--text-2);
    font-size: 13px;
}

.af-leer-titel {
    font-weight: 700;
    color: var(--text);
    font-size: 13.5px;
}

.af-leer > .af-i {
    width: 26px;
    height: 26px;
    color: var(--text-3);
}

.af-leer .af-btn {
    margin-top: 6px;
}

.af-leer.af-leer-flach {
    border: 0;
}

.af-leer-hinweis {
    color: var(--text-3);
    font-size: 11.5px;
}

.af-fehler {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 12px 14px;
    border: 1px solid rgba(255, 92, 92, .45);
    border-radius: var(--radius-sm);
    background: var(--tint-red);
    color: var(--red-text);
    font-size: 13px;
    font-weight: 600;
}

.af-fehler .af-btn {
    margin-left: auto;
}

.af-skelett {
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding: 6px;
}

.af-skelett div {
    height: 44px;
    border-radius: var(--radius-sm);
    background: var(--bg-3);
}

.af-ladetext {
    font-size: 12.5px;
    color: var(--text-3);
    padding: 4px 10px 8px;
}

@media (prefers-reduced-motion: no-preference) {
    .af-menü {
        animation: af-pop .12s ease both;
    }

    .af-skelett div {
        animation: af-skelett 1.2s ease-in-out infinite;
    }

    .af-skelett div:nth-child(2) {
        animation-delay: .15s;
    }

    .af-skelett div:nth-child(3) {
        animation-delay: .3s;
    }

    .af-skelett div:nth-child(4) {
        animation-delay: .45s;
    }

    @keyframes af-pop {
        from {
            opacity: 0;
            transform: translateY(-4px);
        }

        to {
            opacity: 1;
            transform: none;
        }
    }

    @keyframes af-skelett {
        0%,
        100% {
            opacity: .55;
        }

        50% {
            opacity: 1;
        }
    }
}

/* Unter 1100 px einspaltig (Vertrag §1; die Vorlage schmälert nur): die
   Werkbank wächst mit dem Inhalt, die Liste behält eine eigene Rollhöhe. */
@media (max-width: 1100px) {
    .af-werkbank {
        grid-template-columns: minmax(0, 1fr);
        height: auto;
    }

    .af-werkbank > .af-liste {
        max-height: 60vh;
    }
}

/* 149 Batch 4 (Review B2, F8): die Maske als Flex-Spalte über die Höhe von
   .page — Seitenkopf und Hinweisleiste nehmen, was sie brauchen, die
   Werkbank den Rest. Bricht der Kopf um (langer Untertitel, Umschalter mit
   Organisationsnamen, zwei Seitenfunktionen), wird die Werkbank kürzer statt
   .page zum Rollen zu bringen; ein fester Abzug (--werkbank-abzug) gilt nur
   noch für eine Werkbank außerhalb von .af-maske. Die Höhe reicht .page bzw.
   der Projekt-Body durch (ProjectLayout.razor.css, Muster f30/f113). */
.af-maske {
    display: flex;
    flex-direction: column;
    height: 100%;
    min-height: 0;
}

.af-maske > .af-page-head,
.af-maske > .af-hinweisleiste {
    flex: none;
}

/* 156 N20 (2026-10-07): min-height: 0 wie die Vorlage (variante-a-werkbank,
   .wb-split). Das 420-px-Minimum aus .af-werkbank hob die Werkbank in
   niedrigen Fenstern über .page hinaus — mit Hinweisleiste schon bei
   1280×577 um mehr als den unteren Seitenabstand (60 px), der Zählfuß der
   Liste lag dann unter der Fensterkante. Gerollt wird in .af-liste-scroll
   und .af-detail-körper, nie in .page. Einspaltig gilt das Minimum weiter. */
.af-maske > .af-werkbank {
    flex: 1 1 0;
    height: auto;
    min-height: 0;
}

@media (max-width: 1100px) {
    .af-maske {
        height: auto;
    }

    .af-maske > .af-werkbank {
        flex: none;
        min-height: 420px;
    }
}

/* ⑦ Formular im Detail (Vorlage basis.css:291-295): Pflicht-Stern,
   Validierung unter dem Feld, Ankreuzfeld. */
.af-form-row .af-pflicht {
    color: var(--red-text);
    margin-left: 2px;
}

.af-form-fehler {
    font-size: 12px;
    color: var(--red-text);
    margin-top: 5px;
    font-weight: 600;
}

.af-form-row label.af-check {
    display: flex;
    align-items: center;
    gap: 9px;
    margin-bottom: 0;
    font-size: 13px;
    font-weight: 500;
    color: var(--text);
    text-transform: none;
    letter-spacing: 0;
}

.af-form-row .af-check input {
    width: 16px;
    height: 16px;
    accent-color: var(--accent);
}

/* ⑤ Dokument-Ansicht „Gerendert | Quelltext“ (DokumentAnsicht; Vorlage
   basis.css:517, :589). */
.af-dok-leiste {
    display: flex;
    justify-content: flex-end;
    margin: 12px 0 10px;
}

.af-quelltext {
    font-family: var(--mono);
    font-size: 12px;
    line-height: 1.6;
    white-space: pre-wrap;
    overflow-wrap: anywhere;
    background: var(--bg-3);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    padding: 12px 14px;
    margin: 0;
    color: var(--text);
}

/* 149 Batch 12 (FR-015; contracts §1.1 „Genaueres aus dem Bau (Batch 12)“):
   die Leiste der Tabellen-Seiten ohne Detail (Container, Agenten,
   Organisationen, Anlage) — Suche links, Zählung daneben, weitere Bedienung
   (Fensterwahl, Auswahlfilter) rechts. Die Zählung ist der ListenFuß ohne
   Kartenrand: er steht über der Tabelle, nicht am Fuß einer Listenkarte. */
.af-tabellen-leiste {
    display: flex;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
}

.af-tabellen-leiste > .af-suche {
    flex: 0 1 320px;
    min-width: 13rem;
}

.af-tabellen-leiste > .af-lf {
    border-top: 0;
    padding: 0;
}

/* ===== Ende Werkbank-Familie (149) ===== */

/* 157 B3 (FR-010/FR-012): die Options-Zusatzinfos der 150er Optik
   (Impact-Ausklapp, Pflege-Felder) sind fachlich entfallen — die drei
   Spalten leben im Baustein OptionSpalten.razor.css. */


/* ===== 156 Nachtrag M1/M2 (2026-09-30): dichtes Markdown — EIN Baustein =====
   Fachperson wörtlich: Überschriften dezent (höchstens 1 px je Ebene mehr),
   Text kompakt, Listen ohne viel Abstand — „überall wo Markdown gerendert
   wird“. Gilt an jedem Behälter, der Markdown als Blöcke rendert (Chat-Blase
   und -Frage, MarkdownView, Anforderungs-Datei, Transkript-Verlauf). Global
   statt scoped: der Verlauf baut imperativ (kein b-Attribut), und EINE
   Quelle hält die Flächen gleich. Die Schriftgröße setzt die Fläche; die
   Überschriften rechnen relativ dazu (h1 +3, h2 +2, h3 +1, h4–h6 +0).
   white-space: normal — unter pre-wrap würden die Zeilenenden zwischen den
   Blöcken zu Leerzeilen; sichtbare Einzelumbrüche trägt der Renderer (<br>). */
.af-md {
    white-space: normal;
    overflow-wrap: anywhere;
    line-height: 1.55;
}

.af-md > :first-child {
    margin-top: 0;
}

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

.af-md :is(h1, h2, h3, h4, h5, h6) {
    margin: 6px 0 2px;
    font-size: 1em;
    font-weight: 600;
    line-height: 1.35;
}

.af-md h1 {
    font-size: calc(1em + 3px);
}

.af-md h2 {
    font-size: calc(1em + 2px);
}

.af-md h3 {
    font-size: calc(1em + 1px);
}

.af-md :is(p, ul, ol, pre, blockquote, table) {
    margin: 0 0 4px;
}

.af-md :is(ul, ol) {
    padding-left: 18px;
}

/* Derselbe Punkt überall — auch in Flächen, die selbst Listen sind
   (Chat-Beiträge sind li: der Browser zeigte sonst Kreise). */
.af-md ul {
    list-style-type: disc;
}

.af-md ul ul {
    list-style-type: circle;
}

.af-md li {
    margin: 0;
}

.af-md li > :is(p, ul, ol) {
    margin: 0;
}

.af-md code {
    font-family: var(--mono);
    font-size: 0.9em;
    background: var(--bg-4);
    border: 1px solid var(--border);
    border-radius: 3px;
    padding: 0 3px;
}

.af-md pre {
    font-family: var(--mono);
    font-size: 12px;
    line-height: 1.45;
    background: var(--bg-2);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    padding: 4px 8px;
    overflow-x: auto;
    white-space: pre;
    overflow-wrap: normal;
}

.af-md pre code {
    font-size: inherit;
    background: none;
    border: 0;
    padding: 0;
}

.af-md blockquote {
    padding: 0 8px;
    border-left: 3px solid var(--border-light);
    color: var(--text-2);
}

.af-md hr {
    border: 0;
    border-top: 1px solid var(--border);
    margin: 6px 0;
}

.af-md table {
    display: block;
    max-width: 100%;
    overflow-x: auto;
    border-collapse: collapse;
    font-size: 0.95em;
}

.af-md :is(th, td) {
    border: 1px solid var(--border);
    padding: 2px 6px;
    text-align: left;
    vertical-align: top;
}

/* 168 B6 (contracts/ui-verhalten.md §4): ein relativer Link auf ein Mockup
   (Anforderungs-Datei, Fragetext der Inbox) führt in die Galerie — im selben
   Fenster. Akzentfarbe mit gepunkteter Unterstreichung und einem kleinen
   Rahmen-Symbol davor: er sieht anders aus als ein Absprung nach außen. */
.af-md a.anf-link--mockup {
    color: var(--accent);
    text-decoration: underline dotted;
    text-decoration-thickness: 1px;
    text-underline-offset: 3px;
    border-radius: 4px;
    padding: 0 2px;
    margin: 0 -2px;
    transition: background-color .12s ease;
}

.af-md a.anf-link--mockup::before {
    content: "";
    display: inline-block;
    width: .78em;
    height: .62em;
    margin-right: .3em;
    border: 1.5px solid currentColor;
    border-top-width: 3px;
    border-radius: 2px;
    vertical-align: .02em;
    opacity: .8;
}

.af-md a.anf-link--mockup:hover,
.af-md a.anf-link--mockup:focus-visible {
    background: var(--tint-accent);
    text-decoration-style: solid;
}

/* 147 T036 (Nachtrag 2026-10-17): der YAML-Kopf eines Dokuments als Block
   „Kopfinformationen“ — eine ruhige Karteikarte über dem Text: leicht
   abgesetzte Fläche, feine Akzentkante links, kleine Versal-Überschrift.
   Schlüssel als gedämpfte Mono-Beschriftung in einer schmalen Spalte, Werte
   in Textfarbe; lange Werte brechen um. Unter 520 px stehen Schlüssel und
   Wert untereinander. Nur Tokens — hell und dunkel ohne eigenen Zweig. */
.af-md .af-md-kopf {
    container-type: inline-size;
    margin: 0 0 14px;
    padding: 8px 12px 10px;
    background: color-mix(in srgb, var(--bg-3) 55%, transparent);
    border: 1px solid var(--border);
    border-left: 3px solid color-mix(in srgb, var(--accent) 55%, var(--border));
    border-radius: var(--radius-sm);
    font-size: 0.95em;
    line-height: 1.45;
}

.af-md .af-md-kopf-titel {
    margin: 0 0 6px;
    font-size: 10.5px;
    font-weight: 600;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--text-3);
}

.af-md .af-md-kopf-liste {
    display: grid;
    grid-template-columns: minmax(6em, max-content) minmax(0, 1fr);
    column-gap: 16px;
    row-gap: 3px;
    align-items: baseline;
    margin: 0;
}

.af-md .af-md-kopf-liste > div {
    display: contents;
}

.af-md .af-md-kopf dt {
    max-width: 16em;
    font-family: var(--mono);
    font-size: 0.86em;
    line-height: 1.45;
    color: var(--text-2);
    overflow-wrap: anywhere;
}

.af-md .af-md-kopf dd {
    margin: 0;
    min-width: 0;
    color: var(--text);
    overflow-wrap: anywhere;
}

.af-md .af-md-kopf dd ul {
    margin: 0;
    padding-left: 16px;
}

.af-md .af-md-kopf dd li + li {
    margin-top: 2px;
}

.af-md .af-md-kopf dd li::marker {
    color: var(--text-3);
}

/* Was der Leser nicht versteht, bleibt die Zeile, wie sie dasteht. */
.af-md .af-md-kopf-text {
    margin: 4px 0;
    font-family: var(--mono);
    font-size: 0.86em;
    color: var(--text-2);
    white-space: pre-wrap;
}

.af-md .af-md-kopf > :last-child {
    margin-bottom: 0;
}

@container (max-width: 520px) {
    .af-md .af-md-kopf-liste {
        grid-template-columns: minmax(0, 1fr);
        row-gap: 0;
    }

    .af-md .af-md-kopf dt {
        max-width: none;
        line-height: 1.5;
    }

    .af-md .af-md-kopf dd + dt,
    .af-md .af-md-kopf-liste > div + div > dt {
        margin-top: 6px;
    }
}

/* ===== Ende dichtes Markdown ===== */

/* 156 Nachtrag M5 (Vertrag transkript-werkbank §10 M5): die Lauf-Suche
   markiert wie der Browser — CSS Custom Highlight API (transcript.js
   sucheMarkieren setzt die Highlights „tl-fund“ und „tl-fund-aktiv“).
   Global, weil ::highlight kein Element trägt, das Scoped-CSS erreicht. */
::highlight(tl-fund) {
    background-color: var(--such-fund);
}

::highlight(tl-fund-aktiv) {
    background-color: var(--such-fund-aktiv);
    color: var(--such-fund-aktiv-text);
}

/* 024 Nachtrag T019 (2026-10-14): der Board-Tooltip (js/tooltip.js) — ersetzt
   den nativen title dort, wo ein Element data-af-tooltip trägt. Global, weil
   die Blase einmal am Ende von <body> hängt und kein Scoped-CSS sie erreicht.
   Ruhige Werkbank-Marke: Fläche eine Stufe heller als die Karte, feine Kante,
   kleine Schrift, kein Pfeil. Über Menüs (150) und Dialogen (200), unter den
   Toasts (300). Der Zeiger geht durch sie hindurch. */
.af-tooltip {
    position: fixed;
    z-index: 260;
    max-width: min(320px, calc(100vw - 16px));
    padding: 5px 9px 6px;
    border: 1px solid var(--border-light);
    border-radius: var(--radius-sm);
    background: var(--bg-4);
    color: var(--text);
    box-shadow: var(--shadow);
    font: 400 12px/1.45 var(--font);
    letter-spacing: .01em;
    white-space: pre-line;
    overflow-wrap: anywhere;
    pointer-events: none;
}

.af-tooltip[hidden] {
    display: none;
}

@media (prefers-reduced-motion: no-preference) {
    .af-tooltip:not([hidden]) {
        animation: af-tooltip-ein .12s ease-out both;
    }

    .af-tooltip.af-tooltip-oben:not([hidden]) {
        animation-name: af-tooltip-ein-oben;
    }
}

@keyframes af-tooltip-ein {
    from { opacity: 0; transform: translateY(-2px); }
    to { opacity: 1; transform: translateY(0); }
}

@keyframes af-tooltip-ein-oben {
    from { opacity: 0; transform: translateY(2px); }
    to { opacity: 1; transform: translateY(0); }
}
