:root {
    color-scheme: dark;

    /* Geräteweise Anzeige-Skalierung: nur clientseitig, pro Browser/Gerät in
       localStorage gepflegt (Karte „Darstellung auf diesem Gerät“ unter
       /stammdaten/design). Der Bootstrap in base.html setzt die Werte vor dem
       ersten Rendern auf <html>, display-scale.js pflegt sie live. Defaults sind
       neutral (1) – ohne gespeicherte Werte ändert sich nichts. Weil die gesamte
       Oberfläche rem-basiert ist, skaliert die Wurzel-Schriftgröße (--ui-font-scale)
       den gesamten Text; --ui-edge-scale wirkt ausschließlich auf den Abstand des
       Inhalts zum Fensterrand (.app-main/.app-header), --ui-radius-scale auf die
       Ecken-Rundung (Skala 0 = eckig). */
    --ui-font-scale: 1;
    --ui-edge-scale: 1;
    --ui-radius-scale: 1;
    --ui-card-gap-scale: 1;
    --ui-text-inset-scale: 1;
    /* Typografie-Rollen (geräteweise regelbar, Standard = keine Änderung):
       Größe je Rolle als Skala (Standard 1), Schwere je Tier als Wert
       (Standard = bisheriger Wert). Jede font-size ist mit ihrer Rollen-Skala
       multipliziert, jede font-weight durch ihr Tier ersetzt. */
    --ui-fs-title: 1;
    --ui-fs-heading: 1;
    --ui-fs-body: 1;
    --ui-fs-secondary: 1;
    --ui-fs-small: 1;
    --ui-fw-strong: 700;
    --ui-fw-semibold: 600;
    --ui-fw-medium: 500;
    --ui-fw-normal: 400;
    font-size: calc(100% * var(--ui-font-scale));

    /* Farben: dunkles Grundschema, auf ausdrücklichen Wunsch etwas heller/moderner
       und kontrastreicher abgestuft als die reine Fable-Screenshot-Vorlage (größerer
       Abstand zwischen Seite/Karte/Rahmen für klarere Ebenen), weiterhin bewusst
       kein helles/grelles Theme. */
    --color-bg: #121316;
    --color-surface: #1c1e23;
    --color-surface-raised: #262930;
    --color-border: #34373f;
    --color-border-strong: #494d57;

    --color-text: #f3f4f6;
    --color-text-muted: #a7abb4;
    --color-text-faint: #767a84;

    --color-accent: #6ea8fe;
    --color-accent-strong: #4c8dff;
    --color-accent-contrast: #06121f;

    --color-success-bg: #163524;
    --color-success-text: #7ee2a8;
    /* Getönte Flächen für Warnung (heute fällig) und Akzent (diese Woche),
       analog zu success/danger; genutzt von den KPI-Karten (.kpi-card-*). */
    --color-warning-bg: #3a2b12;
    --color-warning-text: #ffc46f;
    --color-accent-bg: #142639;
    --color-danger-bg: #34191b;
    --color-danger-border: #7a3b3b;
    --color-danger-text: #ff8383;
    /* Kräftiger, durchgehender Hintergrund für gefährliche Icon-Buttons
       (Löschen/Entfernen), siehe .icon-button-danger. */
    --color-danger-solid: #b3392f;
    --color-danger-solid-hover: #95271f;

    /* Abstände (feste Basiswerte; die geräteweise Regelung wirkt nur auf den
       Fensterrand, siehe --ui-edge-scale an .app-main/.app-header) */
    --space-1: 0.25rem;
    --space-2: 0.5rem;
    --space-3: 0.75rem;
    --space-4: 1rem;
    --space-5: 1.5rem;
    --space-6: 2.25rem;

    /* Abstand zwischen Karten: projektweit EIN Token (Basis 0,75rem),
       über den Regler „Kartenabstand“ der Darstellung skalierbar
       (--ui-card-gap-scale, 0 = Karten bündig). */
    --card-gap: calc(0.75rem * var(--ui-card-gap-scale));

    /* Abstand Karte → Überschrift des NÄCHSTEN Blocks: doppelter Karten-
       abstand, damit die Überschrift optisch zu ihrem Block darunter
       gruppiert (skaliert mit demselben Regler; 0 = bündig). */
    --card-gap-section: calc(var(--card-gap) * 2);

    /* Seitlicher Einzug freistehender Texte gegenüber den Kartenrändern
       (Basis 0,75rem = Karten-Innenabstand), über den Regler „Text-Einzug“
       der Darstellung skalierbar (0 = bündig mit den Karten). */
    --text-inset: calc(0.75rem * var(--ui-text-inset-scale));

    /* Radien & Schatten (Radius × --ui-radius-scale; Skala 0 = eckige Ecken) */
    --radius-sm: calc(0.375rem * var(--ui-radius-scale));
    --radius-md: calc(0.625rem * var(--ui-radius-scale));
    --radius-lg: calc(0.875rem * var(--ui-radius-scale));
    --shadow-card: 0 1px 2px rgba(0, 0, 0, 0.4), 0 4px 12px rgba(0, 0, 0, 0.28);

    /* Einheitliche optische Höhe aller einzeiligen Eingabe-Controls
       (Textboxen, Selects, Datumsfelder, Combobox-Suchfelder, Filter):
       Padding-basierte Höhen fallen je Control-Typ unterschiedlich aus
       (Datum ≠ Select ≠ Text) – eine feste Höhe zentriert die Inhalte und
       lässt alle Felder gleich hoch wirken (docs/13). Bewusste Ausnahmen:
       Textareas (mehrzeilig), Badge-Selects (.colored-select), kompakte
       Kartenkopf-Selects (1.9rem, Icon-Button-Höhe) und die flachen Felder
       des Eigenschaften-Rastereditors (Fakten-Optik). */
    --control-height: 2.75rem;

    /* Typografie */
    --font-sans: -apple-system, "Segoe UI", system-ui, sans-serif;
}

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

body {
    margin: 0;
    padding: 0;
    background-color: var(--color-bg);
    color: var(--color-text);
    font-family: var(--font-sans);
    /* Geerbter Fließtext folgt der Rolle „Fließtext“ (PO 2026-07-20). Ohne
       diese Basis blieb jeder Text OHNE eigene font-size (Absätze,
       .section-note, Hinweistexte) auf der Browser-Vorgabe von 16 px stehen und
       ignorierte die Skalierung – am deutlichsten auf textlastigen Seiten wie
       den Auflösungsprofilen. Bei Skala 1 ergibt sich unverändert 1rem. */
    font-size: calc(1rem * var(--ui-fs-body));
    line-height: 1.5;
    -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4 {
    font-weight: var(--ui-fw-semibold);
    letter-spacing: -0.01em;
    color: var(--color-text);
}

h2 {
    font-size: calc(1.5rem * var(--ui-fs-title));
    /* Seitentitel → nachfolgender Inhalt (oft Karten): Kartenabstand. */
    margin: 0 0 var(--card-gap);
}

h3 {
    font-size: calc(1.05rem * var(--ui-fs-heading));
    margin: 0;
}

.heading-select {
    font: inherit;
    font-weight: var(--ui-fw-strong);
    color: var(--color-text);
    background-color: var(--color-surface);
    border: 1px solid var(--color-border-strong);
    border-radius: var(--radius-sm);
    padding: 0.1rem 0.5rem;
}

.heading-select:focus {
    outline: none;
    border-color: var(--color-accent);
    box-shadow: 0 0 0 3px rgba(110, 168, 254, 0.2);
}

a {
    color: var(--color-accent);
}

:focus-visible {
    outline: 2px solid var(--color-accent);
    outline-offset: 2px;
    border-radius: var(--radius-sm);
}

/* Nur für Screenreader: entfernt visuell doppelte Hinweise (z. B. Suchfeld-Label
neben identischem Placeholder), behält die zugängliche Beschriftung aber bei. */
.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;
}

.app-header {
    display: flex;
    align-items: flex-end;
    gap: var(--space-3);
    padding: calc(var(--space-4) * var(--ui-edge-scale)) calc(var(--space-6) * var(--ui-edge-scale)) 0;
    border-bottom: 1px solid var(--color-border);
    background-color: var(--color-surface);
}

.app-header .app-nav {
    flex: 1;
    min-width: 0;
}

/* Neu-laden-Button rechts in der Kopfzeile, auf Höhe der Haupt-Reiter. Das
   ⟳-Symbol größer als das Grund-Icon (PO 2026-07-22): Es ist der am häufigsten
   genutzte Kopf-Knopf und darf sichtbarer sein. Nur die Glyphe wächst, die
   36×36-Fläche bleibt gleich, damit alle drei Knöpfe gleich groß sind. */
.app-refresh-button {
    align-self: center;
}

/* Meldeknopf rechts in der Kopfzeile. Als <details> gebaut, damit das Feld ohne
eigenes JavaScript auf- und zuklappt; das Feld selbst schwebt über der Seite,
damit es die Kopfzeilenhöhe nicht verändert. */
.todo-add {
    align-self: center;
    position: relative;
}

/* Abmelde-Knopf in der Kopfzeile (PO 2026-07-21): Die Kopfzeile richtet ihre
   Kinder unten aus (align-items: flex-end, damit die Reiter an der Unterkante
   andocken). Neu-laden- und Meldeknopf heben sich mit align-self: center
   heraus; der Abmelde-Knopf steckt aber im umschließenden <form>, das diese
   Zentrierung nicht erbte und dadurch 1–2 px tiefer saß. Das Formular bekommt
   deshalb dieselbe Zentrierung und legt sich als schmale Flex-Box eng um seinen
   Knopf, sodass alle drei Symbol-Knöpfe auf gleicher Höhe und gleich groß
   stehen. */
.app-logout {
    align-self: center;
    display: flex;
}

.todo-add > summary {
    list-style: none;
    cursor: pointer;
}

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

.todo-add[open] > summary {
    border-color: var(--color-accent);
    color: var(--color-accent);
}

.todo-add-panel {
    position: absolute;
    top: calc(100% + var(--space-1));
    right: 0;
    z-index: 30;
    width: min(24rem, calc(100vw - 2 * var(--space-3)));
    padding: var(--space-3);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    background-color: var(--color-surface);
    box-shadow: 0 0.5rem 1.5rem rgba(0, 0, 0, 0.18);
}

.todo-add-panel textarea {
    width: 100%;
}

/* Verlauf der laufenden Arbeit, aufklappbar am Ticket (PO 2026-07-21).
   Der Kasten bekommt eine feste Höhe und scrollt: Ein Lauf erzeugt hunderte
   Zeilen, die sonst die ganze Tabelle auseinanderzögen. */
.ticket-verlauf {
    margin-top: var(--space-2);
}

/* Vertikal kompakt gehalten (PO 2026-07-22): Der Fortschritt sitzt eng unter
   dem Tickettext und soll die Zeile so wenig wie möglich auseinanderziehen –
   knapper Abstand, kleine Schrift. */
.ticket-verlauf {
    margin-top: var(--space-1);
}

.ticket-verlauf > summary {
    cursor: pointer;
    color: var(--color-text-muted);
    font-size: calc(0.75rem * var(--ui-fs-small));
    line-height: 1.2;
}

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

.ticket-verlauf-text {
    max-height: 12rem;
    margin: var(--space-1) 0 0;
    padding: var(--space-1) var(--space-2);
    overflow: auto;
    border-radius: var(--radius-sm);
    background-color: var(--color-surface-raised);
    color: var(--color-text-muted);
    font-size: calc(0.72rem * var(--ui-fs-small));
    /* Enge Zeilen: Der Fortschritt sind knappe Stichworte, keine Fließtexte. */
    line-height: 1.35;
    /* Die Zeilen sind bereits gekürzt; lange Pfade dürfen umbrechen, statt den
       Kasten in die Breite zu ziehen. */
    white-space: pre-wrap;
    overflow-wrap: anywhere;
}

/* Tickettabellen vertikal kompakt (PO 2026-07-22): NUR die beiden
   Ticketlisten, nicht die Tabellen im übrigen Projekt. Zwei Ursachen für den
   Leerraum in einer Zeile:
   1. Die Zellen tragen projektweit das großzügige Grundpolster (--space-3);
      hier genügt --space-2.
   2. Der Tickettext steht als data-multiline-Zelle oben (vertical-align: top),
      während die 36-px-Aktionsknöpfe die Zeilenhöhe vorgeben – bei einzeiligem
      Text blieb darunter eine leere Fläche. Mittig ausgerichtet sitzt der Text
      auf Knopfhöhe, der Leerraum verschwindet. Der aufgeklappte Fortschritt
      fließt weiterhin darunter. */
#todo-open-table th,
#todo-open-table td,
#todo-done-table th,
#todo-done-table td {
    padding-top: var(--space-2);
    padding-bottom: var(--space-2);
}

#todo-open-table td[data-multiline],
#todo-done-table td[data-multiline] {
    vertical-align: middle;
}

/* Abschnitt „Erledigt“ der Ticketliste: ein- und ausklappbar (PO
   2026-07-21). Der Kartenkopf bleibt optisch der eines Abschnitts, bekommt
   aber ein Dreieck und einen Zeiger, damit er als anklickbar zu erkennen ist. */
.todo-erledigt > summary {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    cursor: pointer;
    list-style: none;
}

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

.todo-erledigt > summary::before {
    content: "▸";
    color: var(--color-text-muted);
    transition: transform 0.15s ease-in-out;
}

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

@media (prefers-reduced-motion: reduce) {
    .todo-erledigt > summary::before {
        transition: none;
    }
}

/* Ticket, an dem Claude Code gerade arbeitet (PO 2026-07-21): Die Zeile
   blinkt langsam. Bewusst langsam und über die Hintergrundfarbe statt über die
   Deckkraft – ein schnelles Blinken oder verschwindender Text machte die Zeile
   unlesbar, während man sie liest.

   `prefers-reduced-motion` schaltet die Bewegung ab; damit die Zeile trotzdem
   erkennbar bleibt, behält sie dann dauerhaft die hervorgehobene Farbe. */
/* Nicht mehr die ganze Zeile blinkt, sondern das Fortschritt-Feld (PO
   2026-07-22, Ticket 15): Es lädt zum Ausklappen ein, und prominenter als das
   frühere dezente Hintergrund-Pulsieren. Zugleich löst das Ticket 16 – das
   frühere Blinken saß auf den Tabellenzellen, die beim Ändern der Spaltenbreite
   umgebaut werden (data-table.js wickelt überlaufenden Zellinhalt ein), wodurch
   die Animation abbrach. Das Fortschritt-Feld ist davon unberührt.

   Prominent über Akzentfarbe UND einem leichten Puls der Fläche; bewusst nicht
   über die Deckkraft, damit die Beschriftung lesbar bleibt. */
@keyframes ticket-fortschritt-blink {
    0%, 100% {
        background-color: var(--color-surface-raised);
        color: var(--color-text-muted);
        box-shadow: 0 0 0 1px var(--color-border-strong);
    }
    50% {
        background-color: var(--color-accent);
        color: var(--color-accent-contrast);
        box-shadow: 0 0 0 1px var(--color-accent);
    }
}

/* Das Feld als klar abgegrenzte, klickbare Fläche – damit das Pulsieren als
   „hier ausklappen“ lesbar ist, nicht als diffuses Flackern. */
.list-table tbody tr[data-in-arbeit] .ticket-verlauf > summary {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    padding: 0.1rem 0.5rem;
    border-radius: 999px;
    font-weight: var(--ui-fw-semibold);
    /* Dauer bewusst ein ganzzahliger Teiler des Nachlade-Intervalls der Liste
       (5 s / 4 = 1,25 s; hx-trigger every 5s in todo/partials/list.html): Das
       Selbstnachladen ERSETZT das Feld im DOM, wodurch die Animation neu
       startet. Nur wenn die Dauer die 5 s glatt teilt, steht die alte Animation
       beim Austausch genau auf Phase 0 – der Neustart landet nahtlos, statt
       mitten im Zyklus zurückzuspringen (das frühere Flackern, Ticket 20).
       Wird das Intervall geändert, muss diese Dauer mitgeführt werden. */
    animation: ticket-fortschritt-blink 1.25s ease-in-out infinite;
}

@media (prefers-reduced-motion: reduce) {
    .list-table tbody tr[data-in-arbeit] .ticket-verlauf > summary {
        animation: none;
        background-color: var(--color-accent);
        color: var(--color-accent-contrast);
    }
}

/* Zurückhaltend gehalten (PO 2026-07-21): Der Weg zur Liste ist der Nebenweg,
   das Melden die Hauptsache – ein Akzent-Knopf zog hier zu viel Aufmerksamkeit. */
.todo-add-list-link {
    color: var(--color-text-muted);
    font-size: calc(0.85rem * var(--ui-fs-secondary));
    text-decoration: none;
}

.todo-add-list-link:hover {
    color: var(--color-text);
    text-decoration: underline;
}

.todo-add-actions {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-2);
    margin-top: var(--space-2);
}

/* Kurze, selbst verschwindende Bestätigung nach dem Hintergrund-Absenden eines
   Tickets (Ticket 65): Die Seite wechselt bewusst nicht, darum signalisiert ein
   dezenter Einblender oben rechts, dass das Ticket angekommen ist. */
.todo-toast {
    position: fixed;
    top: calc(var(--space-4) + 3rem);
    right: var(--space-4);
    z-index: 60;
    padding: var(--space-2) var(--space-3);
    border: 1px solid var(--color-border-strong);
    border-radius: var(--radius-sm);
    background-color: var(--color-surface-raised);
    color: var(--color-text);
    box-shadow: 0 6px 20px rgba(0, 0, 0, 0.3);
    font-size: calc(0.9rem * var(--ui-fs-secondary));
    opacity: 1;
    transition: opacity 0.3s ease, transform 0.3s ease;
}

.todo-toast-leaving {
    opacity: 0;
    transform: translateY(-6px);
}

/* Dieselbe Designsprache wie die Objektklassen-Reiter (.object-class-tab*): flach an
der Kopfzeilen-Unterkante andockende Reiter statt einfacher Textlinks, damit sich
Hauptnavigation und Objektklassen-Reiter wie dieselbe Komponentenfamilie anfühlen. */
.app-nav {
    display: flex;
    align-items: flex-end;
    flex-wrap: nowrap;
    overflow-x: auto;
    overflow-y: hidden;
    min-height: 2.45rem;
    gap: var(--space-1);
}

/* Generische Drag-Affordanz/Einfüge-Trennstrich für jede per data-reorderable-list
aktivierte Reitergruppe (Hauptnavigation, Objektklassen-, Objekttyp-Reiter, künftige
Gruppen). Der Trennstrich nutzt Pseudo-Elemente statt border-left/-right, damit er
unabhängig davon sichtbar bleibt, ob eine Komponente (z. B. .object-class-tab) selbst
ein `border`-Shorthand setzt; die zweifache Attributselektor-Spezifität bei Cursor/
Dragging stellt sicher, dass sie unabhängig von der Stylesheet-Reihenfolge über
komponentenspezifische Einzelklassen-Regeln (z. B. `cursor: pointer`) gewinnt. */
[data-reorder-item] {
    position: relative;
}

[data-reorder-item][data-reorder-ready="true"] {
    cursor: grab;
}

[data-reorder-item].reorder-item-dragging {
    cursor: grabbing;
}

.reorder-item-dragging {
    opacity: 0.5;
}

[data-reorder-item]::before,
[data-reorder-item]::after {
    content: "";
    position: absolute;
    top: 0;
    bottom: 0;
    width: 2px;
    background-color: var(--color-accent);
    opacity: 0;
    pointer-events: none;
}

[data-reorder-item]::before {
    left: 0;
}

[data-reorder-item]::after {
    right: 0;
}

.reorder-item-drop-before::before {
    opacity: 1;
}

.reorder-item-drop-after::after {
    opacity: 1;
}

/* Vertikale Listen (data-reorder-axis="y", z. B. die Objektakte-Karten):
Drop-Indikatoren liegen als waagerechte Linien über bzw. unter dem Element
statt links/rechts daneben. */
[data-reorder-axis="y"] > [data-reorder-item]::before,
[data-reorder-axis="y"] > [data-reorder-item]::after {
    left: 0;
    right: 0;
    width: auto;
    height: 2px;
}

[data-reorder-axis="y"] > [data-reorder-item]::before {
    top: 0;
    bottom: auto;
}

[data-reorder-axis="y"] > [data-reorder-item]::after {
    top: auto;
    bottom: 0;
}

/* Tabellenzeilen als data-reorder-item (z. B. die Ereignisse eines Vorgangs):
Pseudoelemente auf <tr> werden von der Tabellen-Layoutfixierung als anonyme
zusätzliche Zelle eingefügt und verschieben alle Spalten – deshalb hier keine
::before/::after. Der Drop-Indikator liegt stattdessen als durchgehende Linie
(Innenschatten) auf den Zellen der Zielzeile: oberhalb bei drop-before,
unterhalb bei drop-after – exakt an der künftigen Einfügeposition. */
tr[data-reorder-item]::before,
tr[data-reorder-item]::after {
    content: none;
}

tr[data-reorder-item].reorder-item-drop-before > th,
tr[data-reorder-item].reorder-item-drop-before > td {
    box-shadow: inset 0 2px 0 var(--color-accent);
}

tr[data-reorder-item].reorder-item-drop-after > th,
tr[data-reorder-item].reorder-item-drop-after > td {
    box-shadow: inset 0 -2px 0 var(--color-accent);
}

/* Bei Listen mit dediziertem Drag-Handle (data-reorder-handle) zeigt nur der
Handle den Greif-Cursor, nicht das gesamte Element; reorderable-list.js markiert
den Handle beim Initialisieren mit data-reorder-handle-ready. */
[data-reorder-handle] > [data-reorder-item][data-reorder-ready="true"] {
    cursor: auto;
}

[data-reorder-handle-ready] {
    cursor: grab;
    /* Touch/Pen: Auf dem Griff zieht die Geste (Pointer-Pfad in
       reorderable-list.js) statt zu scrollen; ohne touch-action:none würde iOS
       die Berührung als Scrollen werten und keine pointermove liefern. Tippen auf
       Buttons/Selects im Griff bleibt möglich. */
    touch-action: none;
}

.page-links a {
    color: var(--color-text-muted);
    text-decoration: none;
    font-size: calc(0.9rem * var(--ui-fs-secondary));
    font-weight: var(--ui-fw-medium);
    transition: color 0.15s ease;
}

.page-links a:hover {
    color: var(--color-accent);
    text-decoration: none;
}

.app-nav a {
    display: inline-flex;
    align-items: center;
    flex-shrink: 0;
    padding: var(--space-2) var(--space-4);
    color: var(--color-text-muted);
    text-decoration: none;
    font-weight: var(--ui-fw-medium);
    font-size: calc(0.9rem * var(--ui-fs-secondary));
    white-space: nowrap;
    border-bottom: 2px solid transparent;
    margin-bottom: -1px;
    transition: color 0.15s ease, border-color 0.15s ease, background-color 0.15s ease;
}

.app-nav a:hover {
    color: var(--color-text);
    text-decoration: none;
}

.app-nav a.app-nav-active {
    color: var(--color-text);
    background-color: var(--color-surface-raised);
    border-bottom-color: var(--color-accent);
    border-top-left-radius: var(--radius-sm);
    border-top-right-radius: var(--radius-sm);
}

/* Rücksprung-/Einstiegslinks („Zu den …“, „Zurück zu …“) werden global nicht
   mehr angezeigt (PO-Entscheidung; deckt sich mit dem Navigations-Grundsatz in
   docs/13, „redundante globale Rücksprünge auf jeder Fachseite werden
   vermieden“). `.page-links` ist projektweit ausschließlich für diese Links
   reserviert, deshalb genügt eine zentrale Ausblendung – auch für künftige
   Seiten. Das Markup bleibt in den Templates bestehen, ohne Wirkung. */
.page-links {
    display: none;
}

/* Einheitlicher Objektpfad: als Seiten-Breadcrumb oberhalb einer Überschrift
(letzter Eintrag unverlinkt, aktuelle Seite) und als kompakte, vollständig
klickbare Pfad-Darstellung innerhalb von Tabellenzellen (link_last). */
.breadcrumbs {
    display: inline-flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.3rem;
    font-size: calc(0.82rem * var(--ui-fs-secondary));
    color: var(--color-text-muted);
}

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

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

/* Spalte „Offene Störung“ der Objekttabellen: dezenter Warn-Ton, damit eine
   offene Störung auf einen Blick auffällt (ADR-040). */
.open-fault-link {
    color: var(--color-danger-text);
}

/* Mehrere offene Störungen je Objekt (Rollup): untereinander gestapelt,
   damit lange Titel lesbar bleiben. */
.open-fault-list {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
}

/* Karte „Verknüpfte Objekte“ (ADR-045): Abschnitte Übergeordnet /
   Unterobjekte / Beziehungen unter einer Kartenüberschrift. */
.linked-objects-subheading {
    margin: var(--space-4) 0 var(--space-2);
    color: var(--color-text-muted);
    font-size: calc(0.8rem * var(--ui-fs-small));
    font-weight: var(--ui-fw-semibold);
    text-transform: uppercase;
    letter-spacing: 0.04em;
}

.linked-objects-subheading:first-of-type {
    margin-top: 0;
}

/* Beziehungen-Karte der Objektakte (ADR-044): je Beziehung eine Zeile
   „Typ-Bezeichnung · Objekt · Entfernen“; darunter die Schnellanlage. */
.relation-list {
    display: flex;
    flex-direction: column;
}

.relation-row {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-1) 0;
}

.relation-row + .relation-row {
    border-top: 1px solid var(--color-border);
}

.relation-type-label {
    color: var(--color-text-muted);
    font-size: calc(0.9rem * var(--ui-fs-secondary));
}

.relation-object-link {
    flex: 1;
    min-width: 0;
}

.relation-create-form {
    display: flex;
    align-items: flex-start;
    gap: var(--space-2);
    margin-top: var(--space-3);
}

.relation-create-form .combobox {
    flex: 1;
    min-width: 0;
}

/* Breadcrumb als Aktentitel (Objektakte + Vorgangsakte-Präfix, PO
   2026-07-08): erbt die Titelgröße; Vorfahren/Objekt-Segmente gedämpft, der
   eigentliche Titel (Objektname bzw. „ · Vorgangstitel“) in Titel-Optik. */
.akte-hero h2 .breadcrumbs {
    font-size: inherit;
    font-weight: inherit;
    color: var(--color-text-muted);
}

/* Im einzeiligen, herunterskalierenden Vorgangstitel bleibt die Kette in
   einer Zeile (fit-single-line.js skaliert, statt umzubrechen). */
.object-name-heading .breadcrumbs {
    flex-wrap: nowrap;
}

.breadcrumb-current {
    color: var(--color-text);
    font-weight: var(--ui-fw-semibold);
}

.breadcrumb-separator {
    color: var(--color-text-faint);
}

.page-breadcrumbs {
    display: block;
    margin-bottom: var(--space-3);
}

.app-main {
    padding: calc(var(--space-6) * var(--ui-edge-scale));
    max-width: 160rem;
    margin: 0 auto;
}

/* Hinweis, wenn eine htmx-Anfrage am Netz oder am Server gescheitert ist
   (connection-guard.js). Ohne ihn bliebe ein gescheiterter Klick vollkommen
   stumm. Bewusst unten mittig, nicht blockierend, blendet sich selbst aus. */
.connection-hint {
    position: fixed;
    left: 50%;
    bottom: 1.25rem;
    transform: translateX(-50%);
    z-index: 99998;
    display: flex;
    align-items: center;
    gap: var(--space-2);
    max-width: min(38rem, calc(100vw - 2rem));
    padding: 0.7rem 1rem;
    border: 1px solid var(--color-danger-border);
    border-radius: var(--radius-lg);
    background: var(--color-danger-bg);
    color: var(--color-danger-text);
    box-shadow: var(--shadow-card);
    font-size: calc(0.9rem * var(--ui-fs-secondary));
}

.connection-hint[hidden] {
    display: none;
}

/* Schalter „Scrollleisten“ der Darstellung (ui-scale:scrollbar = 0, Klasse
   aus Bootstrap/display-scale.js): blendet NUR die vertikalen Scrollleisten
   aus (width: 0); horizontale bleiben als schlanke, thematisierte Leiste
   erhalten (das ::-webkit-scrollbar-Styling ersetzt die native Darstellung,
   daher bekommt die horizontale Leiste hier ein eigenes Aussehen).
   Gescrollt wird weiterhin normal per Rad, Trackpad oder Touch. */
html.ui-scrollbar-hidden::-webkit-scrollbar,
html.ui-scrollbar-hidden *::-webkit-scrollbar {
    width: 0;
    height: 0.5rem;
    background: transparent;
}

html.ui-scrollbar-hidden::-webkit-scrollbar-thumb,
html.ui-scrollbar-hidden *::-webkit-scrollbar-thumb {
    background: var(--color-border-strong);
    border-radius: 0.25rem;
}

html.ui-scrollbar-hidden::-webkit-scrollbar-track,
html.ui-scrollbar-hidden *::-webkit-scrollbar-track {
    background: transparent;
}

/* Firefox kennt ::-webkit-scrollbar nicht und kann Scrollleisten nur je
   Element ganz aus-/einblenden (scrollbar-width, keine Achsen-Steuerung):
   Dort werden alle Leisten ausgeblendet, nur horizontale Scroller
   (Tabellen-Wrapper) behalten eine schmale Leiste. WebKit-Browser (Safari)
   überspringt diesen Block – dort gilt die Nur-vertikal-Regel oben. */
@supports not selector(::-webkit-scrollbar) {
    html.ui-scrollbar-hidden,
    html.ui-scrollbar-hidden * {
        scrollbar-width: none;
    }

    html.ui-scrollbar-hidden .list-table-wrapper {
        scrollbar-width: thin;
    }
}

.section-note {
    color: var(--color-text-muted);
    font-style: italic;
    margin: 0 0 var(--card-gap);
}

/* Freistehende Texte zwischen/über den Karten (Seitentitel, Rücksprung-
   Links, Hinweise, Gruppen-/Blockköpfe) rücken um --text-inset ein: Sie
   halten damit etwas mehr Abstand zum Rand als die Kartenränder (Regler
   „Text-Einzug“, 100 % = Karten-Innenabstand). Bewusst über
   Direktkind-Selektoren, damit dieselben Klassen INNERHALB von Karten
   (dort liefert das Kartenpolster den Abstand) nicht doppelt einrücken. */
.app-main > h2,
.object-akte-page > h2,
.app-main > .page-links,
.object-akte-page > .page-links,
.app-main > .section-note,
.object-akte-page > .section-note,
.project-history-heading {
    padding-inline: var(--text-inset);
}

.project-history {
    /* Blocküberschrift folgt auf die Karten darüber → Sektionsabstand. */
    margin-top: var(--card-gap-section);
}

.project-history-heading {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: var(--space-4);
    margin-bottom: var(--card-gap);
}

.project-history-heading p {
    margin: var(--space-1) 0 0;
    color: var(--color-text-muted);
    font-size: calc(0.9rem * var(--ui-fs-secondary));
}

.project-history-source {
    color: var(--color-text-faint);
    font-size: calc(0.78rem * var(--ui-fs-small));
    white-space: nowrap;
}

.project-history-grid {
    display: grid;
    gap: var(--card-gap);
}

.project-history-card {
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);
    background-color: var(--color-surface);
    box-shadow: var(--shadow-card);
}

.project-history-card-current {
    border-color: var(--color-accent-strong);
    box-shadow: 0 0 0 1px rgba(110, 168, 254, 0.15), var(--shadow-card);
}

.project-history-card summary {
    padding: var(--space-4) var(--space-5);
    cursor: pointer;
    list-style: none;
}

.project-history-card summary::-webkit-details-marker {
    display: none;
}

.project-history-title,
.project-history-title > span:first-child {
    display: flex;
    align-items: center;
    gap: var(--space-2);
}

.project-history-title {
    justify-content: space-between;
}

.project-history-title strong {
    color: var(--color-text);
}

.project-history-title > span:first-child > span {
    color: var(--color-text-muted);
}

.project-current-badge {
    padding: 0.15rem 0.55rem;
    border-radius: 999px;
    background-color: rgba(110, 168, 254, 0.14);
    color: var(--color-accent);
    font-size: calc(0.72rem * var(--ui-fs-small));
    font-weight: var(--ui-fw-semibold);
    white-space: nowrap;
}

.project-progress-row {
    display: flex;
    justify-content: space-between;
    gap: var(--space-3);
    margin-top: var(--space-3);
    color: var(--color-text-muted);
    font-size: calc(0.82rem * var(--ui-fs-secondary));
}

.project-progress-row strong {
    color: var(--color-text);
}

.project-progress {
    height: 0.4rem;
    margin-top: var(--space-2);
    overflow: hidden;
    border-radius: 999px;
    background-color: var(--color-surface-raised);
}

.project-progress span {
    display: block;
    height: 100%;
    border-radius: inherit;
    background-color: var(--color-accent-strong);
}

.project-status-counts {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2) var(--space-4);
    margin-top: var(--space-3);
    color: var(--color-text-faint);
    font-size: calc(0.78rem * var(--ui-fs-small));
}

.project-status-counts .status-completed {
    color: var(--color-success-text);
}

.project-status-counts .status-blocked {
    color: var(--color-danger-text);
}

.project-task-list {
    border-top: 1px solid var(--color-border);
}

.project-task {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--space-4);
    padding: var(--space-3) var(--space-5);
    border-bottom: 1px solid var(--color-border);
    font-size: calc(0.82rem * var(--ui-fs-secondary));
}

.project-task:last-child {
    border-bottom: 0;
}

.project-task > div:first-child {
    display: flex;
    gap: var(--space-2);
}

.project-task > div:first-child span {
    color: var(--color-text-muted);
}

.project-task-meta {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    flex-wrap: wrap;
    gap: var(--space-2);
    color: var(--color-text-faint);
    text-align: right;
}

.project-task-status {
    padding: 0.1rem 0.45rem;
    border: 1px solid var(--color-border-strong);
    border-radius: 999px;
    font-weight: var(--ui-fw-semibold);
    white-space: nowrap;
}

.project-task-status.status-erledigt {
    color: var(--color-success-text);
}

.project-task-status.status-blockiert {
    color: var(--color-danger-text);
}

.project-task-status.status-in-arbeit {
    color: var(--color-accent);
}

@media (max-width: 40rem) {
    .project-history-heading {
        align-items: flex-start;
        flex-direction: column;
        gap: var(--space-2);
    }

    .project-history-title,
    .project-history-title > span:first-child,
    .project-task {
        align-items: flex-start;
        flex-direction: column;
    }

    .project-task-meta {
        justify-content: flex-start;
        text-align: left;
    }
}

.page-intro h2 {
    margin-top: var(--space-3);
    margin-bottom: var(--space-2);
}

.page-intro p {
    color: var(--color-text-muted);
    margin: 0;
    max-width: 42rem;
}

/* Thematische Gruppen der Einstellungs-Übersicht: Sektionsabstand zwischen
   den Gruppen-Karten. */
.settings-group {
    margin-bottom: var(--card-gap-section);
}

.settings-group:last-of-type {
    margin-bottom: 0;
}

/* Einstellungsbereich: Seitenleiste + Inhalt auf allen /stammdaten-Seiten
   (base.html). Die Leiste erlaubt den direkten Wechsel zwischen den
   Bereichen ohne Rücksprung zur Übersicht. */
.settings-layout {
    display: flex;
    align-items: flex-start;
    gap: var(--card-gap-section);
}

.settings-content {
    flex: 1;
    min-width: 0;
}

.settings-sidebar {
    flex: 0 0 auto;
    width: 13.5rem;
    position: sticky;
    top: var(--space-4);
    display: flex;
    flex-direction: column;
    gap: var(--space-4);
    padding: var(--space-3);
    background-color: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-card);
}

.settings-sidebar-group {
    display: flex;
    flex-direction: column;
}

.settings-sidebar-group-title {
    padding: 0 var(--space-2) var(--space-1);
    color: var(--color-text-faint);
    font-size: calc(0.72rem * var(--ui-fs-small));
    font-weight: var(--ui-fw-semibold);
    text-transform: uppercase;
    letter-spacing: 0.04em;
}

.settings-sidebar-link {
    display: block;
    padding: 0.35rem var(--space-2);
    border-radius: var(--radius-sm);
    color: var(--color-text-muted);
    font-size: calc(0.9rem * var(--ui-fs-secondary));
    text-decoration: none;
}

.settings-sidebar-link:hover,
.settings-sidebar-link:focus-visible {
    color: var(--color-text);
    background-color: var(--color-surface-muted);
}

.settings-sidebar-active {
    color: var(--color-accent);
    background-color: var(--color-surface-muted);
    font-weight: var(--ui-fw-semibold);
}

/* Schmale Bildschirme: Leiste wird zur horizontalen, umbrechenden
   Chip-Zeile oberhalb des Inhalts; Gruppentitel entfallen. */
@media (max-width: 48rem) {
    .settings-layout {
        flex-direction: column;
        /* In Spaltenrichtung steuert align-items die WAAGERECHTE Achse. Das
           `align-items: flex-start` der Grundregel (dort für die Zeilen-
           Anordnung gedacht) ließ die Kinder hier auf ihre Inhaltsbreite
           wachsen: Eine Tabelle mit `min-width: 46rem` schob damit die ganze
           Seite über den Bildschirmrand hinaus, statt in ihrem eigenen
           Wrapper (`.list-table-wrapper`, overflow-x: auto) zu scrollen.
           `stretch` bindet die Kinder wieder an die Containerbreite. */
        align-items: stretch;
        gap: var(--card-gap);
    }

    .settings-sidebar {
        position: static;
        width: 100%;
        flex-direction: row;
        flex-wrap: wrap;
        gap: var(--space-1);
    }

    .settings-sidebar-group {
        display: contents;
    }

    .settings-sidebar-group-title {
        display: none;
    }

    .settings-sidebar-link {
        border: 1px solid var(--color-border);
        border-radius: 999px;
        padding: 0.25rem 0.7rem;
        font-size: calc(0.82rem * var(--ui-fs-small));
    }

    .settings-sidebar-active {
        border-color: var(--color-accent);
    }
}

/* Kompakte Einstellungs-Übersicht: je Gruppe eine Karte mit einzeiligen
   Bereichszeilen (Titel · Kurzbeschreibung · Anzahl) statt großer Karten. */
.settings-index-list {
    display: flex;
    flex-direction: column;
}

.settings-index-row {
    display: flex;
    align-items: baseline;
    gap: var(--space-3);
    padding: var(--space-2) var(--space-3);
    border-radius: var(--radius-sm);
    color: inherit;
    text-decoration: none;
}

.settings-index-row + .settings-index-row {
    border-top: 1px solid var(--color-border);
}

a.settings-index-row:hover,
a.settings-index-row:focus-visible {
    background-color: var(--color-surface-muted);
}

.settings-index-row h3 {
    margin: 0;
    flex-shrink: 0;
    font-size: calc(0.95rem * var(--ui-fs-secondary));
}

.settings-index-description {
    flex: 1;
    min-width: 0;
    color: var(--color-text-muted);
    font-size: calc(0.85rem * var(--ui-fs-secondary));
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.settings-index-count {
    flex-shrink: 0;
    color: var(--color-text-muted);
    font-size: calc(0.85rem * var(--ui-fs-secondary));
}

.settings-index-count strong {
    color: var(--color-text);
}

/* Sehr schmale Bildschirme: Kurzbeschreibung ausblenden, Titel + Anzahl
   bleiben. */
@media (max-width: 40rem) {
    .settings-index-description {
        display: none;
    }
}

.status-badge {
    flex-shrink: 0;
    padding: 0.15rem 0.5rem;
    border: 1px solid var(--color-border-strong);
    border-radius: 999px;
    color: var(--color-text-faint);
    font-size: calc(0.72rem * var(--ui-fs-small));
    font-weight: var(--ui-fw-semibold);
}

.button-link {
    display: inline-block;
    padding: 0.5rem 0.9rem;
    border-radius: var(--radius-sm);
    background-color: var(--color-accent-strong);
    color: var(--color-accent-contrast);
    font-size: calc(0.85rem * var(--ui-fs-secondary));
    font-weight: var(--ui-fw-semibold);
    text-decoration: none;
}

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

.badge {
    margin-left: var(--space-2);
    padding: 0.15rem 0.55rem;
    border-radius: 999px;
    background-color: var(--color-surface-raised);
    border: 1px solid var(--color-border-strong);
    color: var(--color-text-muted);
    font-size: calc(0.75rem * var(--ui-fs-small));
    font-weight: var(--ui-fw-medium);
}

/* Farbige Darstellung von Vorgangstyp/-status/-priorität: ein einziger,
   projektweit wiederverwendbarer Badge (siehe app/templates/partials/macros.html,
   Makro colored_badge) statt separater Klassen je Fachbereich. Dezenter Badge
   mit der gepflegten Farbe als Rahmen/Text, Hintergrund bleibt bewusst nur ein
   transparenter Farbschimmer, damit der Text lesbar bleibt (siehe
   docs/13_design_system.md, Grundsatz „lesbar statt bunt“). */
.colored-badge {
    display: inline-flex;
    align-items: center;
    margin-left: var(--space-2);
    padding: 0.1rem 0.5rem;
    border-radius: 999px;
    border: 1px solid var(--badge-color, var(--color-border-strong));
    background-color: color-mix(in srgb, var(--badge-color, var(--color-border-strong)) 16%, transparent);
    color: var(--badge-color, var(--color-text-muted));
    font-size: calc(0.75rem * var(--ui-fs-small));
    font-weight: var(--ui-fw-medium);
    white-space: nowrap;
    text-decoration: none;
}

.inline-badge-button {
    font: inherit;
    margin-left: 0;
    cursor: text;
}

.inline-master-data-name,
.inline-master-data-description {
    width: 100%;
    min-width: 10rem;
}

.inline-color-input {
    width: 2.75rem;
    height: 2rem;
    padding: 0.1rem;
    cursor: pointer;
}

/* Standardstatus-Select je Vorgangstyp (Ticket 76): kompaktes natives Feld in
   der Stammdaten-Liste, breit genug für die Statusnamen. */
.inline-master-data-select {
    min-width: 10rem;
    cursor: pointer;
}

/* Editierbare Badge-Variante (siehe app/static/js/colored-select.js): das <select>
liefert ausschließlich die Interaktion (Klick/Tastatur öffnet die native Auswahl),
sichtbar bleibt einzig der darüberliegende Badge – dieselbe Darstellung wie beim
rein anzeigenden colored_badge-Makro, keine doppelte Text-/Badge-Anzeige. */
.colored-select {
    position: relative;
    display: inline-flex;
}

.colored-select select {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    opacity: 0;
    cursor: pointer;
}

.colored-select .colored-badge {
    margin-left: 0;
    pointer-events: none;
}

.list-filter-bar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2);
    margin-bottom: var(--space-3);
}

/* Serverseitiges Suchformular (S6-01/S6-02, app/templates/search/partials/
search_form.html): gleiche Optik wie die Listen-Toolbars, aber echtes
GET-Formular auf /suche statt clientseitigem Tabellenfilter. */
.search-form {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    max-width: 40rem;
    margin-bottom: var(--card-gap);
}

.search-form .list-filter {
    flex: 1 1 auto;
    width: auto;
    min-width: 0;
}

.object-akte .search-form {
    margin-bottom: 0;
    max-width: none;
}

/* Filterleisten-Controls (Selects und Datumsfelder, z. B. Zeitraumfilter der
Vorgangsliste): dieselbe Höhe und Designsprache wie .list-toolbar select bzw.
.list-filter, damit alle Filterelemente einer Seite einheitlich wirken. */
.list-filter-bar select,
.list-filter-bar input[type="date"],
.search-form select {
    min-width: 10rem;
    height: var(--control-height);
    padding: 0 0.75rem;
    border: 1px solid var(--color-border-strong);
    border-radius: var(--radius-sm);
    background-color: var(--color-surface);
    color: var(--color-text);
    font: inherit;
}

.list-filter-bar select:focus,
.list-filter-bar input[type="date"]:focus,
.search-form select:focus {
    outline: none;
    border-color: var(--color-accent);
    box-shadow: 0 0 0 3px rgba(110, 168, 254, 0.2);
}

a.colored-badge {
    cursor: pointer;
}

a.colored-badge:hover {
    background-color: color-mix(in srgb, var(--badge-color, var(--color-border-strong)) 28%, transparent);
    text-decoration: none;
}

/* Farbauswahl mit Live-Vorschau (siehe app/static/js/color-field.js). */
.color-field {
    display: flex;
    align-items: center;
    gap: var(--space-3);
}

/* Farbschema-Einstellungen (/stammdaten/design, app/static/js/theme-color-preview.js):
   kompaktes Raster aus Farbfeldern statt der sonst 28rem breiten .form-row je Zeile. */
.theme-color-grid {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-4) var(--space-5);
}

.theme-color-grid .form-row {
    max-width: none;
    width: 11rem;
    margin-bottom: 0;
}

.theme-color-grid input[type="color"] {
    width: 100%;
    height: var(--control-height);
    padding: 0.2rem;
    border: 1px solid var(--color-border-strong);
    border-radius: var(--radius-sm);
    background-color: var(--color-surface);
    cursor: pointer;
}

/* Formulare */

.form-row {
    margin-bottom: var(--space-4);
    display: flex;
    flex-direction: column;
    max-width: 28rem;
}

/* Mehrere kompakte Felder nebeneinander in einer Formularzeile (z. B.
Vorgangstyp/Status/Priorität als Badge-Auswahl im Vorgangsformular): jede
Spalte bleibt eine normale .form-row (Label über dem Feld). */
.form-row-columns {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-4);
    max-width: 28rem;
}

.form-row-columns > .form-row {
    flex: 1 1 auto;
    min-width: 0;
    max-width: none;
}

/* Stammdaten-Felder des Objektformulars als Begriff/Wert-Zeilen – exakt die
Anatomie der Objektdaten-Karte der Objektakte (.object-facts-grid), nur mit
Eingabefeldern: Label links fett wie die dt-Spalte, Control rechts als
sichtbare Textbox. */
.form-facts-grid > .form-facts-row {
    display: grid;
    /* Identisches Spaltenraster wie die Eigenschaftszeilen (.properties-grid),
    inklusive des leeren dritten Segments in Breite des Entfernen-Buttons –
    Stammdaten- und Eigenschaftszeilen fluchten dadurch exakt. */
    grid-template-columns: minmax(7rem, 0.8fr) minmax(0, 1.2fr) 1.9rem;
    gap: var(--space-2) var(--space-3);
    align-items: center;
    padding: var(--space-1) var(--space-2);
    border-bottom: 1px solid var(--color-border);
}

.form-facts-row label {
    margin: 0;
    /* Gleiches Innenpadding wie das Eigenschaftsname-Feld (transparenter
    Rahmen + 0.3/0.4rem), damit die Beschriftungen exakt bündig stehen. */
    padding: 0.3rem 0.4rem;
    border: 1px solid transparent;
    font-weight: var(--ui-fw-semibold);
    font-size: calc(0.9rem * var(--ui-fs-secondary));
    color: var(--color-text);
}

/* Zusammengesetzte Selektoren, damit die Textbox-Optik gegen die subtilen
.properties-grid-Feldregeln gewinnt (alle Zeilen teilen sich einen Container). */
.form-facts-grid > .form-facts-row input,
.form-facts-grid > .form-facts-row select,
.form-facts-grid > .form-facts-row textarea,
.properties-grid [data-property-value-cell] input,
.properties-grid [data-property-value-cell] select {
    width: 100%;
    min-width: 0;
    background-color: var(--color-surface);
    border: 1px solid var(--color-border-strong);
    border-radius: var(--radius-sm);
    padding: 0.35rem 0.5rem;
    color: var(--color-text);
    font: inherit;
    font-size: calc(0.9rem * var(--ui-fs-secondary));
}

.form-facts-grid > .form-facts-row textarea {
    resize: vertical;
}

.form-facts-grid > .form-facts-row input:focus,
.form-facts-grid > .form-facts-row select:focus,
.form-facts-grid > .form-facts-row textarea:focus,
.properties-grid [data-property-value-cell] input:focus,
.properties-grid [data-property-value-cell] select:focus {
    outline: none;
    border-color: var(--color-accent);
    box-shadow: 0 0 0 3px rgba(110, 168, 254, 0.2);
}


.form-row label {
    margin-bottom: var(--space-2);
    font-size: calc(0.875rem * var(--ui-fs-secondary));
    font-weight: var(--ui-fw-medium);
    color: var(--color-text-muted);
}

/* Einzelnes Checkbox-Feld (z. B. "Aktiv"): Checkbox und Beschriftung stehen
   nebeneinander statt im sonst üblichen Spalten-Layout aus Label über Feld. */
.form-row-checkbox label {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: var(--space-2);
    margin-bottom: 0;
    color: var(--color-text);
    font-weight: var(--ui-fw-normal);
    font-size: calc(1rem * var(--ui-fs-body));
}

.form-row-checkbox input[type="checkbox"] {
    width: auto;
}

/* Ein einziger, projektweiter Satz Eingabefeld-Regeln statt getrennter
   Varianten je Kontext (Formular, Tabellenzelle, Combobox): Textfelder,
   Comboboxen, Selects, Datums- und Zahlenfelder erhalten dieselbe Höhe
   (Padding/Schriftgröße/Randstärke), unabhängig davon, ob sie in einem
   .form-row-Formular oder einer Tabellenzelle (.list-table td, z. B.
   Eigenschaften-, Vorgangsstatus- oder Ereignistabelle) stehen. Textareas
   bleiben bewusst größer, folgen aber derselben Randfarbe/-stärke,
   Schriftart und demselben Fokusstil. */
.form-row input,
.form-row select,
.form-row textarea,
.due-action-form input[type="text"],
.list-table td input:not([type="checkbox"]):not([type="color"]),
.list-table td select,
.list-table td textarea {
    background-color: var(--color-surface);
    color: var(--color-text);
    font-family: inherit;
    font-size: calc(0.9rem * var(--ui-fs-secondary));
    line-height: 1.3;
    border: 1px solid var(--color-border-strong);
    border-radius: var(--radius-sm);
    padding: 0.55rem 0.7rem;
    transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

/* Einzeilige Controls auf die einheitliche Kontrollhöhe bringen (vertikal
   zentriert per fester Höhe statt Padding; Textareas bleiben mehrzeilig,
   Farbfelder quadratisch – siehe --control-height). */
.form-row input:not([type="checkbox"]):not([type="color"]),
.form-row select,
.due-action-form input[type="text"],
.list-table td input:not([type="checkbox"]):not([type="color"]),
.list-table td select {
    height: var(--control-height);
    padding-top: 0;
    padding-bottom: 0;
}

.list-table td input:not([type="checkbox"]):not([type="color"]),
.list-table td select,
.list-table td textarea {
    width: 100%;
}

.form-row input:focus,
.form-row select:focus,
.form-row textarea:focus,
.list-table td input:focus,
.list-table td select:focus,
.list-table td textarea:focus {
    outline: none;
    border-color: var(--color-accent);
    box-shadow: 0 0 0 3px rgba(110, 168, 254, 0.2);
}

/* iOS Safari zoomt beim Fokus automatisch in Formularfelder mit einer
   Schriftgröße unter 16px hinein (PO-Meldung 2026-07-29, Ticket 60) – die Seite
   „springt“ dann. Auf Touch-Geräten daher mindestens 16px, damit nichts
   hineinzoomt; die Seite bleibt, wie sie ist. Bewusst mit `!important`, weil es
   die vielen kontextspezifischen Feldgrößen geräteabhängig überstimmen muss –
   auch die in Safari verkleinerten Auswahl-/Datumsfelder (Ticket 57), die auf
   dem iPhone sonst am stärksten zoomen. Checkboxen/Radios/Farb-/Bereichs-/
   Datei-Felder lösen keinen Zoom aus und bleiben ausgenommen. */
@media (pointer: coarse) {
    input:not([type="checkbox"]):not([type="radio"]):not([type="color"]):not([type="range"]):not([type="file"]),
    select,
    textarea {
        font-size: 16px !important;
    }
}

.form-row textarea {
    resize: vertical;
    min-height: 4.5rem;
}

.form-error {
    color: var(--color-danger-text);
    background-color: var(--color-danger-bg);
    border: 1px solid var(--color-danger-border);
    border-radius: var(--radius-sm);
    padding: var(--space-3) var(--space-4);
    max-width: 28rem;
    margin-bottom: var(--space-4);
}

/* Objekt anlegen/bearbeiten verwenden bewusst dieselben Layoutklassen wie die
Objektakte (.object-akte-page/-grid/-akte/-section-header), damit beide Ansichten
strukturell und optisch 1:1 konsistent bleiben, siehe app/templates/technical_objects/
detail.html. */

.object-akte .form-row:last-child {
    margin-bottom: 0;
}

/* Inline-Felder in einer Formularzeile, z. B. „Alle [Wert] [Einheit]“ des
   Maßnahmenplan-Intervalls (ADR-028). */
.form-inline-fields {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    flex-wrap: wrap;
}

.form-inline-number {
    max-width: 6rem;
}

.object-akte .heading-select {
    width: 100%;
    padding: 0.55rem 0.7rem;
    font-size: calc(0.95rem * var(--ui-fs-body));
    font-weight: var(--ui-fw-normal);
}

.object-akte button[data-add-property-row] {
    margin-top: var(--space-3);
}

.properties-table {
    min-width: 0;
}

.properties-table .list-table-actions {
    width: 8rem;
    white-space: nowrap;
}

/* Combobox: rein clientseitiges Widget statt <datalist>, damit ausschließlich
   bekannte Werte vorgeschlagen werden und Browser-/Adressbuch-Autofill nicht
   eingreift (generische Komponente app/static/js/combobox.js). */
.combobox {
    position: relative;
}

.combobox-suggestions {
    /* position: fixed statt absolute: die Eigenschaftszeilen liegen in einem
    Tabellen-Wrapper mit overflow-x: auto, der damit auch die Y-Achse clippt
    (CSS-Spezifikation: "auto" auf einer Achse erzwingt "auto" auf der
    anderen statt "visible"). Ein absolut positioniertes Dropdown würde dort
    unsichtbar abgeschnitten; fixed umgeht das, Position/Breite werden in
    app/static/js/combobox.js je Öffnung aus der Eingabefeld-Position
    berechnet. */
    position: fixed;
    z-index: 200;
    margin: 0.2rem 0 0;
    padding: 0.25rem 0;
    max-height: 14rem;
    overflow-y: auto;
    list-style: none;
    background-color: var(--color-surface-raised);
    border: 1px solid var(--color-border-strong);
    border-radius: var(--radius-sm);
    box-shadow: var(--shadow-card);
}

.combobox-suggestions li {
    padding: 0.4rem 0.65rem;
    font-size: calc(0.85rem * var(--ui-fs-secondary));
    cursor: pointer;
}

.combobox-suggestion-active {
    background-color: var(--color-accent);
    color: var(--color-on-accent, #0b1220);
}

/* Anlegen-Aktion (assignment_combobox mit create_object): abgesetzt als
   Sekundäraktion unter den Treffern, sobald die Eingabe zu keiner Option
   passt. */
.combobox-suggestion-create {
    font-style: italic;
    color: var(--color-text-muted);
}

.combobox-suggestion-create.combobox-suggestion-active {
    color: var(--color-on-accent, #0b1220);
}

li.combobox-suggestion-create:not(:first-child) {
    border-top: 1px solid var(--color-border);
}

/* Eigenen Text übernehmen (Ticket 36): abgesetzt als Sekundäraktion unter den
   Treffern – behält den getippten Freitext, statt zum Vorschlag zu
   vervollständigen. Gleiche Optik wie die Anlegen-Aktion. */
.combobox-suggestion-adopt {
    font-style: italic;
    color: var(--color-text-muted);
}

.combobox-suggestion-adopt.combobox-suggestion-active {
    color: var(--color-on-accent, #0b1220);
}

li.combobox-suggestion-adopt:not(:first-child) {
    border-top: 1px solid var(--color-border);
}

/* Zuordnungs-Picker (assignment_combobox): Suchfeld und Vorschlagsliste
   nutzen die volle verfügbare Breite – deutlich breiter als die kompakten
   Standard-Textfelder, damit Hierarchiepfade und Kontextzeilen lesbar
   bleiben (in Tabellenzellen mit Aktionsbutton füllt der Picker den
   flexiblen Rest der event-reference-control-Zeile). */
.combobox-assignment {
    width: 100%;
}

.combobox-assignment input[type="text"] {
    width: 100%;
    min-width: 14rem;
}

.event-reference-control .combobox-assignment {
    flex: 1 1 auto;
}

.combobox-assignment .combobox-suggestions {
    min-width: min(28rem, 90vw);
}

/* Kontextzeile eines Vorschlags im Wertmodus der generischen Combobox
   (z. B. Objektklasse · Objekttyp hinter dem Objektnamen). */
.combobox-suggestion-hint {
    margin-left: var(--space-2);
    color: var(--color-text-faint);
    font-size: calc(0.75rem * var(--ui-fs-small));
}

.combobox-suggestion-active .combobox-suggestion-hint {
    color: inherit;
}

/* Einheit hinter einem Eigenschaftswert (Objektakte): normale Textfarbe,
   nur ein Leerzeichen Abstand – wirkt wie Teil des Werts. */
.property-value-unit {
    color: inherit;
    white-space: nowrap;
}

/* In-Feld-Einheit des Eigenschaften-Rastereditors: absolut IM Eingabefeld,
   direkt hinter dem getippten Text positioniert (Breitenmessung in
   property-widgets.js); Optik wie der Eingabetext selbst. */
.properties-grid [data-property-value-cell] {
    position: relative;
    min-width: 0;
}

/* Vollbreite Inline-Schnellanlage der Vorgangstabellen: eigene Flex-Zeile
   in einer colspan-Zelle über alle Spalten, damit Felder und Aktionsbuttons
   nicht unter fremden Spaltenüberschriften stehen (docs/13). */
.inline-create-fields {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2);
}

.inline-create-fields .inline-create-title {
    flex: 1 1 12rem;
    min-width: 10rem;
}

.inline-create-fields .combobox {
    flex: 1 1 14rem;
    min-width: 12rem;
}

.property-input-unit {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    pointer-events: none;
    color: var(--color-text);
    font-size: calc(0.9rem * var(--ui-fs-secondary));
    white-space: nowrap;
}

.properties-editor-actions {
    display: flex;
    justify-content: flex-end;
    gap: var(--space-2);
    align-items: center;
    margin-top: var(--space-3);
}

/* Griff zum Verschieben von Eigenschaftszeilen: das eigentliche Ziehen läuft
über die generische reorderable-list-Komponente (data-reorder-handle am
Container), dieser Stil betrifft nur die Optik des Griffs. */
.property-drag-handle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--color-text-faint);
    cursor: grab;
    touch-action: none;
    -webkit-user-select: none;
    -webkit-touch-callout: none;
    user-select: none;
}

.property-drag-handle:active {
    cursor: grabbing;
}

/* Eigenschaften-Rastereditor (Objekt anlegen/bearbeiten): gleiche Anatomie wie
die Objektakten-Darstellung (.object-facts-grid, mehrspaltig, Trennlinien),
nur mit editierbaren Feldern in Fakten-Optik (unauffällig bis Hover/Fokus).
Die feste letzte Eingabezeile ist eine normale `.properties-grid-row` mit der
ID `#new-property-row`; Griff und Entfernen-Button blendet allein die CSS-Regel
zu dieser ID aus (siehe unten) – die Umwandlung in eine vollwertige Zeile
braucht dadurch keine Markup-Injektion (object-form.js). */
.properties-grid > div {
    display: grid;
    grid-template-columns: minmax(7rem, 0.8fr) minmax(0, 1.2fr) 1.9rem;
    gap: var(--space-2) var(--space-3);
    /* stretch statt center: Bricht eine Zelle mehrzeilig um (z. B. ein
       langer Eigenschaftsname), strecken sich alle Felder der Zeile auf
       dieselbe Höhe – das Raster bleibt kohärent. */
    align-items: stretch;
    padding: var(--space-1) var(--space-2);
    border-bottom: 1px solid var(--color-border);
}

/* Felder füllen die (ggf. mehrzeilige) Zeilenhöhe; die Aktionsspalte
   zentriert ihren Button unabhängig davon. */
.properties-grid > div > input,
.properties-grid > div > select,
.properties-grid .combobox > input,
.properties-grid [data-property-value-cell] > input,
.properties-grid [data-property-value-cell] > select,
.properties-grid [data-property-value-cell] .combobox,
.properties-grid [data-property-value-cell] .combobox > input {
    height: 100%;
}

.properties-grid [data-property-actions] {
    display: flex;
    align-items: center;
}

.properties-grid > div > label {
    display: flex;
    align-items: center;
}


.properties-grid input,
.properties-grid select {
    width: 100%;
    min-width: 0;
    background: transparent;
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    padding: 0.3rem 0.4rem;
    color: var(--color-text);
    font: inherit;
    font-size: calc(0.9rem * var(--ui-fs-secondary));
}

.properties-grid input[name="property_key"] {
    font-weight: var(--ui-fw-semibold);
}

/* Der Eigenschaftsname ist selbst der Griff zum Verschieben (data-reorder-grip):
Greif-Cursor solange nicht getippt wird; mit Fokus normaler Text-Cursor. */
.properties-grid input[name="property_key"]:not(:focus) {
    cursor: grab;
}

.properties-grid input:hover,
.properties-grid select:hover {
    border-color: var(--color-border-strong);
}

.properties-grid input:focus,
.properties-grid select:focus {
    outline: none;
    border-color: var(--color-accent);
    background-color: var(--color-surface);
    box-shadow: 0 0 0 3px rgba(110, 168, 254, 0.2);
}

.properties-grid .icon-button-danger {
    width: 1.6rem;
    height: 1.6rem;
    font-size: calc(0.8rem * var(--ui-fs-secondary));
}

/* In der festen letzten Eingabezeile sind Griff und Entfernen unsichtbar
(Platz bleibt reserviert, damit die Spalten bündig stehen). Gilt für den
Rastereditor ebenso wie für den Tabellen-Editor der Objekttyp-Stammdaten. */
#new-property-row .property-drag-handle,
#new-property-row [data-property-actions] .icon-button-danger {
    visibility: hidden;
}

/* Kompaktes Formularmuster für Kommentare in der Vorgangsakte. Ereignisse
werden direkt über die feste Eingabezeile der Fortschrittstabelle erfasst. */
.work-order-note-form {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    margin-top: var(--space-4);
    max-width: 32rem;
}

.work-order-note-form select,
.work-order-note-form textarea {
    width: 100%;
    background-color: var(--color-surface);
    color: var(--color-text);
    font-family: inherit;
    font-size: calc(0.9rem * var(--ui-fs-secondary));
    border: 1px solid var(--color-border-strong);
    border-radius: var(--radius-sm);
    padding: 0.55rem 0.7rem;
}

.work-order-note-form select {
    height: var(--control-height);
    padding-top: 0;
    padding-bottom: 0;
}

.work-order-note-form textarea {
    min-height: 4.5rem;
    resize: vertical;
}

.work-order-note-form select:focus,
.work-order-note-form textarea:focus {
    outline: none;
    border-color: var(--color-accent);
    box-shadow: 0 0 0 3px rgba(110, 168, 254, 0.2);
}

.work-order-note-form label {
    font-size: calc(0.875rem * var(--ui-fs-secondary));
    font-weight: var(--ui-fw-medium);
    color: var(--color-text-muted);
}

.work-order-note-form .form-actions {
    margin: 0;
}

.work-order-events-table {
    min-width: 72rem;
}

/* Fetter Trennstrich zwischen vergangenen und zukünftigen Ereignissen
   (ADR-025): eine besonders kräftige horizontale Linie mit dezentem Label;
   künftige Ereignis-Zeilen sind zusätzlich leicht gedämpft. */
.event-future-divider td {
    padding: 0;
    border-top: 4px solid var(--color-border-strong);
    background-color: transparent;
}

.event-future-divider span {
    display: inline-block;
    padding: var(--space-1) 0 calc(var(--space-1) / 2);
    font-size: calc(0.75rem * var(--ui-fs-small));
    font-weight: var(--ui-fw-strong);
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--color-text-faint);
}

.event-row-future td {
    color: var(--color-text-muted);
}

/* Der statische, beschriftete Trennstrich oben passt nur zur Standard-
   (Drag-)Reihenfolge. Beim Sortieren über einen Spaltenkopf hängt data-table.js
   nur die Zeilen um – die Trennzeile bliebe an falscher Stelle stehen. Darum
   blendet JEDE Sortierung sie aus (PO-Meldung 2026-07-29, Ticket 63). */
.work-order-events-table[data-sorted-by] .event-future-divider {
    display: none;
}

/* Bei Sortierung nach DATUM sitzt der Trennstrich stattdessen – wie in der
   Vorgangsliste (ADR-025) – per CSS an der tatsächlichen Grenze zwischen
   vergangenen und künftigen (data-future) Ereignissen, richtungsunabhängig:
   Aufsteigend stehen die künftigen Zeilen am Ende (die erste trägt den Strich
   oben), absteigend am Anfang (die letzte trägt ihn unten). So steht ein
   künftiger Termin bei aufsteigender Datumssortierung sauber getrennt unten in
   der Liste. Andere Sortierungen streuen die künftigen Zeilen und bekommen
   daher keinen Strich. */
.work-order-events-table[data-sorted-by="date"] tbody tr:not([data-future]):not(.event-future-divider) + tr[data-future] > * {
    border-top: 4px solid var(--color-border-strong);
}

.work-order-events-table[data-sorted-by="date"] tbody tr[data-future]:has(+ tr:not([data-future]):not(.event-future-divider)) > * {
    border-bottom: 4px solid var(--color-border-strong);
}

.work-order-event-input td {
    vertical-align: top;
    background-color: var(--color-surface-raised);
}

/* Höhe/Innenabstand kommen aus der projektweiten Regel für
   .list-table td input/select (siehe oben); hier nur die zusätzliche,
   kontextspezifische Anpassung für die dichte Ereignis-Eingabezeile. */
.work-order-event-input input,
.work-order-event-input select,
.work-order-event-input textarea {
    width: 100%;
    min-width: 0;
    font: inherit;
}

/* Bearbeiten/Schnellerfassung: Die Text-Eingabefelder (Titel-Zeile und
   Beschreibungs-Textarea) umschließen den Text enger – deutlich weniger
   Leerraum ober- und unterhalb (PO-Wunsch 2026-07-28). Der Titel-Input
   verliert seine feste Kontrollhöhe und hugt den Text mit knappem Padding; die
   Textarea bekommt knapperes vertikales Padding. Native Auswahl-/Datumsfelder
   bleiben in ihrer Höhe unverändert. */
.work-order-event-input input.event-title-input:not([type="checkbox"]):not([type="color"]) {
    height: auto;
    min-height: 0;
    padding-top: 0.2rem;
    padding-bottom: 0.2rem;
}

.list-table .work-order-event-input textarea {
    padding-top: 0.3rem;
    padding-bottom: 0.3rem;
}

/* Kompaktes Datumsfeld in Tabellen (PO-Meldung 2026-07-28, Ticket 55, Wahl
   „kompaktes natives Feld“): Rand und Kalender-Icon so knapp wie möglich, damit
   das native Feld nur wenig breiter ist als der Anzeigetext „06.02.26“. Der
   native Kalender bleibt im Feld; die Spalte hat keine erzwungene Mindestbreite
   mehr und bleibt frei verschiebbar (die frühere feste Breite entfiel). */
.list-table td input[type="date"]:not([type="checkbox"]):not([type="color"]) {
    padding-left: 0.35rem;
    padding-right: 0.1rem;
}

.list-table td input[type="date"]::-webkit-calendar-picker-indicator {
    margin-left: 0.1rem;
    padding: 0;
}

/* Native <select> und Datumsfelder rendern in Safari mit einer größeren
   System-Schrift, als per font-size angegeben ist, und wirken dadurch deutlich
   größer als der normale Zelltext (PO-Meldung 2026-07-28, Ticket 57; in
   Chrome/Firefox stimmt die Größe bereits). Nur in Safari verkleinern:
   `@supports (background: -webkit-named-image(i))` trifft ausschließlich Safari,
   sodass Chrome/Firefox unberührt bleiben. */
@supports (background: -webkit-named-image(i)) {
    .list-table td select,
    .list-table td input[type="date"]:not([type="checkbox"]):not([type="color"]) {
        font-size: calc(0.78rem * var(--ui-fs-secondary));
    }
}

.event-reference-control {
    display: flex;
    align-items: center;
    gap: var(--space-2);
}

.event-reference-control select {
    flex: 1 1 auto;
}

.list-value-with-action {
    display: inline-flex;
    align-items: center;
    gap: 0.15rem;
}

/* Kleine Entfernen-Buttons (×) in Listenwerten/Chips: wie alle Löschen-/
Entfernen-Aktionen dauerhaft mit rotem Hintergrund und weißem ✕, nicht erst
bei Hover (docs/13_design_system.md, „Buttons“). */
.inline-remove-button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.1rem;
    height: 1.1rem;
    padding: 0;
    border: 0;
    border-radius: var(--radius-sm);
    background-color: var(--color-danger-solid);
    color: #fff;
    font: inherit;
    font-size: calc(0.75rem * var(--ui-fs-small));
    line-height: 1;
    cursor: pointer;
}

.inline-remove-button:hover {
    background-color: var(--color-danger-solid-hover);
    color: #fff;
}

.work-order-event-input input[type="time"] {
    margin-top: var(--space-2);
}

.work-order-event-input textarea {
    /* Kompakter Start (PO 2026-07-22, Ticket 25): rund eineinhalb Zeilen als
       Minimum – kurze Meldungen sind dann nicht unnötig hoch. Für längeren Text
       wächst das Feld über table-textarea-autogrow.js in der Höhe mit. */
    min-height: 2.4rem;
    resize: vertical;
}

.form-actions {
    display: flex;
    align-items: center;
    gap: var(--space-4);
    /* Einheitlicher Standardabstand der Aktionsleiste zur darüberliegenden
    Karte (kollabiert mit deren margin-bottom, wo vorhanden). */
    margin-top: var(--space-4);
    /* Folgt auf die Aktionsleiste eine Karte (z. B. „Gespeicherte
    Farbschemata“ unter dem Farb-Formular), gilt der Kartenabstand. */
    margin-bottom: var(--card-gap);
}

/* In Dialogen ist die Aktionsleiste die Fußzeile – kein Nachlauf-Abstand. */
.app-modal .form-actions {
    margin-bottom: 0;
}

/* "Abbrechen" ist ein reiner Link, soll aber dieselbe Höhe/Innenabstände wie der
primäre "Speichern"-Button haben (gleiche Aktionsleiste, sekundär statt primär).
.button-danger ("Löschen") behält ihre eigene, rote Gestaltung. */
.form-actions a:not(.button-danger) {
    display: inline-flex;
    align-items: center;
    font-family: inherit;
    font-size: calc(0.9rem * var(--ui-fs-secondary));
    font-weight: var(--ui-fw-semibold);
    text-decoration: none;
    border-radius: var(--radius-sm);
    padding: 0.55rem 1.1rem;
    border: 1px solid var(--color-border-strong);
    color: var(--color-text-muted);
    transition: color 0.15s ease, border-color 0.15s ease;
}

.form-actions a:not(.button-danger):hover {
    color: var(--color-text);
    border-color: var(--color-accent);
    text-decoration: none;
}

.button-secondary {
    background: transparent;
    border: 1px solid var(--color-border-strong);
    color: var(--color-text-muted);
}

.button-secondary:hover {
    background: transparent;
    border-color: var(--color-accent);
    color: var(--color-text);
}

/* Buttons */

button {
    font-family: inherit;
    font-size: calc(0.9rem * var(--ui-fs-secondary));
    font-weight: var(--ui-fw-semibold);
    cursor: pointer;
    border-radius: var(--radius-sm);
    padding: 0.55rem 1.1rem;
    border: 1px solid transparent;
    transition: background-color 0.15s ease, border-color 0.15s ease, transform 0.05s ease;
}

button[type="submit"] {
    background-color: var(--color-accent-strong);
    color: var(--color-accent-contrast);
}

button[type="submit"]:hover {
    background-color: var(--color-accent);
}

button[type="button"] {
    background-color: transparent;
    color: var(--color-text-muted);
    border-color: var(--color-border-strong);
}

button[type="button"]:hover {
    color: var(--color-text);
    border-color: var(--color-accent);
}

button:active {
    transform: translateY(1px);
}

.button-danger {
    display: inline-block;
    font-family: inherit;
    font-size: calc(0.9rem * var(--ui-fs-secondary));
    font-weight: var(--ui-fw-semibold);
    cursor: pointer;
    border-radius: var(--radius-sm);
    padding: 0.55rem 1.1rem;
    border: 1px solid var(--color-danger-border);
    /* Dauerhafter Warnhintergrund, nicht erst bei Hover (docs/13, „Buttons“). */
    background-color: var(--color-danger-solid);
    color: #fff;
    text-decoration: none;
    transition: background-color 0.15s ease, border-color 0.15s ease;
}

.button-danger:hover {
    background-color: var(--color-danger-solid-hover);
    color: #fff;
    text-decoration: none;
}

/* Wiederverwendbare Listen und Tabellen */

.list-toolbar {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    margin-bottom: var(--card-gap);
    max-width: 28rem;
}

.list-toolbar label,
.list-toolbar-search label {
    color: var(--color-text-muted);
    font-size: calc(0.875rem * var(--ui-fs-secondary));
    font-weight: var(--ui-fw-medium);
}

.list-toolbar-with-action {
    flex-direction: row;
    align-items: flex-end;
    justify-content: space-between;
    /* Primäraktion (+) und Spaltenmenü/Einstellungen bleiben immer in einer
       Zeile mit der Suchleiste – auch auf schmalen/mobilen Bildschirmen; die
       Suche schrumpft stattdessen (flex-shrink + min-width: 0). */
    flex-wrap: nowrap;
    gap: var(--space-3);
    max-width: none;
}

.list-toolbar-search {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    flex: 1 1 20rem;
    min-width: 0;
    max-width: 28rem;
}

/* Rechte Aktionsgruppe der Toolbar (Primäraktion + Spaltenmenü): ein eigener
Flex-Container, damit justify-content: space-between auf .list-toolbar-with-action
nur den EINEN Abstand zwischen Suche/Filter (links) und dieser Gruppe (rechts)
spreizt, statt Lücken zwischen den einzelnen Aktions-Buttons auseinanderzuziehen.
Der Spaltenmenü-Button wird von data-table.js automatisch hier eingehängt (siehe
setupColumnMenu), sodass jede Tabellen-Toolbar davon profitiert. */
.list-toolbar-actions {
    display: flex;
    align-items: center;
    flex-shrink: 0;
    gap: var(--space-2);
}

/* Eigenständige, rechtsbündige Aktionsgruppe für Tabellen ohne Toolbar oder
Kartenkopf: stellt die Tabelleneinstellungen (⚙) direkt oben rechts über der
Tabelle bereit (automatisch von data-table.js erzeugt). */
.data-table-standalone-actions {
    justify-content: flex-end;
    margin-bottom: var(--space-2);
}

.data-table-column-menu-container {
    position: relative;
    flex-shrink: 0;
}

/* Einheitliche quadratische Icon-Buttons der rechten Toolbar-Aktionsgruppe
(reines „+“-Icon und Spaltenmenü ⚙): gleiche Höhe, Breite, Rundung und Hover wie
.icon-button, aber größer skaliert, damit beide als zusammengehörige
Buttongruppe wirken. Als zusammengesetzter Selektor (.icon-button.list-toolbar-icon-button)
formuliert, damit die größere Breite/Höhe unabhängig von der Regelreihenfolge im
Stylesheet zuverlässig die Basisgröße aus .icon-button überschreibt (gleiche
Spezifität würde sonst je nach Quellreihenfolge zur kleineren Basisgröße führen). */
.icon-button.list-toolbar-icon-button {
    width: var(--control-height);
    height: var(--control-height);
    font-size: calc(1.1rem * var(--ui-fs-heading));
}

.data-table-column-menu {
    position: absolute;
    top: calc(100% + var(--space-2));
    right: 0;
    z-index: 20;
    /* Breit genug für Checkbox + editierbare Überschrift in einer Zeile. */
    min-width: 18rem;
    max-height: 20rem;
    overflow-y: auto;
    padding: var(--space-2);
    background-color: var(--color-surface-raised);
    border: 1px solid var(--color-border-strong);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-card);
}

.data-table-column-menu-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-2);
    padding: var(--space-2);
    border-radius: var(--radius-sm);
    cursor: grab;
}

.data-table-column-menu-row:hover {
    background-color: var(--color-surface);
}

.data-table-column-menu-row label {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    font-size: calc(0.85rem * var(--ui-fs-secondary));
    color: var(--color-text);
    cursor: pointer;
}

.data-table-column-menu-row input[type="checkbox"] {
    accent-color: var(--color-accent);
}

/* Editierbare Spaltenüberschrift im Spaltenmenü: dezentes Textfeld, das erst
bei Fokus/Hover als Eingabe erkennbar wird, damit die Menüzeile ruhig bleibt. */
.data-table-column-menu-name {
    flex: 1 1 auto;
    min-width: 0;
    padding: 0.25rem 0.4rem;
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    background-color: transparent;
    color: var(--color-text);
    font: inherit;
    font-size: calc(0.85rem * var(--ui-fs-secondary));
}

.data-table-column-menu-row:hover .data-table-column-menu-name,
.data-table-column-menu-name:focus {
    border-color: var(--color-border-strong);
    background-color: var(--color-surface);
}

/* Zurücksetzen auf die Standardüberschrift: kompakter Icon-Button passend zur
Höhe des Textfelds der Menüzeile. */
.data-table-column-menu-reset {
    width: 1.75rem;
    height: 1.75rem;
    font-size: calc(0.85rem * var(--ui-fs-secondary));
}

.data-table-column-menu-name:focus {
    outline: none;
    border-color: var(--color-accent);
    box-shadow: 0 0 0 3px rgba(110, 168, 254, 0.2);
}

/* Pflichtspalte (nicht ausblendbar): ausgegraut statt eines „Pflicht“-Texts –
   nur der Einblenden-Schalter, die Überschrift bleibt normal editierbar. */
.data-table-column-menu-row-required > label {
    opacity: 0.45;
}

.data-table-column-menu-row-dragging {
    opacity: 0.5;
    cursor: grabbing;
}

.data-table-column-menu-row-drop-before {
    box-shadow: inset 0 2px 0 var(--color-accent);
}

.data-table-column-menu-row-drop-after {
    box-shadow: inset 0 -2px 0 var(--color-accent);
}

.list-filter {
    width: 100%;
    height: var(--control-height);
    padding: 0 0.75rem;
    border: 1px solid var(--color-border-strong);
    border-radius: var(--radius-sm);
    background-color: var(--color-surface);
    color: var(--color-text);
    font: inherit;
}

/* Zustandsfilter-Selects (data-list-state-filter) sind sonst unstyled
   Browser-Controls und weichen dadurch in Höhe/Optik von .list-filter ab;
   dieselbe Höhe/Optik wie das Suchfeld, wenn beide nebeneinander stehen. */
.list-toolbar select {
    min-width: 12rem;
    height: var(--control-height);
    padding: 0 0.75rem;
    border: 1px solid var(--color-border-strong);
    border-radius: var(--radius-sm);
    background-color: var(--color-surface);
    color: var(--color-text);
    font: inherit;
}

.list-toolbar select:focus {
    outline: none;
    border-color: var(--color-accent);
    box-shadow: 0 0 0 3px rgba(110, 168, 254, 0.2);
}

.list-filter:focus {
    outline: none;
    border-color: var(--color-accent);
    box-shadow: 0 0 0 3px rgba(110, 168, 254, 0.2);
}

.list-table-wrapper {
    overflow-x: auto;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);
    background-color: var(--color-surface);
    box-shadow: var(--shadow-card);
}

/* Listeninhalte oben statt mittig (PO 2026-07-22, Ticket 19): global über den
   Schalter „Listeninhalte“ in den Anzeige-Einstellungen (Klasse ui-list-align-top
   am <html>). Standard bleibt mittig; oben rückt Text, Badges und Buttons an die
   Oberkante – wie beim Beschreibungstext.

   !important, weil einzelne Tabellen ihre Zellen gezielt mittig stellen (z. B.
   die Tickettabellen); der globale Schalter soll diese Einzelregeln überstimmen. */
.ui-list-align-top .list-table th,
.ui-list-align-top .list-table td {
    vertical-align: top !important;
}

/* Aktionsknöpfe sind eine Flex-Gruppe – dort greift vertical-align nicht, also
   die Knöpfe selbst an den oberen Rand. */
.ui-list-align-top .list-row-actions {
    align-items: flex-start;
}

.list-table {
    width: 100%;
    min-width: 46rem;
    /* separate statt collapse: Beim Resizing wird die Spaltenbreite exakt aus der
    Zeigerposition berechnet (siehe data-table.js); border-collapse verschiebt den
    gerenderten Trennstrich abhängig vom Browser um bis zu einem Pixel gegenüber
    getBoundingClientRect(), wodurch der sichtbare Trenner nicht exakt unter dem
    Mauszeiger läge. */
    border-collapse: separate;
    border-spacing: 0;
    font-size: calc(0.9rem * var(--ui-fs-secondary));
}

.list-table[data-table] {
    table-layout: fixed;
    width: auto;
    min-width: 0;
}

/* Schalter „Nicht breiter als der Bildschirm“ (Ticket 21): Im Fit-Modus müssen
   auch Formularfelder in Zellen (Filterzeile, Inline-Eingaben) mit ihrer Spalte
   schrumpfen – sonst behalten Selects/Inputs ihre Mindest-Inhaltsbreite und
   ragen aus schmal geklammerten Spalten heraus, wodurch trotz gepasster
   Tabellenbreite doch ein Scrollbalken entstünde. Die Klammerung der reinen
   Textinhalte übernimmt bereits die Inhaltsskalierung in data-table.js. */
.list-table[data-table].data-table-fit td input:not([type="checkbox"]):not([type="color"]),
.list-table[data-table].data-table-fit td select,
.list-table[data-table].data-table-fit td textarea {
    min-width: 0;
    max-width: 100%;
    width: 100%;
}

/* Überbreite Inhalte skaliert die Inhaltsskalierung (data-table.js) per
   transform herunter – das verkleinert aber die LAYOUT-Breite nicht. In den
   Mehrzeilen-Zellen (overflow: visible) bläht diese unsichtbare Layout-Breite
   die scrollbare Fläche auf, sodass trotz optisch passender Tabelle ein
   Scrollbalken entstünde. Im Fit-Modus clippen daher alle Zellen ihren
   horizontalen Überhang; sichtbar bleibt alles, weil es bereits herunter-
   skaliert in die Spalte passt. */
.list-table[data-table].data-table-fit td,
.list-table[data-table].data-table-fit th {
    overflow: hidden;
}

.list-table th,
.list-table td {
    min-width: 3.5rem;
    padding: var(--space-3) var(--space-4);
    border-bottom: 1px solid var(--color-border);
    overflow: hidden;
    text-overflow: ellipsis;
    text-align: left;
    vertical-align: middle;
}

/* Interaktive Tabellen schneiden überbreiten Inhalt NICHT mit „…“ ab, sondern
   skalieren ihn herunter (fitCellContents in data-table.js) – der Grundsatz
   „niemals abschneiden“ (docs/13). Das „…“ aus der Basisregel oben blitzte
   trotzdem manchmal neben skalierten Badges auf: im kurzen Moment, bevor die
   Skalierung greift, und in Safari auch bei bereits skaliertem Inhalt (die
   Layout-Breite bleibt beim transform erhalten). Darum hier hart auf `clip` –
   ohne JS-Timing-Lücke (PO 2026-07-22, Ticket 26). */
.list-table[data-table] th,
.list-table[data-table] td {
    text-overflow: clip;
}

/* Vorgänge, deren „Letzter Fortschritt“ in der Zukunft liegt (data-future):
   kräftiger Trennstrich als Grenze zwischen Vergangenheit und Zukunft, analog
   zum Trenner der Ereignisliste (ADR-025).

   Der Strich erscheint NUR bei Sortierung nach genau dieser Spalte
   (data-sorted-by="last-progress", gesetzt von data-table.js; Richtung egal –
   PO 2026-07-21). Sonst stünden die künftigen Vorgänge verstreut in der Liste
   und der Strich träfe mitten hinein, statt zu trennen: In der
   Standardsortierung nach Vorgangsnummer folgen unter einem künftigen Vorgang
   ohne Weiteres wieder vergangene.

   Er sitzt per CSS an der TATSÄCHLICHEN Grenze statt als eigene Trennzeile im
   Markup (so wie es die Ereignisliste macht), und zwar richtungsunabhängig:
   Aufsteigend stehen die künftigen Zeilen am Ende – dann trägt die erste von
   ihnen den Strich oben. Absteigend stehen sie am Anfang – dann trägt die
   letzte von ihnen den Strich unten. Ein Strich pauschal oben an jeder
   künftigen Zeile säße absteigend direkt unter dem Tabellenkopf und würde
   nichts trennen. So entsteht in beiden Richtungen genau EIN Strich, auch
   nach dem Umsortieren (data-table.js hängt die Zeilen im DOM um). */
.list-table[data-sorted-by="last-progress"] tbody tr:not([data-future]) + tr[data-future] > * {
    border-top: 3px solid var(--color-border-strong);
}

.list-table[data-sorted-by="last-progress"] tbody tr[data-future]:has(+ tr:not([data-future])) > * {
    border-bottom: 3px solid var(--color-border-strong);
}

/* Mehrzeilige Textzellen (data-multiline): Zeilenumbrüche und Leerzeilen
   langer Texte bleiben erhalten (pre-line) und werden nicht per Ellipse
   abgeschnitten – global für alle Listen nutzbar. */
.list-table td[data-multiline] {
    white-space: pre-line;
    overflow: visible;
    text-overflow: clip;
    vertical-align: top;
}

/* Ereignisbeschreibung in der Vorgangs-Ereignistabelle (PO 2026-07-27):
   optionaler Titel als fette erste Zeile, darunter der Beschreibungstext. Die
   Zelle wird auf ~10 Zeilen begrenzt; ist der Inhalt höher, blendet
   event-description.js einen „mehr anzeigen“-Schalter ein. */
.event-desc {
    white-space: pre-line;
    line-height: 1.5;
    max-height: calc(10 * 1.5em);
    overflow: hidden;
}

.event-desc.is-expanded {
    max-height: none;
}

.event-desc-title {
    display: block;
    font-weight: var(--ui-fw-strong);
}

.event-desc-more {
    display: inline-block;
    margin-top: var(--space-1);
    padding: 0;
    border: none;
    background: none;
    color: var(--color-accent);
    font: inherit;
    cursor: pointer;
}

.event-desc-more:hover {
    text-decoration: underline;
}

/* Titel-Eingabefeld über der Beschreibungs-Textarea (Schnellerfassung +
   Bearbeiten-Zeile): steht als eigene Box oberhalb, fett als Titel-Hinweis. */
.event-title-input {
    display: block;
    width: 100%;
    margin-bottom: var(--space-1);
    font-weight: var(--ui-fw-strong);
}

/* Badges in Tabellenzellen: kein zusätzlicher linker Außenabstand (der stammt
aus Badge-Verwendungen neben Überschriften) – der freie Raum vor/hinter einem
Badge entspricht damit exakt dem normalen Zellen-Padding. Mehrere Badges in
derselben Zelle behalten einen kleinen Abstand zueinander. */
.list-table .colored-badge {
    margin-left: 0;
}

.list-table .colored-badge + .colored-badge {
    margin-left: var(--space-1);
}

/* Auf Spaltenbreite herunterskalierte Zellinhalte (fitCellContents in
data-table.js): Inhalte, die trotz Umbruchmöglichkeit breiter als ihre Spalte
bleiben (Badges, Datumsangaben, lange Wörter), werden vollständig, aber
verkleinert dargestellt statt mit „…“ abgeschnitten. */
.data-table-cell-fit {
    display: inline-block;
    max-width: none;
    vertical-align: middle;
    transform-origin: left center;
    white-space: inherit;
}

.list-table thead th {
    position: relative;
    background-color: var(--color-surface-raised);
    color: var(--color-text-muted);
    font-size: calc(0.78rem * var(--ui-fs-small));
    font-weight: var(--ui-fw-semibold);
    letter-spacing: 0.03em;
    text-transform: uppercase;
    text-align: left !important;
    white-space: nowrap;
    border-right: 1px solid var(--color-border);
    touch-action: none;
    overflow: visible;
}

/* Greifzone des Spaltentrenners breiter (PO 2026-07-23, Ticket 32): Der 8-px-
   Griff wurde knapp verfehlt, dann startete das Umsortieren der Spalte, an der
   man klickte. 14 px, mittig auf dem Trenner (right: -7px), decken beide Seiten
   der Grenze ab und sind zuverlässig zu treffen. Der Griff liegt über der
   Kopfzelle (z-index) und unterbindet beim Anfassen deren Umsortier-Drag. */
.data-table-resize-handle {
    position: absolute;
    z-index: 2;
    top: 0;
    width: 14px;
    height: 100%;
    cursor: col-resize;
}

.data-table-resize-handle-right {
    right: -7px;
}

.list-table thead th:last-child {
    border-right: 0;
}

/* Der rechte Resize-Griff der letzten Spalte ragt sonst über den Tabellenrand
   (Ticket 21: Scrollbalken im Fit-Modus). Er wird generell bündig an die
   Innenkante gerückt statt entfernt – so bleibt er greifbar (Ticket 27), ragt
   in keinem Modus über und erzeugt keinen Überlauf. */
.list-table[data-table] thead th:last-child .data-table-resize-handle-right {
    right: 0;
}

/* Headerloser Modus: entfernt ausschließlich die optische Kopfzeile (Hintergrund,
Großschrift, Beschriftung) einer Tabelle, ohne ihre Struktur zu verändern. Der
Spaltentrenner (Rahmen zwischen den Kopfzellen) und der unsichtbar darüberliegende
Resize-Hitbereich (data-table-resize-handle) bleiben unverändert erhalten, sodass
Spaltenbreiten weiterhin per Ziehen angepasst werden können; Reihenfolge, Sichtbarkeit
und Persistenz laufen komplett über die bestehende, unveränderte JavaScript-Logik, die
nur die Tabellenstruktur kennt und keine Kenntnis vom headerlosen Modus benötigt.
Aktivierung generisch über das Attribut data-table-headerless am jeweiligen table-Element,
ohne Sonderlösung je Tabelle. */
.list-table[data-table-headerless] thead th {
    height: 0.5rem;
    padding: 0;
    background-color: transparent;
    color: transparent;
    font-size: 0;
    letter-spacing: normal;
    text-transform: none;
}

.list-table[data-table-headerless] .data-table-header-label,
.list-table[data-table-headerless] .data-table-sort-button {
    display: none;
}

.list-table tbody th {
    color: var(--color-text);
    font-weight: var(--ui-fw-semibold);
}

.list-table tbody tr:last-child th,
.list-table tbody tr:last-child td {
    border-bottom: 0;
}

.list-table tbody tr:hover {
    background-color: rgba(110, 168, 254, 0.06);
}

.list-table [hidden] {
    display: none;
}

.data-table-sort-button,
.data-table-header-label {
    display: block;
    width: 100%;
    /* Nicht abschneiden: überbreite Überschriften werden von fitCellContents
       (data-table.js) per transform: scale() auf die Spaltenbreite
       herunterskaliert. Bei overflow: hidden würde der Text vor dem Skalieren
       mit „…“ beschnitten und bliebe abgeschnitten – daher sichtbar lassen. */
    overflow: visible;
    white-space: nowrap;
    transform-origin: left center;
}

.data-table-sort-button {
    padding: 0;
    border: 0;
    background: transparent;
    color: inherit;
    font: inherit;
    letter-spacing: inherit;
    text-align: left;
    text-transform: inherit;
    white-space: inherit;
}

.data-table-sort-button:hover {
    color: var(--color-text);
}

.list-table th[aria-sort="ascending"] .data-table-sort-button::after {
    content: "↑";
    margin-left: var(--space-2);
    color: var(--color-accent);
    font-size: calc(0.75rem * var(--ui-fs-small));
}

.list-table th[aria-sort="descending"] .data-table-sort-button::after {
    content: "↓";
    margin-left: var(--space-2);
    color: var(--color-accent);
    font-size: calc(0.75rem * var(--ui-fs-small));
}

.data-table-resizing {
    user-select: none;
}

.data-table-column-dragging {
    opacity: 0.5;
}

.data-table-column-target-before {
    box-shadow: inset 3px 0 0 var(--color-accent);
}

.data-table-column-target-after {
    box-shadow: inset -3px 0 0 var(--color-accent);
}

.list-table-number {
    text-align: right !important;
    white-space: nowrap;
}

.list-table-actions {
    width: 1%;
}

.list-table[data-table] .list-table-actions {
    width: 8rem;
}

.list-values {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-1);
}

.list-value {
    padding: 0.15rem 0.5rem;
    border: 1px solid var(--color-border-strong);
    border-radius: 999px;
    color: var(--color-text-muted);
    font-size: calc(0.78rem * var(--ui-fs-small));
    white-space: nowrap;
}

.list-empty-value {
    color: var(--color-text-faint);
}

.list-row-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2);
}

/* Rechtsbündige Aktionsgruppe am Zeilenende (z. B. Speichern/Abbrechen der
Inline-Eingabezeile in der Vorgänge-Tabelle der Objektakte). */
.list-row-actions-end {
    justify-content: flex-end;
}

.list-row-actions form {
    margin: 0;
}


.list-empty-message {
    padding: var(--space-4);
    border: 1px dashed var(--color-border-strong);
    border-radius: var(--radius-md);
    background-color: var(--color-surface);
    color: var(--color-text-muted);
}

.list-empty-message-with-action {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: var(--space-3);
}

/* Objektakte */

.object-details {
    max-width: 28rem;
}

.object-details dt {
    color: var(--color-text-faint);
    font-size: calc(0.8rem * var(--ui-fs-secondary));
    font-weight: var(--ui-fw-medium);
    text-transform: uppercase;
    letter-spacing: 0.03em;
    margin-top: var(--space-3);
}

.object-details dt:first-child {
    margin-top: 0;
}

.object-details dd {
    margin: var(--space-1) 0 0;
    font-size: calc(0.98rem * var(--ui-fs-body));
}

button.button-danger {
    border-color: var(--color-danger-border);
    background-color: var(--color-danger-solid);
    color: #fff;
}

button.button-danger:hover {
    border-color: var(--color-danger-border);
    background-color: var(--color-danger-solid-hover);
    color: #fff;
}

/* Generischer Desktop-Dialog. Fachliche Inhalte werden serverseitig als Partial
eingesetzt; die Hülle bleibt für Objekte, Vorgänge und spätere Bereiche identisch. */
.app-modal {
    width: min(68rem, calc(100vw - 2rem));
    max-width: none;
    max-height: calc(100vh - 2rem);
    padding: 0;
    overflow: hidden;
    border: 1px solid var(--color-border-strong);
    border-radius: var(--radius-lg);
    background: var(--color-surface-raised);
    color: var(--color-text);
    box-shadow: var(--shadow-card);
}

.app-modal::backdrop {
    background: rgba(4, 8, 15, 0.72);
}

.app-modal-panel {
    display: flex;
    flex-direction: column;
    max-height: calc(100vh - 2rem);
}

.app-modal-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    padding: var(--space-3) var(--space-4);
    border-bottom: 1px solid var(--color-border);
}

.app-modal-header h2 {
    min-width: 0;
    margin: 0;
    font-size: calc(1.05rem * var(--ui-fs-heading));
    overflow-wrap: anywhere;
}

.app-modal-close {
    width: 2rem;
    height: 2rem;
}

.app-modal-body {
    min-height: 0;
    overflow: auto;
    padding: var(--space-4);
}

.app-modal-body .object-akte-grid {
    margin-bottom: var(--card-gap);
}

.app-modal-body .form-actions {
    position: sticky;
    bottom: calc(var(--space-4) * -1);
    margin: 0 calc(var(--space-4) * -1) calc(var(--space-4) * -1);
    padding: var(--space-3) var(--space-4);
    border-top: 1px solid var(--color-border);
    background: var(--color-surface-raised);
}

/* Zweispaltige Dialog-Layouts (Dokument bearbeiten/hochladen): dort liegt die
   Aktionsleiste innerhalb der linken Rasterspalte – die Seiten-Überhänge des
   einspaltigen Standards würden mit ihrer Kante und dem erhöhten Hintergrund
   die Ränder der Nachbarkarte kreuzen (optisches Artefakt am Dialogfuß).
   Auch die Trennlinie oben entfällt: Sie läge sonst als freischwebende
   horizontale Linie unter der letzten Karte der Spalte; der Hintergrund
   bleibt (deckungsgleich mit dem Modal-Hintergrund) als Abdeckung beim
   Scrollen. */
.app-modal-body .object-akte-grid .form-actions {
    margin-left: 0;
    margin-right: 0;
    border-top: none;
}

.icon-button {
    display: inline-flex;
    flex-shrink: 0;
    align-items: center;
    justify-content: center;
    width: 2.25rem;
    height: 2.25rem;
    /* Feste quadratische Fläche für ALLE reinen Symbol-Buttons: <button>
       erbt sonst das breite Grund-Padding (button { padding: 0.55rem 1.1rem }),
       das die Fläche sprengt und das Symbol wegdrückt – bei <a>-Icon-Buttons
       fällt das nicht auf, bei <button>-Icon-Buttons schon. padding: 0 hier
       macht Anker-, Submit- und Button-Varianten einheitlich gleich groß. */
    padding: 0;
    border: 1px solid var(--color-border-strong);
    border-radius: var(--radius-sm);
    background-color: var(--color-surface);
    color: var(--color-text-muted);
    font-size: calc(1.1rem * var(--ui-fs-heading));
    line-height: 1;
    text-decoration: none;
    transition: border-color 0.15s ease, color 0.15s ease;
}

.icon-button:hover {
    border-color: var(--color-accent);
    color: var(--color-text);
    text-decoration: none;
}

/* Neutrale Icon-Buttons, die als echtes <button type="submit|button">
   eingesetzt werden (z. B. der Objektbild-Umschalter der Dokumententabelle):
   Ohne diese Regel setzen die button[type="…"]-Grundregeln (Spezifität
   0,1,1) eine Akzent- bzw. Transparenz-Fläche und überschreiben die neutrale
   .icon-button-Optik (0,1,0) – der Button erschien dadurch akzentblau
   gefüllt. Die Sonder-Varianten (-selected/-danger/-save) haben eigene,
   gleich spezifische Regeln weiter unten und gewinnen über die Quellreihenfolge. */
button[type="submit"].icon-button,
button[type="button"].icon-button {
    background-color: var(--color-surface);
    color: var(--color-text-muted);
    border-color: var(--color-border-strong);
}

/* Aktiver Zustand einer Icon-Schnellaktion (z. B. „Als Objektbild
   verwenden“ in der Dokumententabelle der Objektakte, ADR-037): subtil und
   MONOCHROM – gefülltes Symbol in normaler Textfarbe auf gedrückt wirkendem
   Grund (Inset-Schatten), keine Akzentfarbe. Die button[type="…"]-Selektoren
   sind nötig, damit der Zustand die neutrale button-Regel oben überstimmt. */
.icon-button-selected,
.icon-button-selected:hover,
button[type="submit"].icon-button-selected,
button[type="submit"].icon-button-selected:hover,
button[type="button"].icon-button-selected,
button[type="button"].icon-button-selected:hover {
    border-color: var(--color-border-strong);
    background-color: var(--color-surface-raised);
    color: var(--color-text);
    box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.35);
}

/* Gefährliche Aktionen (Löschen/Entfernen) als Icon-Button statt Textbutton,
   projektweit einheitlich: durchgehend roter Hintergrund (nicht erst bei
   Hover) mit weißem Symbol, damit die Gefahr sofort erkennbar ist, nicht
   erst nach Mauskontakt. Tooltip/aria-label tragen weiterhin die textuelle
   Bedeutung. */
.icon-button-danger {
    position: relative;
    border-color: var(--color-danger-border);
    background-color: var(--color-danger-solid);
    color: transparent;
}

.icon-button-danger:hover {
    background-color: var(--color-danger-solid-hover);
    border-color: var(--color-danger-border);
    color: transparent;
}

/* Löschen/Entfernen zeigen global ein weißes Mülltonnensymbol auf rotem Grund
   (PO-Entscheidung 2026-07-06; ersetzt das frühere weiße ✕). Das ✕ bleibt als
   Textinhalt im Button, wird aber unsichtbar geschaltet (color: transparent);
   das Symbol kommt als zentrierte, weiß eingefärbte Maske und skaliert über die
   prozentuale Maskengröße mit der Buttongröße mit (auch die kleineren
   Danger-Buttons im Eigenschaften-Raster). Tooltip/aria-label tragen weiterhin
   die textuelle Bedeutung. */
.icon-button-danger::before {
    content: "";
    position: absolute;
    inset: 0;
    background-color: #fff;
    -webkit-mask: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%3E%3Cpath%20fill='%23fff'%20d='M6%2019a2%202%200%200%200%202%202h8a2%202%200%200%200%202-2V7H6v12zM19%204h-3.5l-1-1h-5l-1%201H5v2h14V4z'/%3E%3C/svg%3E") center / 58% no-repeat;
    mask: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%3E%3Cpath%20fill='%23fff'%20d='M6%2019a2%202%200%200%200%202%202h8a2%202%200%200%200%202-2V7H6v12zM19%204h-3.5l-1-1h-5l-1%201H5v2h14V4z'/%3E%3C/svg%3E") center / 58% no-repeat;
}

button[type="submit"].icon-button-danger,
button[type="button"].icon-button-danger {
    background-color: var(--color-danger-solid);
    /* Das ✕ auch bei <button type="…"> unsichtbar halten: die breiten
       button[type="…"]-Grundregeln (Spezifität 0,1,1) setzen sonst wieder eine
       sichtbare Textfarbe und schlagen das .icon-button-danger (0,1,0). Nur das
       Mülltonnen-Symbol (::before) bleibt sichtbar. */
    color: transparent;
}

button[type="submit"].icon-button-danger:hover,
button[type="button"].icon-button-danger:hover {
    background-color: var(--color-danger-solid-hover);
    color: transparent;
}

/* Modal-Trigger und andere Icon-Buttons sind teils <button type="button">
(z. B. für hx-get-Auslöser), teils <a> (reine Navigation). Die generische
button[type="button"]-Grundregel hat dieselbe Spezifität wie .icon-button und
würde ohne diese präzisere Regel den Hintergrund auf "transparent" statt der
Icon-Button-Oberfläche zurücksetzen. */
/* :not(.icon-button-danger): Lösch-/Entfernen-Buttons behalten ihren
dauerhaften roten Hintergrund (docs/13, „Buttons“) – ohne die Ausnahme
gewänne diese spätere Regel gleicher Spezifität und übermalte die
button[type="button"]-Löschbuttons (z. B. Eigenschaft entfernen im
Objekt-Editor, Ereignis löschen) grau. */
button[type="button"].icon-button:not(.icon-button-danger) {
    background-color: var(--color-surface);
}

.object-overview-table {
    min-width: 0;
    width: 100%;
}

.object-facts {
    margin: 0;
}

.object-facts > div {
    display: grid;
    grid-template-columns: minmax(7rem, 0.8fr) minmax(0, 1.2fr);
    gap: var(--space-3);
    padding: var(--space-2) var(--space-3);
    border-bottom: 1px solid var(--color-border);
}

.object-facts > div:last-child {
    border-bottom: 0;
}

.object-facts dt {
    color: var(--color-text);
    font-weight: var(--ui-fw-semibold);
}

.object-facts dd {
    min-width: 0;
    margin: 0;
    overflow-wrap: anywhere;
}

/* Mehrspaltige Variante der Faktenliste für vollbreite Karten (Objektdaten,
Fortschritt & Wartung in der Objektakte): die Begriff/Wert-Zeilen fließen in so
viele Spalten, wie die Desktopbreite hergibt, statt als schmale Einzelspalte
große Leerflächen zu lassen. Einheitliche Trennlinien unter allen Zeilen, da es
in einem mehrspaltigen Raster keine eindeutige „letzte Zeile“ gibt. */
.object-facts-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(24rem, 1fr));
    column-gap: var(--space-4);
    /* stretch statt start: Einträge derselben Rasterzeile sind gleich hoch,
       ihre Trennstriche (border-bottom) fluchten damit spaltenübergreifend –
       auch wenn ein Wert mehrzeilig umbricht. */
    align-items: stretch;
}

.object-facts-grid > div,
.object-facts-grid > div:last-child {
    border-bottom: 1px solid var(--color-border);
}

/* Vertikaler Stapel der Objektakte-Karten: der Container liefert den einheitlichen
Design-Standardabstand zwischen den Karten und ist zugleich die per Drag
umsortierbare Liste (data-reorderable-list mit data-reorder-axis="y" und dem
Kartenkopf als Handle, siehe reorderable-list.js). */
.object-akte-sections {
    display: flex;
    flex-direction: column;
    gap: var(--card-gap);
}

/* Im Stapel liefert ausschließlich das Flex-Gap den Abstand – der
   Außenabstand der Karte würde sich sonst dazu addieren (Doppelabstand,
   z. B. Dashboard doppelt so weit wie die Einstellungs-Karten). */
.object-akte-sections > .object-akte {
    margin-bottom: 0;
}

/* Generische, schreibgeschützte Zeitleiste (app/templates/partials/timeline.html):
fachbereichsunabhängig, aktuell für die Vorgangshistorie genutzt, aber ohne
Sonderlösung auch für künftige Chroniken (Objekte, Dokumente, Wartungen)
wiederverwendbar. */
.timeline {
    margin: 0;
    padding: 0;
    list-style: none;
}

.timeline-entry {
    display: grid;
    grid-template-columns: minmax(8rem, 0.6fr) minmax(0, 1.4fr);
    gap: var(--space-3);
    padding: var(--space-2) var(--space-3);
    border-bottom: 1px solid var(--color-border);
}

.timeline-entry:last-child {
    border-bottom: 0;
}

.timeline-time {
    color: var(--color-text-muted);
    font-size: calc(0.85rem * var(--ui-fs-secondary));
    white-space: nowrap;
}

.timeline-title {
    color: var(--color-text);
    font-weight: var(--ui-fw-semibold);
}

.timeline-description {
    margin: var(--space-1) 0 0;
    color: var(--color-text-muted);
    overflow-wrap: anywhere;
    /* Zeilenumbrüche und Leerzeilen langer Texte erhalten (Kommentare,
       Historie, Ereignisse). */
    white-space: pre-line;
}

.object-akte-page {
    max-width: 96rem;
    margin: 0 auto;
}

/* Akten (Objekt, Vorgang, Maßnahmenplan) nutzen die volle Listenbreite
   (identisch zu .app-main), damit Desktop möglichst viele Informationen
   gleichzeitig zeigt; Formulare behalten die kompaktere Standardbreite,
   da ihre Feldbreiten ohnehin begrenzt sind (siehe docs/13_design_system.md,
   „Seitenbreiten“). */
.object-akte-page-wide {
    max-width: 160rem;
}

.object-akte-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--card-gap);
    margin-bottom: var(--card-gap);
}

.object-akte {
    min-width: 0;
    margin-bottom: var(--card-gap);
    background-color: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-card);
    padding: var(--space-3);
}

.object-akte-grid .object-akte {
    margin-bottom: 0;
}

.object-akte h3 {
    margin: 0;
    font-size: calc(0.95rem * var(--ui-fs-body));
}

.object-akte-section-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    margin-bottom: var(--space-2);
}

/* Kompaktere Variante für Icon-Aktionen in dichten Kontexten (Objektakte-Kopf,
Tabellenzeilen wie „Bearbeiten“ in den Stammdatenlisten) – überall dieselbe Größe. */
.object-akte-section-header .icon-button,
.list-row-actions .icon-button {
    width: 1.9rem;
    height: 1.9rem;
    font-size: calc(1rem * var(--ui-fs-body));
}

/* Der Speichern-Button (button[type=submit].icon-button-save) erzwingt sonst
   seine eigene, größere Formularfuß-Größe (2.25rem, Spezifität 0,2,1) und wäre
   in der Aktionszelle größer als Abbrechen/Löschen. In der kompakten
   Tabellenzeile bekommt er dieselbe Größe wie die übrigen Aktions-Icons
   (PO-Meldung 2026-07-28, Ticket 56). */
.list-row-actions button[type="submit"].icon-button-save {
    width: 1.9rem;
    height: 1.9rem;
}

/* Filter-Selects direkt im Kartenkopf (statt einer eigenen Toolbar-Zeile über
der Tabelle, platzsparend z. B. im Vorgänge-Bereich der Objektakte): gleiche
Designsprache wie .list-toolbar select, aber auf die kompakte Höhe der
Kartenkopf-Icon-Buttons gebracht. */
.object-akte-section-header select {
    height: 1.9rem;
    min-width: 8rem;
    padding: 0 var(--space-2);
    border: 1px solid var(--color-border-strong);
    border-radius: var(--radius-sm);
    background-color: var(--color-surface);
    color: var(--color-text);
    font: inherit;
    font-size: calc(0.85rem * var(--ui-fs-secondary));
}

.object-akte-section-header select:focus {
    outline: none;
    border-color: var(--color-accent);
    box-shadow: 0 0 0 3px rgba(110, 168, 254, 0.2);
}

.object-akte .list-table th,
.object-akte .list-table td {
    padding: var(--space-2) var(--space-3);
}

/* Kein zweiter, verschachtelter Kartenrahmen um Tabellen innerhalb der ohnehin
schon als Karte gestalteten Objektakte-Sektion – ruhigeres, flacheres Layout. */
.object-akte .list-table-wrapper {
    background: none;
    border: none;
    box-shadow: none;
    border-radius: 0;
}

.object-akte .list-empty-value {
    display: block;
    padding: var(--space-2) 0;
}

.object-akte-children {
    width: 100%;
    margin-bottom: 0;
}

@media (max-width: 48rem) {
    .object-akte-grid {
        grid-template-columns: 1fr;
    }
}

/* Objektübersicht */

.object-class-tabs {
    display: flex;
    align-items: flex-end;
    /* Reicht die Breite nicht, brechen die Reiter zuerst in eine zweite
    Zeile um; erst wenn auch zwei Zeilen nicht reichen, wird die Leiste
    vertikal scrollbar (max-height ≈ zwei Reiterzeilen, die dann anteilig
    sichtbare dritte Zeile ist der Scroll-Hinweis) – statt sofort
    horizontal zu scrollen. */
    flex-wrap: wrap;
    overflow-x: auto;
    overflow-y: auto;
    min-height: 2.45rem;
    max-height: 5.5rem;
    gap: var(--space-1);
    border-bottom: 1px solid var(--color-border);
    /* Gleicht den 1px-Überhang der Reiter-Unterstreichung (margin-bottom:
    -1px am .object-class-tab) aus – ohne ihn meldet die Leiste bei
    overflow-y: auto dauerhaft 1px Scroll-Überstand (Phantom-Scrollbar);
    zuvor hat overflow-y: hidden denselben Pixel einfach abgeschnitten. */
    padding-bottom: 1px;
    margin-bottom: var(--card-gap);
}

.object-class-tab {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    flex-shrink: 0;
    padding: var(--space-2) var(--space-4);
    border: none;
    background: none;
    color: var(--color-text-muted);
    text-decoration: none;
    font-family: inherit;
    font-weight: var(--ui-fw-medium);
    font-size: calc(0.9rem * var(--ui-fs-secondary));
    white-space: nowrap;
    border-bottom: 2px solid transparent;
    margin-bottom: -1px;
    cursor: pointer;
    transition: color 0.15s ease, border-color 0.15s ease, background-color 0.15s ease;
}

.object-class-tab:hover {
    color: var(--color-text);
}

.object-class-tab-count {
    padding: 0.05rem 0.45rem;
    border-radius: 999px;
    background-color: var(--color-surface-raised);
    color: var(--color-text-faint);
    font-size: calc(0.75rem * var(--ui-fs-small));
    font-weight: var(--ui-fw-semibold);
}

.object-class-tab-empty {
    color: var(--color-text-faint);
}

.object-class-tab-empty .object-class-tab-count {
    background: none;
}

.object-class-tab-active {
    color: var(--color-text);
    background-color: var(--color-surface-raised);
    border-bottom-color: var(--color-accent);
    border-top-left-radius: var(--radius-sm);
    border-top-right-radius: var(--radius-sm);
}

.object-class-tab-active .object-class-tab-count {
    background-color: rgba(110, 168, 254, 0.16);
    color: var(--color-accent);
}

/* Objekttyp-Reiter unter den Objektklassen-Reitern: dieselbe Komponente
   (.object-class-tabs/.object-class-tab), nur kompakter/gedämpfter als
   sekundäre Ebene – keine eigenständige, abweichend gestaltete Tab-Komponente. */
.object-class-tabs + .object-class-tabs-secondary {
    /* Zieht die Sekundärleiste bis auf einen festen Restabstand an die
       Primärleiste heran – gekoppelt an den skalierbaren Kartenabstand,
       damit der Zwischenraum bei jeder Reglerstellung gleich bleibt. */
    margin-top: calc(0.25rem - var(--card-gap));
}

.object-class-tabs-secondary {
    min-height: 2.1rem;
    /* Kompaktere Reiter → niedrigere Zwei-Zeilen-Grenze (siehe
    .object-class-tabs). */
    max-height: 4.2rem;
    margin-bottom: var(--card-gap);
}

.object-class-tabs-secondary .object-class-tab {
    padding: var(--space-1) var(--space-3);
    font-size: calc(0.82rem * var(--ui-fs-secondary));
    color: var(--color-text-faint);
}

.object-class-tabs-secondary .object-class-tab:hover {
    color: var(--color-text-muted);
}

.object-class-tabs-secondary .object-class-tab-active {
    color: var(--color-text);
}

/* Tab-Reiter als <button> (z. B. Ereignisse/Historie in der Vorgangsakte):
exakt dieselbe Optik wie die Link-Reiter. Die globalen Button-Regeln
(button[type="button"]: Rahmenfarbe, Hover-Akzentrahmen, Radius) haben höhere
Spezifität als .object-class-tab und würden die Tab-Komponente sonst sichtbar
verändern – deshalb hier gleichrangige, später definierte Regeln. */
button.object-class-tab {
    border: none;
    border-bottom: 2px solid transparent;
    border-radius: 0;
    background: none;
    color: var(--color-text-muted);
    font-weight: var(--ui-fw-medium);
}

button.object-class-tab:hover {
    color: var(--color-text);
    border-color: transparent;
    background: none;
}

button.object-class-tab.object-class-tab-active {
    color: var(--color-text);
    background-color: var(--color-surface-raised);
    border-bottom-color: var(--color-accent);
    border-radius: var(--radius-sm) var(--radius-sm) 0 0;
}

button.object-class-tab.object-class-tab-active:hover {
    border-bottom-color: var(--color-accent);
}

/* ============================================================
   Fable-Sprint-4-Layout: generische Bausteine für Akten- und
   Fälligkeitsseiten (verbindlicher Standard, siehe
   docs/13_design_system.md „Akten-Anatomie“/„Aktenkopf“).
   ============================================================ */

/* Aktenkopf (Page Hero): Titel und Badge-Zeile links, Aktionen rechts. */
.akte-hero {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--space-3);
    margin-bottom: var(--card-gap);
}

/* Objektbezeichnung im Vorgangsakten-Titel: verlinkt zur Objektakte und ist
   dauerhaft als Link erkennbar (Akzentfarbe + Unterstreichung), damit sofort
   klar ist, dass ein Klick zur Objektakte führt. */
.akte-hero-object-link {
    color: var(--color-accent);
    text-decoration: underline;
}

.akte-hero-object-link:hover,
.akte-hero-object-link:focus-visible {
    color: var(--color-accent-strong);
    text-decoration: underline;
}

.akte-hero-main {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2) var(--space-3);
    /* flex-basis 0 (nicht auto): Das Item wächst aus 0 in den freien Platz,
       statt seine (große) Inhaltsbreite als Basis zu nehmen. Mit Basis „auto“
       entsteht bei breitem Inhalt negativer Freiraum, und das Item schrumpft –
       Firefox/Safari bis auf Minimalbreite, sodass die Titel-Breadcrumb
       Segment für Segment vertikal umbricht (Ticket 42/43). Mit „0“ bekommt
       der Kopf zuverlässig die verfügbare Breite und die Kette steht
       horizontal. */
    flex: 1 1 0;
    min-width: 0;
}

.akte-hero-main h2 {
    margin: 0;
    /* Kein „overflow-wrap: anywhere“: Das erlaubt Umbrüche an JEDER Stelle und
       drückt die Mindestbreite des h2 auf ~1 Zeichen – der eigentliche Treiber
       des vertikalen Umbruchs (Ticket 43). Lange, umbruchlose Namen sind bei
       fachlichen Objekt-/Vorgangsbezeichnungen die Ausnahme. */
    overflow-wrap: normal;
}

/* Titel-Breadcrumb der Objektakte (Ticket 42/43): Die Segmente (Namen) bleiben
   ganz und stehen horizontal nebeneinander; die Kette darf – wenn nötig – nur
   zwischen Segmenten als Zeile umbrechen, nie mitten im Wort und nicht Segment
   für Segment untereinander. */
.akte-hero-main h2 .breadcrumbs a,
.akte-hero-main h2 .breadcrumbs .breadcrumb-current {
    overflow-wrap: normal;
    word-break: keep-all;
}

.akte-hero-badges {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2);
}

.akte-hero-actions {
    display: flex;
    flex-shrink: 0;
    gap: var(--space-2);
}

/* Interaktive Status-/Prioritätsauswahl im Aktenkopf: kompakt wie ein Badge,
   nicht wie ein Formularfeld in voller Breite. */
.akte-hero .colored-select {
    display: inline-flex;
}

/* Generisches Akten-Overlay (Drawer) innerhalb einer Liste: ersetzt Toolbar/Tabelle
im selben Bereich durch eine vollbreite eingebettete Akte statt eines kleinen
zentrierten Dialogs (.app-modal). Aktivierung ausschließlich per Markup
(data-drawer-root/-list-body/-panel/-open/-close), siehe app/static/js/record-drawer.js;
heute für die Objektakte genutzt, ohne Anpassung auch für künftige Aktentypen nutzbar. */
.record-drawer-root[hidden] {
    display: none;
}

/* Die Aktionsleiste (Bearbeiten/Schließen) schwebt oben rechts über dem
Akteninhalt statt eine eigene Zeile zu belegen – so beginnt der Aktenkopf
(Objektname) direkt unter den Reitern auf derselben Höhe wie die Buttons. */
.record-drawer {
    position: relative;
}

.record-drawer-bar {
    position: absolute;
    top: 0;
    right: 0;
    display: flex;
    align-items: center;
    gap: var(--space-2);
}

/* Das Panel erhält beim Öffnen programmatisch den Fokus (record-drawer.js),
damit kein interaktives Element sichtbar „vorausgewählt“ wirkt; der
Browser-Fokusrahmen um das gesamte Overlay bleibt dabei unterdrückt. */
.record-drawer:focus {
    outline: none;
}

/* Die Objektakte innerhalb des Overlays zeigt „Bearbeiten“ bereits in der
   Aktionsleiste oben (.record-drawer-bar); der doppelte Aktions-Link im
   eingebetteten Aktenkopf entfiele sonst als überflüssiger zweiter Button.
   Auch die Objektklassen-/Objekttyp-Badges (Links) des Aktenkopfs sind im
   Overlay redundant, da dieselbe Information direkt darüber als aktive Reiter
   sichtbar und navigierbar ist. Der schaltbare Objektstatus (.colored-select,
   ADR-020) steckt dagegen nur im Aktenkopf und bleibt deshalb sichtbar. */
.record-drawer .akte-hero-actions,
.record-drawer .akte-hero-badges a.colored-badge {
    display: none;
}

/* Platz für die schwebende Aktionsleiste rechts, damit sehr lange Objektnamen
nicht unter die Buttons laufen. */
.record-drawer .akte-hero {
    padding-right: 7rem;
}

/* Dreispaltiges Kartenraster oberhalb der Verlaufsbereiche. Die Karten
   selbst sind gewöhnliche .object-akte-Karten – kein paralleles Kartenmuster. */
.akte-card-grid {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--card-gap);
    margin-bottom: var(--card-gap);
}

/* Liegt das Kartenraster im gemeinsamen vertikalen Karten-Container einer
Akte (verschiebbarer Block, Vorgangsakte), liefert dessen Flex-Gap den
Abstand – kein zusätzlicher Außenabstand. */
.object-akte-sections > .akte-card-grid {
    margin-bottom: 0;
}

.akte-card-grid .object-akte {
    margin-bottom: 0;
}

@media (max-width: 1100px) {
    .akte-card-grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

@media (max-width: 720px) {
    .akte-card-grid {
        grid-template-columns: 1fr;
    }
}

/* KPI-Karten: kompakte Kennzahlenkacheln (Label oben, große Zahl darunter),
   z. B. Kopf der globalen Fälligkeitenliste. Farbvarianten nutzen die
   bestehenden semantischen Flächenfarben. */
.kpi-cards {
    display: grid;
    grid-template-columns: repeat(5, minmax(0, 1fr));
    gap: var(--card-gap);
    margin-bottom: var(--card-gap);
}

.kpi-card {
    display: flex;
    align-items: baseline;
    gap: var(--space-2);
    padding: var(--space-2) var(--space-3);
    background-color: var(--color-surface-raised);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
}

.kpi-card-label {
    font-size: calc(0.75rem * var(--ui-fs-small));
    color: var(--color-text-muted);
}

.kpi-card-value {
    margin-left: auto;
    font-size: calc(1rem * var(--ui-fs-body));
    font-weight: var(--ui-fw-semibold);
    line-height: 1.2;
}

.kpi-card-danger {
    background-color: var(--color-danger-bg);
    border-color: var(--color-danger-border);
}

.kpi-card-danger .kpi-card-label,
.kpi-card-danger .kpi-card-value {
    color: var(--color-danger-text);
}

.kpi-card-warning {
    background-color: var(--color-warning-bg);
    border-color: #6a4a1a;
}

.kpi-card-warning .kpi-card-label,
.kpi-card-warning .kpi-card-value {
    color: var(--color-warning-text);
}

.kpi-card-accent {
    background-color: var(--color-accent-bg);
    border-color: #27446b;
}

.kpi-card-accent .kpi-card-label,
.kpi-card-accent .kpi-card-value {
    color: var(--color-accent);
}

.kpi-card-success {
    background-color: var(--color-success-bg);
    border-color: #2c5a3e;
}

.kpi-card-success .kpi-card-label,
.kpi-card-success .kpi-card-value {
    color: var(--color-success-text);
}

@media (max-width: 1100px) {
    .kpi-cards {
        grid-template-columns: repeat(3, minmax(0, 1fr));
    }
}

@media (max-width: 640px) {
    .kpi-cards {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    /* Objektliste auf schmalen Handy-Bildschirmen (Ticket 35, PO 2026-07-26):
       Die Objekttabelle trägt je nach Auflösungsprofil bis zu acht Spalten;
       selbst maximal geschrumpft (Mindestbreite je Spalte) überschreitet sie
       die Handybreite, sodass man seitlich aus dem Bild scrollen muss. Unter
       640px werden deshalb nur die Kernspalten Bild, Bezeichnung und Typ
       gezeigt; alle übrigen Spalten (Markieren, Einordnung, Übergeordnet,
       Offene Störungen, Untergeordnet sowie eingeblendete Zustands-/
       Eigenschaftsspalten) werden ausgeblendet. Die feste Breite und die
       Spaltenbreiten des Fit-Modus (data-table.js setzt sie inline) werden
       zugunsten einer gleichmäßigen Aufteilung über die volle Breite außer
       Kraft gesetzt, damit die Tabelle ohne Seitwärtsscrollen passt. Nur die
       Objektliste ist betroffen (eigene Spaltenschlüssel). */
    #technical-objects-table {
        width: 100% !important;
        min-width: 0 !important;
        table-layout: fixed !important;
    }

    #technical-objects-table col[data-column-key="image"] {
        width: 64px !important;
    }

    #technical-objects-table col[data-column-key="name"],
    #technical-objects-table col[data-column-key="object-type"] {
        width: auto !important;
    }

    #technical-objects-table thead th[data-column-key]:not([data-column-key="image"]):not([data-column-key="name"]):not([data-column-key="object-type"]),
    #technical-objects-table tbody th[data-column-key]:not([data-column-key="image"]):not([data-column-key="name"]):not([data-column-key="object-type"]),
    #technical-objects-table tbody td[data-column-key]:not([data-column-key="image"]):not([data-column-key="name"]):not([data-column-key="object-type"]),
    #technical-objects-table colgroup col[data-column-key]:not([data-column-key="image"]):not([data-column-key="name"]):not([data-column-key="object-type"]) {
        display: none !important;
    }
}

/* Monatskalender (Kalendergrundlage für Fälligkeiten, S4-04): serverseitig
   gerendertes 7-Spalten-Raster mit vollständigen Kalenderwochen. Einträge sind
   Links auf den jeweiligen Maßnahmenplan; ihre Kennfarbe (--urgency-color)
   stammt ausschließlich aus dem Dringlichkeitssystem (urgency_color-Makro,
   dieselbe Quelle wie urgency_badge – keine eigene Farblogik). */
.calendar-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    margin-bottom: var(--space-3);
}

.calendar-title {
    margin: 0;
    font-size: calc(1.1rem * var(--ui-fs-heading));
}

.calendar-nav {
    display: flex;
    align-items: center;
    gap: var(--space-2);
}

/* Samstag und Sonntag halb so breit wie die Werktage (PO 2026-07-21): An
   Wochenenden stehen selten Termine an, die fünf Werktage brauchen den Platz
   für Objekt- und Unternehmensnamen. Fünf volle plus zwei halbe Spalten
   ergeben rechnerisch sechs Anteile – jeder Werktag gewinnt damit rund ein
   Sechstel Breite. */
.calendar {
    display: grid;
    grid-template-columns: repeat(5, minmax(0, 2fr)) repeat(2, minmax(0, 1fr));
    gap: 1px;
    background-color: var(--color-border);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);
    overflow: hidden;
}

.calendar-weekday {
    padding: var(--space-2) var(--space-3);
    background-color: var(--color-surface-raised);
    color: var(--color-text-muted);
    font-size: calc(0.75rem * var(--ui-fs-small));
    font-weight: var(--ui-fw-semibold);
    text-transform: uppercase;
    letter-spacing: 0.04em;
}

.calendar-day {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
    min-height: 7rem;
    padding: var(--space-2);
    background-color: var(--color-surface);
}

.calendar-day-outside {
    background-color: var(--color-bg);
}

.calendar-day-outside .calendar-day-number {
    color: var(--color-text-faint);
}

.calendar-day-number {
    font-size: calc(0.8rem * var(--ui-fs-secondary));
    color: var(--color-text-muted);
}

.calendar-day-today {
    box-shadow: inset 0 0 0 2px var(--color-accent);
}

.calendar-day-today .calendar-day-number {
    color: var(--color-accent);
    font-weight: var(--ui-fw-strong);
}

.calendar-entry {
    display: block;
    padding: 0.15rem var(--space-2);
    border-left: 3px solid var(--urgency-color, var(--color-text-muted));
    border-radius: var(--radius-sm);
    background-color: var(--color-surface-raised);
    color: var(--color-text);
    font-size: calc(0.8rem * var(--ui-fs-secondary));
    text-decoration: none;
    /* Einträge brechen um statt abzuschneiden (PO 2026-07-17): der volle
       Ereignistext bleibt lesbar, lange Wörter brechen notfalls hart. */
    white-space: normal;
    overflow-wrap: anywhere;
}

.calendar-entry:hover {
    color: var(--color-accent);
}

/* Termine offener Vorgänge im Kalender: durchgehende Kante (PO 2026-07-21),
   Farbe aus dem Dringlichkeitssystem.

   Vier Zeilen (Ticket 48): Objekt, Vorgangsname, erster Satz des Ereignisses,
   beteiligte Unternehmen. Jede Zeile ein Block – so stehen sie sicher
   untereinander, unabhängig von der Zellenbreite. Erster Satz und Unternehmen
   sind optisch zurückgenommen, damit Objekt und Vorgang führen. */
.calendar-entry-work-order {
    display: block;
}

.calendar-entry-line {
    display: block;
}

/* Objekt führt den Eintrag an – fett hervorgehoben (PO 2026-07-27). */
.calendar-entry-object {
    font-weight: var(--ui-fw-strong);
}

.calendar-entry-satz,
.calendar-entry-company {
    color: var(--color-text-muted);
}

/* Beteiligtes Unternehmen kursiv (PO 2026-07-27). */
.calendar-entry-company {
    font-style: italic;
}

/* Kalender-Toggle-Button in der Aktionsspalte der Ereignisliste (PO
   2026-07-17): gedrückt = Akzentfarbe, das Ereignis erscheint im
   Monatskalender und auf dem Dashboard. */
/* Ereignis steht im Kalender: deutlich farbig markiert (PO 2026-07-21).
   Der Selektor ist absichtlich so lang: Die Klasse allein (0-1-0) unterlag
   sowohl button[type="button"] (0-1-1) als auch der Icon-Button-Grundregel
   button[type="button"].icon-button (0-2-1), die beide den Text gedämpft
   färben – der Aktiv-Stil war dadurch wirkungslos. Mit Typ-Attribut und
   beiden Klassen (0-3-1) gewinnt er eindeutig. */
button[type="button"].icon-button.event-calendar-button-active {
    color: var(--color-accent);
    border-color: var(--color-accent);
    background-color: var(--color-accent-bg);
}

/* Dokumente und Medien (Sprint 5): Vorschaubilder in Listen (verkleinerte
JPEG-Vorschau statt Originaldatei, siehe docs/05_architecture.md
„Performance“), größere Vorschau auf der Bearbeiten-Seite sowie dezente
Hinweise („warnen statt verbieten“, ADR-007). */
.document-thumb {
    display: block;
    /* Die Vorschaugröße (Tabelleneinstellungen, data-table-thumb-size →
    --table-thumb-size) regelt die HÖHE: alle Zeilen bleiben zunächst
    gleich hoch; die Breite folgt dem ursprünglichen Seitenverhältnis
    (kein Zuschnitt auf ein festes Format). */
    height: var(--table-thumb-size, 3.5rem);
    width: auto;
    border-radius: var(--radius-sm);
    border: 1px solid var(--color-border);
}

/* Vorschaubild als Link auf die Datei (gleiches Ziel wie der Dateiname):
kein zusätzlicher Baseline-Abstand, Fokus-/Hover-Zustand am Bildrahmen. */
.document-thumb-link {
    display: inline-block;
    line-height: 0;
    border-radius: var(--radius-sm);
}

/* Vorschau-/Bild-Spalten zentrieren ihren Inhalt (Thumbnail bzw. „–“).
   Der Thumbnail-Link ist inline-block → text-align zentriert ihn; das
   block-Bild darin zusätzlich über margin-inline: auto, damit es auch bei
   voller Spaltenbreite mittig sitzt. */
.list-table th.list-table-thumb,
.list-table td.list-table-thumb {
    text-align: center;
}

/* „Badges zentrieren“ (Ticket 54): je Tabelle im Spaltenmenü umschaltbar
   (Klasse data-table-badge-center, gesetzt von data-table.js). Zentriert nur
   Zellen, die einen farbigen Badge enthalten – der übrige Zelleninhalt bleibt
   linksbündig. :has() wird von den Zielbrowsern (Safari/Firefox aktuell)
   unterstützt. */
.list-table.data-table-badge-center td:has(.colored-badge) {
    text-align: center;
}

.list-table td.list-table-thumb .document-thumb {
    margin-inline: auto;
    /* In Tabellenzellen begrenzt sich das Bild selbst auf die Spaltenbreite
       (Seitenverhältnis bleibt erhalten, max-height statt fester Höhe).
       Wichtig, weil Bilder NACH dem Zellen-Fitting von data-table.js laden:
       die Transform-Skalierung griffe zu spät und bräche zudem die
       Zentrierung (transform-origin links) – Bildzellen sind dort
       ausgenommen. */
    height: auto;
    max-height: var(--table-thumb-size, 3.5rem);
    max-width: 100%;
}

/* Der Bild-Link füllt die Zelle als Block: verlässliche Bezugsbreite für
   max-width des Bilds (Safari löst %-max-width in shrink-to-fit-Containern
   sonst nicht auf) und Zentrierung über margin-inline des Bilds. */
.list-table td.list-table-thumb .document-thumb-link {
    display: block;
}

/* Mehrfachbearbeitung (Objektübersicht): schmale Auswahlspalte und die
   Aktionsleiste, die bei Auswahl über der Tabelle erscheint. */
.list-table th.list-table-select,
.list-table td.list-table-select {
    width: 2.2rem;
    text-align: center;
}

/* Die Aktionsleiste sitzt IN der Suchzeile (keine eigene Zeile, PO
   2026-07-16): als flexibles Toolbar-Element zwischen Suchfeld und
   +-Button; das Suchfeld schrumpft, solange die Leiste sichtbar ist.
   Bewusst OHNE eigenen Rahmen/Hintergrund (die frühere Akzent-Umrandung
   wirkte wie ein Fokusring) und ohne eigenes Padding – die Zeile behält
   beim Erscheinen exakt die Höhe des Suchfelds, nichts verschiebt sich. */
.bulk-edit-bar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2);
    flex: 1 1 auto;
    min-width: 0;
}

/* Alle Bedienelemente der Leiste in der einheitlichen Kontrollhöhe und
   Optik der übrigen Toolbar-Controls (Suchfeld, dynamische Comboboxen):
   gleiche Höhe, gleicher Rahmen, gleiche Schrift – Selects deckt bereits
   die .list-toolbar-Regel ab. */
.bulk-edit-bar input[type="text"],
.bulk-edit-bar .combobox input[type="text"] {
    height: var(--control-height);
    padding: 0 0.75rem;
    border: 1px solid var(--color-border-strong);
    border-radius: var(--radius-sm);
    background-color: var(--color-surface);
    color: var(--color-text);
    font: inherit;
    min-width: 0;
}

/* Das innere Combobox-Textfeld füllt seinen Wrapper; die direkten
   Textfelder (Eigenschaft/Wert) teilen sich den Platz flexibel. */
.bulk-edit-bar .combobox input[type="text"] {
    width: 100%;
}

.bulk-edit-fields > input[type="text"] {
    flex: 1 1 9rem;
}

/* Checkbox-Option in der Aktionsleiste („auch als Objektbild“): einzeilig
   neben dem Dokument-Picker, in der Sekundärschrift der Leiste. */
.bulk-edit-checkbox {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    white-space: nowrap;
    font-size: calc(0.9rem * var(--ui-fs-secondary));
    color: var(--color-text-muted);
}

.bulk-edit-bar input[type="text"]:focus {
    outline: none;
    border-color: var(--color-accent);
    box-shadow: 0 0 0 3px rgba(110, 168, 254, 0.2);
}


/* Die Selects der Leiste dürfen unter die 12rem-Toolbar-Vorgabe schrumpfen,
   damit die Zeile einzeilig bleibt (nichts verschiebt sich); die Breite
   bestimmt der Inhalt bzw. der verfügbare Platz. */
.list-toolbar .bulk-edit-bar select {
    min-width: 0;
    flex: 0 1 auto;
}

.bulk-edit-fields .combobox {
    flex: 1 1 9rem;
    min-width: 0;
}

/* display:flex würde das hidden-Attribut überstimmen – ohne Auswahl bleibt
   die Leiste vollständig verborgen (die Suchzeile sieht aus wie zuvor). */
.bulk-edit-bar[hidden] {
    display: none;
}

.bulk-edit-count {
    font-weight: var(--ui-fw-semibold);
    white-space: nowrap;
}

.bulk-edit-fields {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2);
    flex: 1;
    min-width: 0;
}

/* display:flex würde das hidden-Attribut überstimmen – nicht aktive
   Aktions-Feldgruppen bleiben ausgeblendet. */
.bulk-edit-fields[hidden] {
    display: none;
}


.document-thumb-link:hover .document-thumb,
.document-thumb-link:focus-visible .document-thumb {
    border-color: var(--color-accent);
}

.document-thumb-link:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px rgba(110, 168, 254, 0.2);
}

/* Vorschauspalte der Ereignisliste: mehrere zugeordnete Dokumente stehen
neben-/untereinander (Thumbnails oder Dateiname-Links) und brechen um. */
.event-documents {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    /* Vorschau(en) horizontal in der Zelle zentrieren (PO-Meldung 2026-07-28,
       Ticket 52) – analog zur zentrierten Vorschauspalte (.list-table-thumb). */
    justify-content: center;
    gap: var(--space-2);
}

/* Dokument-Anhängen in der Ereignis-Schnellerfassung (Ticket 59): Büroklammer
   als Label (Optik wie .icon-button) über einem versteckten File-Input, mit
   Anzahl-Zähler. */
.event-doc-attach {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    height: 1.9rem;
    padding: 0 0.5rem;
    border: 1px solid var(--color-border-strong);
    border-radius: var(--radius-sm);
    color: var(--color-text-muted);
    cursor: pointer;
}

/* Das File-Input liegt als unsichtbares Overlay über dem gesamten Label und ist
   selbst die Tap-Fläche (Ticket 61): iOS Safari öffnet die Dateiauswahl bei
   einem display:none-Feld nicht und auch die Label-Assoziation ist dort
   unzuverlässig – ein sichtbar vorhandenes, nur transparentes Feld wird
   dagegen direkt ausgelöst. */
.event-doc-attach .visually-hidden-file {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    margin: 0;
    padding: 0;
    opacity: 0;
    cursor: pointer;
}

.event-doc-attach:hover,
.event-doc-attach.is-active {
    border-color: var(--color-accent);
    color: var(--color-text);
}

.event-doc-attach-count {
    font-size: calc(0.8rem * var(--ui-fs-secondary));
    font-weight: var(--ui-fw-semibold);
    color: var(--color-accent);
}

/* Vorschaugrößen-Regler in den Tabelleneinstellungen */
/* Filter-Sektion der Tabelleneinstellungen: nimmt den per Markup gelieferten
   [data-table-filters]-Container auf (data-table.js verschiebt ihn beim
   Aufbau ins Menü) – Controls gestapelt und auf Menübreite. */
.data-table-menu-filters {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    padding: var(--space-2) var(--space-3) var(--space-3);
    margin-bottom: var(--space-2);
    border-bottom: 1px solid var(--color-border);
}

.data-table-menu-filters-heading {
    font-size: calc(0.8rem * var(--ui-fs-secondary));
    font-weight: var(--ui-fw-semibold);
    color: var(--color-text-muted);
}

.data-table-menu-filters [data-table-filters],
.data-table-menu-filters .list-filter-bar {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: var(--space-2);
    margin: 0;
}

.data-table-menu-filters select,
.data-table-menu-filters input[type="date"] {
    width: 100%;
    min-width: 0;
    height: var(--control-height);
    padding: 0 0.75rem;
    border: 1px solid var(--color-border-strong);
    border-radius: var(--radius-sm);
    background-color: var(--color-surface);
    color: var(--color-text);
    font: inherit;
    font-size: calc(0.9rem * var(--ui-fs-secondary));
}

.data-table-menu-thumb-size {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
    padding: var(--space-2) var(--space-3);
    border-top: 1px solid var(--color-border);
}

.data-table-menu-thumb-size label {
    font-size: calc(0.8rem * var(--ui-fs-secondary));
    font-weight: var(--ui-fw-semibold);
    color: var(--color-text-muted);
}

.data-table-menu-thumb-size input[type="range"] {
    width: 100%;
}

/* Ansichts-Schalter in den Tabelleneinstellungen (data-table-view-toggle):
Haken + Beschriftung in einer Zeile. Der CSS-Vertrag des Schalters: innerhalb
eines [data-view-toggle-scope] sind [data-view-toggle-only]-Elemente nur mit
gesetztem Haken sichtbar, [data-view-toggle-off-only]-Elemente nur ohne. */
.data-table-menu-view-toggle {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-2) var(--space-3);
    border-top: 1px solid var(--color-border);
}

.data-table-menu-view-toggle label {
    font-size: calc(0.8rem * var(--ui-fs-secondary));
    font-weight: var(--ui-fw-semibold);
    color: var(--color-text-muted);
    cursor: pointer;
}

[data-view-toggle-scope]:not([data-view-toggle-on]) [data-view-toggle-only] {
    display: none;
}

[data-view-toggle-scope][data-view-toggle-on] [data-view-toggle-off-only] {
    display: none;
}

.document-preview {
    display: block;
    max-width: 24rem;
    max-height: 18rem;
    margin-top: var(--space-3);
    border-radius: var(--radius-md);
    border: 1px solid var(--color-border);
}

/* Vorschau in der rechten Karte des Bearbeiten-Dialogs: die zwei Dreh-Symbole
   flankieren die zentrierte, klickbare Vorschau links/rechts. */
.document-preview-row {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-3);
    margin-bottom: var(--space-3);
}

.document-preview-link {
    display: inline-flex;
}

.document-preview-link .document-preview {
    margin-top: 0;
}

.document-preview-link:hover .document-preview,
.document-preview-link:focus-visible .document-preview {
    border-color: var(--color-border-strong);
}

.document-preview-none {
    color: var(--color-text-muted);
}

/* Dreh-Symbole: reine Symbole ohne hervorgehobenen Hintergrund, etwas
   größer, links/rechts neben der Vorschau. */
.document-rotate-button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: var(--space-1);
    border: none;
    background: none;
    color: var(--color-text-muted);
    font-size: calc(2rem * var(--ui-fs-title));
    line-height: 1;
    cursor: pointer;
    transition: color 0.15s ease;
}

.document-rotate-button:hover,
.document-rotate-button:focus-visible {
    color: var(--color-text);
}

/* Dokument-Viewer-Popup: Werkzeugleiste oben, darunter die Anzeigefläche mit
   optionalen Blätter-Pfeilen. */
.document-viewer {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
}

/* Der Viewer-Container ist nur als Tastatur-/Vollbildziel fokussierbar
   (tabindex="-1"); ein Fokusrahmen um Bild/Fläche würde optisch stören. */
.document-viewer:focus,
.document-viewer:focus-visible {
    outline: none;
}

.document-viewer:fullscreen {
    padding: var(--space-4);
    background: var(--color-surface);
}

.document-viewer-toolbar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
}

.document-viewer-tool {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 2.25rem;
    height: 2.25rem;
    padding: 0 var(--space-2);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    background: var(--color-surface);
    color: var(--color-text-muted);
    font-size: calc(1.2rem * var(--ui-fs-heading));
    line-height: 1;
    text-decoration: none;
    cursor: pointer;
    transition: color 0.15s ease, border-color 0.15s ease;
}

.document-viewer-tool:hover,
.document-viewer-tool:focus-visible {
    color: var(--color-text);
    border-color: var(--color-border-strong);
}

.document-viewer-tool-sep {
    width: 1px;
    height: 1.5rem;
    background: var(--color-border);
}

.document-viewer-body {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: min(70vh, 40rem);
}

.document-viewer:fullscreen .document-viewer-body {
    flex: 1;
}

.document-viewer-stage {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    /* Mindesthöhe vom Viewer-Body erben: solange das Medium lädt, hätte die
       Fläche sonst keine Höhe und das eigene overflow: auto würde die
       absolut zentrierte Lade-Sanduhr wegclippen (sie wäre nie sichtbar). */
    min-height: inherit;
    max-height: calc(100vh - 12rem);
    overflow: auto;
}

/* Sanduhr, solange Bild/PDF der Anzeigefläche noch lädt (dieselbe monochrome
   Strich-SVG wie der Formular-Indikator); document-viewer.js setzt
   data-loaded am Stage-Container, sobald das Medium fertig (oder
   fehlgeschlagen) ist. */
.document-viewer-loading {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    color: var(--color-text-muted);
    animation: request-indicator-pulse 1.2s ease-in-out infinite;
    pointer-events: none;
}

.document-viewer-loading svg {
    display: block;
    width: 2.5rem;
    height: 2.5rem;
}

.document-viewer-stage[data-loaded] .document-viewer-loading {
    display: none;
}

.document-viewer:fullscreen .document-viewer-stage {
    max-height: none;
    height: 100%;
}

.document-viewer-stage img {
    max-width: 100%;
    max-height: calc(100vh - 12rem);
    border-radius: var(--radius-md);
    transform-origin: center center;
    transition: transform 0.1s ease;
}

.document-viewer-stage iframe {
    width: 100%;
    height: calc(100vh - 12rem);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    background: var(--color-surface);
}

.document-viewer-empty {
    color: var(--color-text-muted);
    text-align: center;
}

/* Große, klickbare Blätter-Pfeile über dem Dokument. */
.document-viewer-nav {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    display: flex;
    align-items: center;
    justify-content: center;
    width: 3rem;
    height: 3rem;
    padding: 0;
    font-size: calc(2.25rem * var(--ui-fs-title));
    line-height: 1;
    color: var(--color-text);
    background: var(--color-surface-raised);
    border: 1px solid var(--color-border-strong);
    border-radius: 50%;
    box-shadow: var(--shadow-card);
    cursor: pointer;
    z-index: 1;
}

.document-viewer-nav:hover {
    background: var(--color-surface);
}

/* Beim Drücken nur einfärben statt bewegen (PO 2026-07-20). Die globale
   Regel `button:active { transform: translateY(1px) }` ersetzt hier sonst die
   Zentrierung `translateY(-50%)`: Der Pfeil springt aus der Mitte an den
   oberen Rand – eine sehr starke Bewegung UND er rutscht unter dem Zeiger
   weg, sodass das mouseup daneben landet und gar kein Klick ausgelöst wird
   (kurze Klicks blätterten deshalb oft nicht). Das erneute Setzen von
   translateY(-50%) hält den Pfeil an Ort und Stelle. */
.document-viewer-nav:active {
    transform: translateY(-50%);
    background: var(--color-accent);
    color: var(--color-accent-contrast);
    border-color: var(--color-accent);
}

.document-viewer-prev {
    left: 0;
}

.document-viewer-next {
    right: 0;
}

.form-hint {
    color: var(--color-text-muted);
    font-size: calc(0.875rem * var(--ui-fs-secondary));
}

/* Schreibgeschützt angezeigter, vom Unternehmen geerbter „Eigenes
   Unternehmen“-Status einer Person (Ticket 62): Wert plus leiser Hinweis. */
.contact-inherited-flag {
    display: inline-flex;
    align-items: baseline;
    gap: var(--space-2);
}

/* Kennzeichnung eines Maßnahmenplans, der zu einem Unterobjekt gehört
   (Rollup in der Karte „Wartung & Prüfungen“, Ticket 71). */
.plan-subobject-note {
    display: inline-block;
    margin-left: var(--space-2);
    color: var(--color-text-faint);
    font-size: calc(0.85rem * var(--ui-fs-secondary));
}

/* Generische Sanduhr für laufende HTMX-Formular-Anfragen (z. B. der
   Datei-Upload): htmx setzt .htmx-request auf das anfragende Element (das
   Formular), solange die Anfrage läuft. Die monochrome, pulsierende Sanduhr
   (Strich-SVG in currentColor) ERSETZT dabei den Speichern-Button: sie hat
   dessen Größe, der in <span data-request-replace> eingefasste Button wird
   ausgeblendet – kein Layout-Sprung. Einbindung per Markup:
   <span data-request-replace>…Button…</span>
   <span data-request-indicator>…SVG…</span> */
[data-request-indicator] {
    display: none;
    align-items: center;
    justify-content: center;
    width: 2.25rem;
    height: 2.25rem;
    color: var(--color-text-muted);
    pointer-events: none;
}

[data-request-indicator] svg {
    width: 1.35rem;
    height: 1.35rem;
}

form.htmx-request [data-request-indicator] {
    display: inline-flex;
    animation: request-indicator-pulse 1.2s ease-in-out infinite;
}

form.htmx-request [data-request-replace] {
    display: none;
}

@keyframes request-indicator-pulse {
    0%, 100% { opacity: 0.35; }
    50% { opacity: 1; }
}

.akte-warning {
    margin: 0 0 var(--space-3);
    padding: var(--space-2) var(--space-3);
    border-radius: var(--radius-sm);
    background-color: var(--color-warning-bg);
    color: var(--color-warning-text);
    font-size: calc(0.875rem * var(--ui-fs-secondary));
}

/* Speichern-Icon-Button (save_button-Makro): monochrome SVG-Diskette in
currentColor, gleiche subtile Optik wie die übrigen Icon-Buttons (✎/✕).
Der zusammengesetzte Selektor überschreibt die generische Primärfarbe von
button[type="submit"] (sonst blauer Block ohne sichtbares Icon). */
button[type="submit"].icon-button-save {
    width: 2.25rem;
    height: 2.25rem;
    padding: 0;
    background-color: var(--color-surface);
    border-color: var(--color-border-strong);
    color: var(--color-text-muted);
}

button[type="submit"].icon-button-save:hover {
    background-color: var(--color-surface);
    border-color: var(--color-accent);
    color: var(--color-text);
}

.icon-button-save svg {
    width: 1.05rem;
    height: 1.05rem;
    display: block;
}

/* Inline-Bearbeitung der Bezeichnung in der Überschrift des
Bearbeiten-Overlays: „FL-23 ✎ bearbeiten“ – der Stift ersetzt den Namen durch
eine Textbox in Überschriftgröße; das Feld gehört per form-Attribut zum
Bearbeiten-Formular. */
.object-name-heading {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    margin: 0;
}

/* Einzeilige, bei Bedarf herunterskalierte Überschriften (fit-single-line.js):
   Der Container schneidet Überbreite ab, der innere [data-fit-content] wird per
   transform verkleinert, sodass alles in eine Zeile passt statt umzubrechen. */
[data-fit-single-line] {
    white-space: nowrap;
    overflow: hidden;
}

[data-fit-single-line] [data-fit-content] {
    display: inline-block;
    transform-origin: left center;
}

/* Die Vorgangs-Überschrift ist sonst inline-flex; als Fit-Container muss sie ein
   Block sein, damit clientWidth den verfügbaren Platz misst (nicht die
   Inhaltsbreite). */
.object-name-heading[data-fit-single-line] {
    display: block;
}

.object-name-heading input[name="name"] {
    min-width: 12rem;
    background-color: var(--color-surface);
    border: 1px solid var(--color-border-strong);
    border-radius: var(--radius-sm);
    padding: 0.15rem 0.5rem;
    color: var(--color-text);
    font: inherit;
}

.object-name-heading input[name="name"]:focus {
    outline: none;
    border-color: var(--color-accent);
    box-shadow: 0 0 0 3px rgba(110, 168, 254, 0.2);
}

.object-name-edit-button {
    width: 1.9rem;
    height: 1.9rem;
    font-size: calc(0.95rem * var(--ui-fs-body));
}

/* Karte „Darstellung auf diesem Gerät“ (/stammdaten/design): Regler-Zeilen für
   Text-, Abstands- und Rundungs-Skalierung. */
.ui-scale-row {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    margin-bottom: var(--space-3);
}

.ui-scale-row label {
    flex: 0 0 8rem;
}

.ui-scale-row input[type="range"] {
    flex: 1 1 auto;
    min-width: 0;
}

.ui-scale-row output {
    flex: 0 0 3.5rem;
    text-align: right;
    color: var(--color-text-muted);
    font-variant-numeric: tabular-nums;
}

/* Zwischenüberschriften der Anzeige-Karte (Schriftgrößen je Rolle,
   Schriftschwere je Stufe). */
.ui-scale-subheader {
    margin-top: var(--space-4);
    margin-bottom: var(--space-2);
}

.ui-scale-subheader h4 {
    margin: 0;
    font-size: calc(0.85rem * var(--ui-fs-secondary));
    color: var(--color-text-muted);
}

.ui-scale-row .ui-scale-weight {
    flex: 1 1 auto;
    min-width: 0;
}

/* Verlinktes lokales Dokument (ADR-038): „lokal öffnen“-Icon in der Vorschau-/
   Aktionsspalte und der gedämpfte „Lokal · Rechner“-Hinweis neben dem Dateinamen. */
.document-local-open {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--color-text-muted);
}

.document-local-open:hover,
.document-local-open:focus-visible {
    color: var(--color-accent);
}

.doc-local-tag {
    display: inline-block;
    margin-left: var(--space-2);
    padding: 0 0.4rem;
    border-radius: var(--radius-sm);
    background-color: var(--color-surface-raised);
    color: var(--color-text-muted);
    font-size: calc(0.72rem * var(--ui-fs-secondary));
    white-space: nowrap;
    vertical-align: middle;
}

/* Umschalter „Datei hochladen“ ↔ „Lokale Datei verlinken“ im Dokument-Dialog
   (ADR-038): segmentierte Auswahl; die aktive Seite ist hervorgehoben, die
   inaktive lädt per HTMX den anderen Modus. */
.document-mode-switch {
    display: inline-flex;
    margin-bottom: var(--space-4);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    overflow: hidden;
}

.document-mode-switch button {
    border: 0;
    background: transparent;
    color: var(--color-text-muted);
    padding: var(--space-2) var(--space-4);
    font: inherit;
    cursor: pointer;
}

.document-mode-switch button:hover {
    color: var(--color-text);
}

.document-mode-switch button.is-active {
    background-color: var(--color-surface-raised);
    color: var(--color-text);
    cursor: default;
}

/* Login-Seite (formularbasierter Zugang mit „Angemeldet bleiben“, ADR-036):
   eigenständige, zentrierte Karte ohne App-Navigation. */
.login-page {
    min-height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--space-4);
}

.login-card {
    width: 100%;
    max-width: 22rem;
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    padding: var(--space-6);
    background-color: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-card);
}

.login-card h1 {
    margin: 0 0 var(--space-2);
    text-align: center;
}

.login-remember {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    color: var(--color-text-muted);
}

.login-card button[type="submit"] {
    margin-top: var(--space-2);
}
