/* Design-System PLD Pro – siehe DESIGN.md.
   Die Farbtokens leiten sich von den MudBlazor-Palettenvariablen ab, damit
   eigene Elemente den Light-/Dark-Wechsel ohne Doppelpflege mitmachen. */

:root {
    --pld-surface: var(--mud-palette-surface);
    --pld-background: var(--mud-palette-background);
    --pld-border: var(--mud-palette-lines-default);
    --pld-text-primary: var(--mud-palette-text-primary);
    --pld-text-secondary: var(--mud-palette-text-secondary);
    --pld-primary: var(--mud-palette-primary);
    --pld-accent: var(--mud-palette-warning);
    --pld-success: var(--mud-palette-success);
    --pld-info: var(--mud-palette-info);
    --pld-error: var(--mud-palette-error);

    --pld-font-mono: "IBM Plex Mono", ui-monospace, "Cascadia Mono", Consolas, monospace;

    --pld-row-height: 48px;
    /* 29.08.2026 von 4px auf 5px (KMU-Feedback: Kategorie-Farbstreifen beim
       schnellen Scannen zu unauffaellig, v. a. Accent vs. Info). */
    --pld-stripe-width: 5px;

    /* Mindestgroesse einer Trefferflaeche auf Touch (DESIGN.md, Abschnitt 12). */
    --pld-touch-target: 44px;
}

/* --- Breakpoints ----------------------------------------------------------
   Diese beiden Zahlen sind KEINE freie Wahl: sie muessen zu MudBlazors
   Breakpoints und damit zu MudTable.Breakpoint passen. Eine Tabelle mit
   Breakpoint="Xs" stapelt unter 600 px, eine mit "Sm" unter 960 px – die
   zugehoerige Media-Query unten muss denselben Wert tragen.

   Es gibt keinen Compiler, der das prueft. Wer den Breakpoint einer Tabelle
   aendert, aendert die Media-Query mit (DESIGN.md, Abschnitt 12). */

/* --- Sichtbarer Fokus -----------------------------------------------------
   Fehlte bisher vollstaendig – auch fuer NavTile, dessen ganzer Zweck die
   Erreichbarkeit mit der Tastatur ist. Ohne diese Regel sieht man beim
   Durchtabben nicht, wo man steht. */
:focus-visible {
    outline: 2px solid var(--pld-primary);
    outline-offset: 2px;
}

/* --- Signature 1: Kategorie-Farbstreifen (DESIGN.md, Abschnitt 1) ---------
   Eine leichte Anspielung auf physische Ablage-Register. Wird auf
   Tabellenzeilen und Karten angewendet, nicht punktuell. */

/* Seit die Kategorien Mandanten-Stammdaten sind, benennen die Klassen die
   Farbe und nicht mehr die Kategorie – ein Mandant kann seine Kategorien frei
   benennen, die Palette bleibt fest (DESIGN.md, Abschnitt 1). */
.pld-cat-primary { --pld-category-color: var(--pld-primary); }
.pld-cat-accent { --pld-category-color: var(--pld-accent); }
.pld-cat-info { --pld-category-color: var(--pld-info); }
.pld-cat-success { --pld-category-color: var(--pld-success); }
.pld-cat-neutral { --pld-category-color: var(--pld-text-secondary); }

.pld-row > td:first-child {
    border-left: var(--pld-stripe-width) solid var(--pld-category-color, transparent);
}

.pld-row > td {
    height: var(--pld-row-height);
}

/* Zeilendichte der Dokumentliste (KMU-Feedback 29.08.2026, Desktop-Runde:
   "in DATEV sehe ich 25+ Zeilen auf einen Blick, hier sind es sechs").
   --pld-row-height (48px) ist dabei gar nicht der eigentliche Hebel: bei
   den meisten Zeilen erzwingt bereits ein zweizeilig umbrechender
   Dateiname mehr Hoehe, als die Vorgabe je durchsetzen koennte (Fund:
   tatsaechliche Zeilenhoehe nachgemessen 83-107px, nie 48px). Der wahre
   Hebel ist der MudBlazor-Standard-Innenabstand von 16px oben/unten je
   Zelle - auf 8px reduziert, gilt fuer Desktop UND die gestapelte Karte
   gleichermassen (dieselbe Zahl, ein einziger Ort statt zwei gepflegter
   Werte). Nur auf .pld-list-table, nicht auf .pld-row generell - andere
   Tabellen (Papierkorb, Uebersicht "Zuletzt abgelegt") haben ihre eigene
   Zeilenhoehe nie zur Diskussion gestellt. */
.pld-list-table .pld-row > td.mud-table-cell {
    padding-bottom: 8px;
    padding-top: 8px;
}

/* Eine Zeile mit genau einem Ziel. Der Klick ist Komfort fuer die Maus – der
   Weg fuer Tastatur und Screenreader ist der Link in der Zeile selbst
   (DESIGN.md, Abschnitt 9). */
.pld-row-clickable {
    cursor: pointer;
}

/* Bulk-Aktionsleiste in DmsList.razor (Design-Review 26.08.2026), erscheint
   nur bei mindestens einer Auswahl - eigener Hintergrund, damit sie sich von
   der Filterzeile darueber abhebt statt wie ein weiterer Filter zu wirken. */
.pld-bulk-bar {
    background: var(--pld-background);
    border: 1px solid var(--pld-border);
    border-radius: 4px;
    padding: 0.5rem 0.75rem;
}

/* "Weitere Filter" in DmsList.razor: der Kalender-Adornment-Knopf von
   MudDatePicker bleibt bei fester Touch-Zielgroesse (48px), auch mit
   Dense="true" auf dem Picker selbst – ragte dadurch 8px ueber die sonst
   kompakte, dichte Zeile (Kunde/Lieferant-Select, Checkbox) hinaus.
   MudCollapse misst seine Zielhoehe an dieser Zeile; die ueberstehenden 8px
   zaehlten mit und der Filterbereich bekam einen eigenen, unnoetigen
   vertikalen Scrollbalken (UX-Fund 13.08.2026). Auf 32px gestutzt, wie die
   Checkbox daneben (.mud-checkbox-dense) es bereits ist. */
.pld-filter-row .mud-input-adornment-icon-button {
    height: 32px;
    padding: 4px;
    width: 32px;
}

/* DmsList.razor-Werkzeugleiste auf dem Telefon (KMU-Feedback 29.08.2026:
   "zu viel Vorbau, bevor ueberhaupt ein Dokument sichtbar ist") - Suchen/
   Exportieren/Upload nehmen als Variant.Outlined/Filled-Knoepfe mit Label
   unnoetig viel Zeilenhoehe, obwohl auf 390px ohnehin schon wenig Platz
   neben der Suchleiste bleibt. Kompaktere Auspraegung nur unterhalb des
   Tabellen-Stapel-Umbruchs (599.98px, dieselbe Grenze wie bei .pld-row) -
   Beschriftung und Funktion bleiben unveraendert, nur Innenabstand und
   Schriftgroesse sinken auf das Mass von Dense-Buttons. */
@media (max-width: 599.98px) {
    .pld-list-toolbar .mud-button-root {
        font-size: .8125rem;
        padding: 4px 10px;
    }
}

/* DmsUpload.razor: der Hinweis auf den ZIP-/Ordner-Bulk-Import ist nur am
   Computer relevant - eine bestehende Ordnerstruktur zu einer ZIP-Datei zu
   packen ist kein Vorgang, den jemand vom Telefon aus anstoesst (Erik,
   29.08.2026). Ausgeblendet statt entfernt: derselbe Hinweistext bleibt am
   Desktop unveraendert bestehen. */
@media (max-width: 599.98px) {
    .pld-desktop-only-hint {
        display: none;
    }
}

/* --- Tabellen im gestapelten Modus (unter 600 px) -------------------------
   MudBlazor stapelt Tabellen unterhalb von MudTable.Breakpoint, und die
   Vorgabe dafuer ist Xs – das war also immer schon an. Zwei eigene Regeln
   von oben passen dort aber nicht:

   1. Die Zeilenhoehe. 48 px je Zelle ergaben bei neun Spalten eine 432 px
      hohe "Zeile" je Dokument; gemessen am 31.07.2026 war die Liste damit
      ueber 11000 px lang. Gestapelt zaehlt die Trefferflaeche, nicht die
      Zeilenhoehe.
   2. Der Farbstreifen. Er haengt an td:first-child und dekorierte gestapelt
      nur den ersten Block statt der Karte. Er wandert deshalb auf jede
      Zelle – das ergibt einen durchgehenden Streifen am linken Rand der
      ganzen Karte.

   Der Wert 599.98px gehoert zu Breakpoint.Xs. Tabellen mit Breakpoint="Sm"
   brauchen zusaetzlich den 959.98px-Block weiter unten.

   Das :not() ist tragend, nicht kosmetisch: MudTd HideSmall blendet eine Zelle
   mit "visibility:collapse; height:0" aus, nicht mit display:none. Ein
   pauschales min-height blaeht genau diese Zellen wieder auf und macht die
   Karte laenger statt kuerzer – gemessen 464 px statt der erwarteten 350. */
@media (max-width: 599.98px) {
    .pld-row > td:not(.mud-table-cell-hide) {
        border-left: var(--pld-stripe-width) solid var(--pld-category-color, transparent);
        height: auto;
        min-height: var(--pld-touch-target);
    }

    .pld-row { border-bottom: 2px solid var(--pld-border); }
    .pld-row:last-child { border-bottom: 0; }
}

@media (max-width: 959.98px) {
    .pld-table-sm-stacked .pld-row > td:not(.mud-table-cell-hide) {
        border-left: var(--pld-stripe-width) solid var(--pld-category-color, transparent);
        height: auto;
        min-height: var(--pld-touch-target);
    }

    /* MudBlazor nimmt gestapelten Zellen ihren Rand (border:none), damit die
       Karte ruhig wirkt. Ohne Ersatz laufen die Karten aber ineinander und man
       sieht nicht, wo ein Dokument endet – deshalb eine Trennlinie je Zeile. */
    .pld-table-sm-stacked .pld-row { border-bottom: 2px solid var(--pld-border); }
    .pld-table-sm-stacked .pld-row:last-child { border-bottom: 0; }

    /* Kategorie und Status in EIN Feld auf der Karte (KMU-Feedback
       29.08.2026: "Datei/Kategorie/Status/Aktionen als eigene Zeile ist viel
       Flaeche fuer ein Dokument"). .pld-row bleibt technisch display:table-row,
       aber jede Zelle bekommt von MudBlazor selbst schon display:flex fuers
       Stapeln (Fund: table-row + flex-Kind blockifiziert das Kind laut
       CSS-Display-Spezifikation, genau das erzeugt die bestehende
       Kartenoptik) - flex-basis auf einer einzelnen Zelle wirkt darin aber
       nicht, deshalb wird die Zeile hier selbst zum Flex-Container.
       Ausgewaehlt ueber data-label statt nth-child: die Spaltenreihenfolge
       verschiebt sich um eins, sobald die Checkbox-Spalte fehlt (ReadOnly/
       Steuerberater ohne DocumentsWrite) - eine Positionsangabe waere für
       genau diese Rollen falsch.

       Die Basis (display:flex auf der Zeile, flex:1 1 100% als Vorgabe je
       Zelle) gilt fuer JEDE gestapelte Tabelle mit .pld-table-sm-stacked -
       das ist die generische Korrektur des MudBlazor-Stapel-Verhaltens
       selbst. Alles Spaltenspezifische danach (Reihenfolge, Kategorie/
       Status/Aktionen-Regeln) ist dagegen an .pld-list-table gebunden, eine
       zusaetzliche Klasse nur auf der Dokumentliste (DmsList.razor) - andere
       Tabellen mit .pld-table-sm-stacked tragen z. T. eigene Spalten namens
       "Status"/"Aktionen" mit voellig anderer Bedeutung (z. B.
       TenantAdministration.razor, UserAdministration.razor) und duerfen
       diese Umformung nicht miterben (Fund 29.08.2026: eine erste Fassung
       band alles an .pld-table-sm-stacked und griff dadurch ungewollt auch
       in diese fremden Tabellen ein). */
    .pld-table-sm-stacked .pld-row {
        display: flex;
        flex-wrap: wrap;
    }

    .pld-table-sm-stacked .pld-row > td.mud-table-cell {
        flex: 1 1 100%;
    }

    /* "Kunde" steht im DOM zwischen Kategorie und Status und ist NUR dann
       display:none (Regel weiter unten), wenn das Dokument tatsaechlich
       keinen Kunden hat (HideSmall="@(context.Partner is null)" in
       DmsList.razor) - bei jedem Dokument MIT Kunde bleibt die Zelle
       bewusst sichtbar, das ist keine Ausnahme, sondern der haeufigere Fall
       in echten Daten. Mit sichtbarer 100%-Breite dazwischen brach die
       gewuenschte gemeinsame Zeile fuer genau diese (haeufigeren) Dokumente
       wieder auseinander (Fund 29.08.2026: 9 von 14 Beispieldokumenten
       betroffen). flex-wrap bricht Zeilen nach der VISUELLEN Reihenfolge
       (order), nicht nach der DOM-Reihenfolge - Kunde bekommt hier deshalb
       eine spaetere Position zugewiesen, egal ob sichtbar oder nicht, und
       steht Kategorie/Status nie mehr im Weg. */
    .pld-list-table .pld-row > td[data-label="Datei"] { order: 1; }
    .pld-list-table .pld-row > td[data-label="Kategorie"] { order: 2; }
    .pld-list-table .pld-row > td[data-label="Status"] { order: 3; }
    .pld-list-table .pld-row > td[data-label="Kunde"] { order: 4; }
    .pld-list-table .pld-row > td[data-label="Größe"] { order: 5; }
    .pld-list-table .pld-row > td[data-label="Belegdatum"] { order: 6; }
    .pld-list-table .pld-row > td[data-label="Abgelegt"] { order: 7; }

    /* Der Innenabstand (14px auf 8px oben/unten je Zelle) ist seit der
       Desktop-Dichte-Runde (29.08.2026) nicht mehr hier, sondern
       ungebunden an eine Bildschirmgroesse direkt bei der generischen
       .pld-row > td-Regel gesetzt - gilt seither fuer Karte UND
       Desktop-Tabelle gleichermassen, ein einziger Wert statt zweier
       gepflegter Kopien. Der Touch-Mindestwert (--pld-touch-target, 44px)
       bleibt unveraendert ueber min-height (Regel fuer
       .pld-table-sm-stacked weiter oben). */

    /* "Datei" als eigenes Wortlabel ist redundant - der Dateiname traegt die
       Endung (".pdf") bereits sichtbar, ein Label sagt nichts zusaetzlich
       aus (KMU-Feedback 29.08.2026, dritte Runde, einstimmig bei allen drei
       Personas). Ohne Label bekommt der Dateiname die volle Zeilenbreite
       statt sie sich mit dem Label zu teilen - kuerzere/keine Zeilenumbrueche
       bei vielen Dateinamen. */
    .pld-list-table .pld-row > td[data-label="Datei"] {
        justify-content: flex-start;
    }

    .pld-list-table .pld-row > td[data-label="Datei"]::before {
        content: none;
    }

    /* Kopfzeile der Karte (Erik, 29.08.2026): Checkbox links, Aktionen-Menü
       (nur die drei Punkte, ohne "Aktionen"-Beschriftung) rechts, beide in
       ihrer natuerlichen Groesse statt auf voller Breite - dieselbe Zeile
       statt zwei eigener. Checkbox hat kein data-label (einzige Zelle ohne),
       das ist ihr zuverlaessiger Selektor unabhaengig von der Rolle -
       "Aktionen" bekommt denselben order-Wert, die DOM-Reihenfolge
       (Checkbox zuerst) entscheidet dann bei Gleichstand, welche der beiden
       links landet. margin-left:auto schiebt Aktionen an den rechten Rand,
       ohne die Zeile auf 100% Breite zu zwingen. */
    .pld-list-table .pld-row > td.mud-table-cell:not([data-label]) {
        order: 0;
        flex: 0 0 auto;
    }

    .pld-list-table .pld-row > td[data-label="Aktionen"] {
        order: 0;
        flex: 0 0 auto;
        margin-left: auto;
        /* Traegt keinen eigenen Kartenrand mehr - sie steht nicht mehr am
           linken Rand, seit sie mit margin-left:auto nach rechts wandert
           (gleicher Grund wie bei Status weiter unten). Die Zelle behielt
           ausserdem als einzige einen border-bottom (1px, Herkunft nicht in
           dieser Datei - vermutlich eine MudBlazor-Vorgabe fuer die letzte
           Spalte), sichtbar als duenner Strich unter der Kopfzeile der Karte
           (Fund 29.08.2026, Screenshot) - die Karte hat bereits ihre eigene
           Trennlinie am unteren Rand, eine zweite mitten in der Karte war
           nie beabsichtigt. */
        border-bottom: none;
        border-left: none;
    }

    .pld-list-table .pld-row > td[data-label="Aktionen"]::before {
        content: none;
    }

    /* min-width:0 ist hier tragend, nicht kosmetisch: Flex-Items tragen per
       Spezifikation ein implizites min-width:auto (Inhalt darf nicht unter
       seine eigene Minimalbreite schrumpfen) - genau das liess beide Zellen
       trotz flex-basis:50% auf voller Zeilenbreite (317px) stehen, bis es
       nachgemessen und explizit aufgehoben wurde (Fund 29.08.2026). */
    /* 62/38 (Erik, 30.08.2026: "Entferne das Wort Kategorie und aligne die
       eigentliche Kategorie mit dem Farbstreifen mit dem Wort Kunde, damit
       es nicht unruhig ist") - "Kategorie" als Wort ist seither ebenso
       redundant wie "Status" schon vorher (Fund 29.08.2026): der
       Kategoriename selbst steht ja bereits da. padding-left auf 1rem
       (statt .5rem) angehoben, damit der Kategoriewert genau dort beginnt,
       wo das Wort "Kunde" in der Zeile darunter beginnt (dessen Zelle traegt
       MudBlazors eigenes 1rem, unveraendert) - beide Zellen tragen denselben
       5px-Farbstreifen (Regel weiter oben), nur die Innenabstaende mussten
       angeglichen werden. Ohne "Kategorie" als eigenes Flex-Item bleibt fuer
       den Kategoriewert dieselbe 62%-Breite wie zuvor fuer Wort+Wert
       zusammen. */
    .pld-list-table .pld-row > td[data-label="Kategorie"] {
        flex: 1 1 62%;
        justify-content: flex-start;
        min-width: 0;
        padding-left: 1rem;
        padding-right: .5rem;
    }

    .pld-list-table .pld-row > td[data-label="Status"] {
        flex: 1 1 38%;
        justify-content: flex-start;
        min-width: 0;
        padding-left: .5rem;
        padding-right: .5rem;
    }

    /* "Kategorie" und "Status" sind als Woerter redundant zur Kategorie-
       Farbe/zum Chip-Text selbst - beide Zellen haben deshalb seit hier kein
       data-label-Pseudoelement mehr. */
    .pld-list-table .pld-row > td[data-label="Kategorie"]::before,
    .pld-list-table .pld-row > td[data-label="Status"]::before {
        content: none;
    }

    /* Der Chip selbst ist display:flex und traegt deshalb dasselbe implizite
       min-width:auto wie die Tabellenzelle weiter oben - ohne diese Regel
       bliebe er bei seiner vollen Inhaltsbreite (104px), egal wie schmal die
       Zelle daneben ist. */
    .pld-list-table .pld-row > td[data-label="Status"] .pld-status {
        min-width: 0;
    }

    /* Der Kategorie-Farbstreifen (Regel oben, gilt fuer JEDE Zelle) ergab bei
       voller Zeilenbreite je Feld eine durchgehende Linie am linken Kartenrand
       - jetzt, wo Status neben Kategorie steht statt darunter, erzeugte
       Status' eigener border-left stattdessen einen zweiten, sinnlosen Strich
       MITTEN in der Karte (Fund 29.08.2026, Screenshot). Kategorie traegt die
       Randlinie fuer diese gemeinsame Zeile weiterhin, Status nicht mehr. */
    .pld-list-table .pld-row > td[data-label="Status"] {
        border-left: none;
    }

    /* .pld-status setzt white-space:nowrap (richtig in der vollen Spalte der
       Desktop-Tabelle) - bei halber Kartenbreite lief ein langer Statusname
       wie "Freigegeben" dadurch über den Kartenrand hinaus, statt umzubrechen
       (Fund 29.08.2026, Screenshot: Chip-Text sichtbar abgeschnitten). */
    .pld-list-table .pld-row > td[data-label="Status"] .pld-status {
        white-space: normal;
    }

    /* Ausgeblendete Zellen (Kunde/Groesse/Belegdatum/Abgelegt) behalten trotz
       visibility:collapse und Nullhoehe ihre volle flex-basis:100% aus der
       Regel oben - dazwischen liegend (Kunde steht im DOM zwischen Kategorie
       und Status) erzwang das eine eigene Zeile im Flex-Umbruch und riss die
       gewuenschte gemeinsame Zeile auseinander (Fund 29.08.2026, nachgemessen
       per getBoundingClientRect). Ein reines flex-basis:0 reichte nicht -
       flex-grow:1 verteilte den freien Rest der Zeile trotzdem auf die
       unsichtbare Zelle und liess fuer Status keinen Platz mehr auf derselben
       Zeile (Rundungsfehler bei 317px/2). display:none nimmt sie vollstaendig
       aus der Flex-Berechnung heraus - fuer table-column-collapse-Semantik
       gibt es hier ohnehin keinen Grund mehr, sobald die Zeile selbst
       display:flex ist statt eine echte Tabellenzeile. */
    .pld-table-sm-stacked .pld-row > td.mud-table-cell-hide {
        display: none;
    }

    /* Mandantenliste mit aufklappbarer Detailzeile: die Kartenzeilen sind
       display:flex, die Detailzeile bleibt eine echte table-row. Innerhalb
       eines table-row-group wickelt der Browser die Flex-Zeilen deshalb in
       anonyme Tabellenzellen, und die Detailzeile teilt sie in zwei Gruppen.
       Folgen am Handy (Fund 01.11.2026): aufgeklappt wurde die Tabelle 527 px
       breit statt 349 (die inneren Tabellen der Details setzten die
       Mindestbreite), zugeklappt standen die Karten je nach Browser
       nebeneinander, weil die anonymen Zellen nicht neu zusammengefuegt
       wurden. Als Block gibt es keine anonymen Tabellenboxen mehr; die
       Detailzeile bekommt die Kartenbreite, und was breiter ist, scrollt in
       .pld-table-scroll. Nur hier, weil nur diese Tabelle ChildRowContent hat.
       Ueber .mud-table-root und ">" gebunden: die Details enthalten selbst
       Tabellen, die Tabellen bleiben muessen. */
    .pld-tenants-table .mud-table-root,
    .pld-tenants-table .mud-table-root > tbody,
    .pld-tenants-table .mud-table-root > tbody > tr:not(.pld-row),
    .pld-tenants-table .mud-table-root > tbody > tr:not(.pld-row) > td {
        display: block;
        width: 100%;
    }

    .pld-tenants-table .mud-table-root > tbody > tr:not(.pld-row) {
        border-bottom: 2px solid var(--pld-border);
        background: var(--mud-palette-background-gray);
    }
}

/* Die Aktionen-Spalte bleibt beim waagrechten Scrollen sichtbar, statt hinter
   den uebrigen Spalten zu verschwinden (DESIGN.md, Abschnitt 9) – loest die
   Erreichbarkeit, ohne eine der uebrigen acht Spalten zu opfern. Nur ab
   960 px: darunter stapelt die Tabelle ohnehin zu Karten, sticky waere dort
   falsch. */
@media (min-width: 960px) {
    .pld-table-sm-stacked .pld-row > td:last-child,
    .pld-table-sm-stacked .mud-table-head th:last-child {
        position: sticky;
        right: 0;
        background: var(--mud-palette-surface);
        box-shadow: -8px 0 8px -8px rgba(0, 0, 0, .15);
    }

    /* Dokumentliste bleibt breiter als ihr Container (Messung 04.09.2026:
       Container 788px, Tabelle ~1109px bei realistischen Dateinamen – vorher
       ~1135px). Spalten zu streichen stand nicht zur Debatte (inhaltliche
       Verarmung, CHANGELOG-DESIGN.md); die Zellpolsterung ist der einzige
       Hebel, der keinen Inhalt kostet. Bewusst nur ab diesem Breakpoint: die
       gestapelte Handy-Karte hat kein Breiten-, sondern ein Ruhe-Bedürfnis,
       ihr Innenabstand bleibt unangetastet. */
    .pld-list-table td.mud-table-cell,
    .pld-list-table th.mud-table-cell {
        padding-left: .75rem;
        padding-right: .75rem;
    }
}

/* "Abgelegt" (Datum + Uhrzeit) brach beim Vermessen der Dokumentliste
   (04.09.2026) in JEDER Zeile zwischen Datum und Uhrzeit um: das
   automatische Tabellen-Layout wies der Spalte weniger Platz zu, als der
   Wert einzeilig braucht, und das Leerzeichen im Wert bot einen
   Bruchpunkt an, den der Browser lautlos nutzte – jede Zeile wurde dadurch
   ohne ersichtlichen Grund zweizeilig hoch. "Größe" hat dieselbe Falle
   (Leerzeichen vor der Einheit) und ist vorsorglich mit abgesichert.
   Bewusst nicht an .pld-mono insgesamt: der Speicherort auf der
   Detailseite ist ebenfalls ein Mono-Wert, aber ohne eigenen
   Scroll-Container – ihn am Umbrechen zu hindern, liefe dort in einen
   waagrechten Überlauf statt in eine zweite Zeile. */
td[data-label="Abgelegt"] .pld-mono,
td[data-label="Größe"] .pld-mono {
    white-space: nowrap;
}

/* Eine Tabelle, die auch gestapelt zu breit bleibt – etwa die des Betreibers
   mit elf Spalten –, scrollt in ihrem eigenen Container und schiebt nicht die
   ganze Seite waagrecht. */
.pld-table-scroll {
    overflow-x: auto;
}

.pld-card {
    border-left: var(--pld-stripe-width) solid var(--pld-category-color, transparent);
}

/* Drop-Zone um das native <InputFile> (DmsUpload.razor) - der Input selbst
   bleibt unveraendert (gleicher Selektor, gleiche Funktion), liegt hier nur
   transparent und flaechendeckend ueber dem gestalteten Rahmen. */
.pld-upload-dropzone {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: .5rem;
    padding: 2rem 1rem;
    border: 2px dashed var(--pld-border);
    border-radius: 8px;
    text-align: center;
}

.pld-upload-dropzone:focus-within {
    border-color: var(--mud-palette-primary);
}

.pld-upload-dropzone-icon {
    color: var(--pld-text-secondary);
}

.pld-upload-dropzone-input {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    opacity: 0;
    cursor: pointer;
}

.pld-category-dot {
    background: var(--pld-category-color, var(--pld-text-secondary));
    border-radius: 2px;
    display: inline-block;
    height: 14px;
    margin-right: .5rem;
    vertical-align: -2px;
    width: 4px;
}

/* --- Ordnerbaum der Kundenakte (DESIGN.md, Abschnitt 9) -------------------
   Bewusst kein zweiter Farbcode: der Kategorie-Streifen oben bleibt das
   einzige Farbsignal, Kunden und Ordner tragen keine eigene Farbe.

   Die Einrueckung kommt aus DocumentFolder.Depth, nicht aus verschachteltem
   Markup – der Baum kommt bereits in Anzeigereihenfolge aus dem Service. */
.pld-folder-row {
    align-items: center;
    border-radius: 4px;
    cursor: pointer;
    display: flex;
    gap: .25rem;
    /* 44px statt der 48px der Tabellenzeilen: der Baum ist dichter, bleibt
       aber ueber der Mindestgroesse fuer Touch-Ziele. */
    min-height: 44px;
    padding: 0 .5rem;
}

.pld-folder-row:hover {
    background: var(--mud-palette-action-default-hover);
}

.pld-folder-selected {
    background: var(--mud-palette-action-default-hover);
    font-weight: 600;
}

/* Eigene Trefferflaeche fuers Auf- und Zuklappen. Ein Tippen auf den Namen
   waehlt den Ordner aus, es klappt ihn nicht auf. */
.pld-folder-toggle {
    display: inline-flex;
    flex: 0 0 auto;
    justify-content: center;
    width: 32px;
}

.pld-folder-name {
    flex: 1 1 auto;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Das rohe <input type=file> hat eine Eigenbreite, die einen 360-px-Bildschirm
   sprengt. Die Gestaltung des Elements selbst (Ablageflaeche, Drag & Drop)
   bleibt offen – DESIGN.md, Abschnitt 8. */
input[type="file"] {
    max-width: 100%;
}

/* Der Dateiname im Panelkopf der Upload-Liste (DmsUpload.razor) ist frei
   gewaehlt vom Nutzer und kann laenger sein als jede feste Breite – ohne
   diesen Umbruch sprengt ein langer Name die Zeile bei 360 px (DESIGN.md,
   Abschnitt 12). Anders als .pld-folder-name (die dort einzeilig bleibt)
   darf der Dateiname hier auf mehrere Zeilen umbrechen, weil im Panelkopf
   genug vertikaler Platz ist. anywhere, nicht break-word: break-word senkt
   die Mindestbreite nicht, ein Name ohne Leerzeichen blaehte die Vorfahren
   des Panelkopfs trotzdem auf seine volle Laenge auf – bei 1024 px wurde die
   Seite 2134 px breit, Entfernen/Aufklappen lagen ausserhalb (Fund
   30.09.2026, DESIGN.md Abschnitt 16, Regel 2). */
.pld-upload-filename,
.pld-upload-message {
    overflow-wrap: anywhere;
    min-width: 0;
}

/* Dubletten-Hinweis vor dem Hochladen (DmsUpload.razor). Der Link auf das
   vorhandene Dokument erbte sonst die dunkle Textfarbe ohne Unterstreichung
   und war im Warnkasten nicht als Link zu erkennen. Farbe des Kastens,
   Unterstreichung als Signal – kein eigener Farbton neben dem Warnton. */
/* Der Hinweis steht im Panelkopf unter der Dateizeile. MudBlazor zentriert
   den Aufklapp-Pfeil senkrecht im ganzen Kopf – mit Hinweis rutschte er
   neben den Warnkasten statt neben das Entfernen-Kreuz der Dateizeile.
   Oben ausgerichtet liegen beide auf einer Linie (gemessen, gleiche Mitte);
   ohne Hinweis aendert sich nichts, der Kopf ist dann einzeilig. */
.pld-upload-file .mud-expand-panel-header {
    align-items: flex-start;
}

.pld-upload-duplicate a {
    color: inherit;
    font-weight: 600;
    text-decoration: underline;
    text-underline-offset: 2px;
}

/* --- Formular-Raster, Gruppen, Vorschlaege (22.10.2026) ------------------
   Entwurf "Upload-Pruefung" (CHANGELOG-DESIGN.md), zuerst fuer die
   Upload-Seite, dann auch im Belegdaten-Dialog - deshalb pld-form-*, nicht
   pld-upload-*. Vorher hatte jedes Feld ein eigenes Mass, kein Feld endete
   rechts dort, wo das naechste endete.

   Das Raster fragt die Breite seines Containers ab (Container Query), nicht
   die des Fensters: neben der Vorschau oder in einem Dialog ist das
   Formular schmaler als der Bildschirm, und eine Media Query laege daneben. */
.pld-page-max {
    max-width: 80rem;
    margin-inline: auto;
}

/* Geteilte Ansicht: Beleg links, Felder rechts (DmsUpload.razor). Ob sie
   greift, entscheidet der Server einmal beim ersten Rendern
   (pldproUpload.isWide, min-width 75rem) - schmal wird die Datei gar nicht
   erst geschickt. Die Vorschau laeuft beim Scrollen mit, solange der Beleg
   hoeher ist als die Felder daneben. */
.pld-upload-review-split {
    display: grid;
    grid-template-columns: minmax(0, 5fr) minmax(0, 6fr);
    gap: 1.75rem;
    align-items: start;
}

/* Die Hoehe richtet sich zusaetzlich nach der Breite (28.10.2026): eine
   A4-Seite hochkant ist 1,414-mal so hoch wie breit, dazu die Werkzeugleiste
   des PDF-Betrachters. Vorher nahm der Rahmen fast die ganze Fensterhoehe -
   bei einer einseitigen Rechnung blieb darunter eine graue Flaeche, und
   neben den kurzen Feldern ein leerer Streifen. Mehrseitige Belege blaettern
   im Rahmen weiter. Deshalb Container Query: die Spalte ist schmaler als das
   Fenster. */
.pld-upload-preview {
    position: sticky;
    top: calc(var(--mud-appbar-height) + 1rem);
    container-type: inline-size;
}

.pld-upload-preview .pld-preview-frame {
    height: min(calc(100vh - var(--mud-appbar-height) - 6rem), 62rem, calc(100cqi * 1.414 + 4rem));
}

.pld-upload-preview .pld-preview-image-box {
    max-height: min(calc(100vh - var(--mud-appbar-height) - 6rem), 62rem);
}

.pld-upload-preview-bar {
    display: flex;
    justify-content: flex-end;
}

.pld-form-fields {
    container-type: inline-size;
    display: flex;
    flex-direction: column;
    gap: 1.5rem;
}

.pld-form-group-title {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: .25rem .75rem;
    margin-bottom: .5rem;
}

.pld-form-group-title .mud-typography-caption {
    color: var(--pld-text-secondary);
}

.pld-form-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    align-items: start;
    gap: 1rem 1.25rem;
}

.pld-form-grid + .pld-form-grid {
    margin-top: 1rem;
}

.pld-form-grid-amounts {
    grid-template-columns: repeat(3, minmax(0, 1fr)) minmax(0, .6fr);
}

.pld-form-grid-full {
    grid-column: 1 / -1;
    margin-top: -.5rem;
}

.pld-form-field {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

/* MudBlazors Eingabefelder wachsen in einer Flex-Spalte mit (flex:1 1 auto) -
   ein Hinweis darunter rutschte sonst um die Hoehe der Nachbarzelle nach
   unten. */
.pld-form-field > .mud-input-control,
.pld-form-field > .mud-select,
.pld-form-field-grow > .mud-select {
    flex: none;
}

.pld-form-field-row {
    flex-direction: row;
    align-items: flex-end;
    gap: .25rem;
}

.pld-form-field-grow {
    flex: 1 1 auto;
    min-width: 0;
}

@container (max-width: 30rem) {
    .pld-form-grid {
        grid-template-columns: minmax(0, 1fr);
    }

    .pld-form-grid-amounts {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

/* Hinweis am Feld - fuer einen Fall, den MudBlazors HelperText nicht
   abdeckt: Warnung mit Symbol, oder eine Fundstelle fuer mehrere Felder. */
.pld-field-hint {
    display: flex;
    align-items: flex-start;
    gap: .375rem;
    margin-top: .25rem;
    font-size: .8125rem;
    line-height: 1.45;
    color: var(--pld-text-secondary);
}

.pld-field-hint-warn {
    color: var(--pld-accent);
}

.pld-field-hint .mud-icon-root {
    flex: none;
    margin-top: .05rem;
}

/* Feld mit noch unveraendertem Vorschlag: getoent, Unterlinie in Info.
   Feld mit Hinweis: Unterlinie in Warnfarbe. */
.pld-field-suggested .mud-input {
    background: color-mix(in srgb, var(--pld-info) 6%, transparent);
    border-radius: 4px 4px 0 0;
    padding-inline: .5rem;
}

.pld-field-suggested .mud-input.mud-input-underline::before {
    border-bottom-color: var(--pld-info);
}

.pld-field-warn .mud-input.mud-input-underline::before {
    border-bottom: 1.5px solid var(--pld-accent);
}

/* "Für alle 3 übernehmen" - Textlink am Feld statt eines Kopier-Symbols ganz
   rechts. Ein Knopf, kein <a>: er aendert Werte, er navigiert nicht. */
.pld-text-action {
    align-self: flex-start;
    margin-top: .375rem;
    padding: .125rem 0;
    border: 0;
    background: none;
    color: var(--pld-text-primary);
    font: inherit;
    font-size: .8125rem;
    text-decoration: underline;
    text-decoration-color: color-mix(in srgb, var(--pld-text-primary) 35%, transparent);
    text-underline-offset: 3px;
    cursor: pointer;
}

.pld-text-action:hover:not(:disabled) {
    text-decoration-color: currentColor;
}

/* "+ Lieferant „…“ anlegen" als Eintrag einer Auswahl: halbfett, damit er
   sich von den Kunden darunter abhebt - er waehlt keinen aus, er legt an. */
.pld-select-create {
    font-weight: 600;
}

.pld-text-action:disabled {
    cursor: default;
    opacity: .5;
}

/* Marke im Panelkopf und Zusammenfassung des zugeklappten Belegs. */
.pld-upload-badge {
    font-size: .75rem;
    font-weight: 600;
    padding: .125rem .5rem;
    border-radius: 999px;
    background: color-mix(in srgb, var(--pld-info) 14%, transparent);
    color: var(--pld-info);
    white-space: nowrap;
}

/* Der Dateiname darf schrumpfen und umbrechen, statt als Ganzes in die
   naechste Zeile zu rutschen - am Telefon stand das Symbol sonst allein in
   der ersten Zeile. Groesse und Marke weichen stattdessen nach unten aus.
   Nur schmal: Flexbox bricht nach der Ausgangsbreite um, und am Desktop
   soll der Name so breit sein wie sein Text. */
@media (max-width: 599.98px) {
    .pld-upload-file-header .pld-upload-filename {
        flex: 1 1 10rem;
    }
}

.pld-upload-summary {
    padding-left: 1.75rem;
    line-height: 1.5;
    font-size: .8125rem;
    color: var(--pld-text-secondary);
}

.pld-upload-summary span + span::before {
    content: "·";
    padding: 0 .4rem;
}

/* Dateiname in Dokumenttabellen (DESIGN.md, Abschnitt 16, Regel 2 – der
   Dateiname ist die zweite nachweislich unbrechbare Zeichenkette).

   Zwei Modi, weil anywhere allein nur die Haelfte loest:
   - Gestapelt (Karte) genuegt anywhere: die Zelle hat eine echte Breite,
     der Name bricht darin um. Vorher wuchs die ganze Karte auf die
     Namenslaenge, bei 375 px lagen Belegdatum, Status und Menue ALLER
     Zeilen ausserhalb des Bildschirms (Fund 30.09.2026).
   - Als Tabelle macht anywhere die Mindestbreite der Spalte fast null, und
     der Tabellenalgorithmus quetscht sie auf drei Zeichen. Dort deshalb
     width:max-content mit fester Obergrenze. Die Obergrenze in ch und OHNE
     Prozentanteil: ein min(40ch, 100%) ist in einer Tabellenzelle zyklisch,
     gilt beim Bemessen der Spalte als "none", und die Spalte wuchs wieder
     auf die volle Namenslaenge (gemessen 2704 px).

   Die beiden Grenzen muessen zum Breakpoint der Tabellen passen – 600 px
   fuer die Vorgabe Xs, 960 px fuer pld-table-sm-stacked. Kein Compiler
   prueft das. */
.pld-filename {
    overflow-wrap: anywhere;
}

@media (min-width: 600px) {
    .mud-table:not(.pld-table-sm-stacked) .pld-filename {
        display: inline-block;
        width: max-content;
        max-width: 40ch;
    }
}

@media (min-width: 960px) {
    .pld-table-sm-stacked .pld-filename {
        display: inline-block;
        width: max-content;
        max-width: 40ch;
    }
}

/* Metadatentabelle der Detailseite. Sie ist eine MudSimpleTable und kennt
   deshalb weder Breakpoint noch DataLabel; auf dem Telefon zaehlt hier nur,
   dass die langen Werte umbrechen. Der Storage-Key ist die laengste
   unbrechbare Zeichenkette der Anwendung. */
.pld-meta-table td:last-child {
    overflow-wrap: anywhere;
}

/* Ein einzelner langer Wert ohne Leerzeichen in einer Tabellenzelle, etwa
   eine E-Mail-Adresse in der Benutzertabelle: am Telefon blaehte er die
   gestapelte Tabelle auf 437 px bei 364 px Platz auf (gemessen 22.10.2026).
   Auf den Wert, nicht auf die Zelle – sonst bricht auch deren DataLabel
   ("E-/Mail"). */
.pld-wrap-anywhere {
    overflow-wrap: anywhere;
    min-width: 0;
}

/* --- Vorschlags-Aktion (SuggestionAction.razor, 22.10.2026) ---------------
   "31.07.2026 übernehmen", "Lieferant „…“ anlegen": ein kleiner, umrandeter
   Knopf direkt unter dem Feld, nur so breit wie sein Text. Vorher ein
   MudChip, der wie ein Etikett aussah und sich in einer senkrechten
   MudStack ueber die ganze Breite zog (DESIGN.md, "Vorschlags-Aktionen").
   Farben aus den Theme-Variablen, damit Hell und Dunkel mitgehen. */
.pld-suggestion-action {
    display: inline-flex;
    align-items: center;
    gap: .375rem;
    align-self: flex-start;
    max-width: 100%;
    min-height: 2.25rem;
    margin-top: .5rem;
    padding: .375rem .75rem;
    border: 1px solid color-mix(in srgb, var(--pld-text-primary) 30%, transparent);
    border-radius: 6px;
    background: var(--pld-surface);
    color: var(--pld-text-primary);
    font: inherit;
    font-size: .875rem;
    font-weight: 600;
    line-height: 1.3;
    text-align: left;
    cursor: pointer;
}

.pld-suggestion-action > span {
    min-width: 0;
    overflow-wrap: anywhere;
}

.pld-suggestion-action .mud-icon-root {
    flex: none;
    font-size: 1.125rem;
}

.pld-suggestion-action:hover:not(:disabled) {
    border-color: var(--pld-text-primary);
    background: color-mix(in srgb, var(--pld-text-primary) 6%, var(--pld-surface));
}

.pld-suggestion-action:disabled {
    cursor: default;
    opacity: .5;
}

@media (pointer: coarse) {
    .pld-suggestion-action {
        min-height: var(--pld-touch-target);
    }
}

/* --- Hilfetexte unter Feldern ---------------------------------------------
   13 statt MudBlazors 12 px (22.10.2026): an ihnen haengt bei den
   Vorschlaegen die Fundstelle im Beleg, und die las sich in 12 px kaum. Der
   Kontrast (text-secondary auf surface, 5,2:1) reichte schon, die Groesse
   nicht. Bewusst nur hier und nicht ueber den Typskala-Token: Tabellen und
   Metadaten bleiben, wie sie sind. */
.mud-input-helper-text {
    font-size: .8125rem;
    line-height: 1.45;
}

.pld-meta-table td:first-child {
    width: 40%;
}

/* Kundenakte: unter md steht der Ordnerbaum vor der Dokumentliste im
   Quelltext. Auf dem Telefon schoebe ein Kunde mit vielen Ordnern die
   Dokumente aus dem Bild – deshalb dort Inhalt vor Navigation. MudGrid ist ein
   Flex-Container, mehr als order braucht es nicht. */
@media (max-width: 959.98px) {
    .pld-partner-tree { order: 2; }
    .pld-partner-docs { order: 1; }
}

/* --- Hilfeseite /hilfe -----------------------------------------------------
   Fliesstext statt Bedienoberflaeche: die ganze Seite bekommt EINE Breite
   (64 rem wie die Spalte der Website), und Einleitung, Absaetze, Listen,
   Tabellen und Videos fuellen ihre Karte. Bis 30.10.2026 begrenzte die Seite
   stattdessen einzelne Texte auf 68ch/78ch in Karten ueber die volle Breite –
   fuenf verschiedene rechte Kanten auf einer Seite (Fund Erik). In rem statt
   px (DESIGN.md, Abschnitt 12). */

.pld-help {
    max-width: 64rem;
}

.pld-help-lead {
    color: var(--pld-text-secondary);
}

.pld-help-toc {
    columns: 2;
    column-gap: 2rem;
    list-style: none;
    margin: 0;
    padding: 0;
}

/* Zweispaltig erst, wenn zwei Spalten auch breit genug sind – auf 360 px
   waeren es zwei je 12 Zeichen breite Saeulen. */
@media (max-width: 599.98px) {
    .pld-help-toc { columns: 1; }
}

.pld-help-toc li {
    break-inside: avoid;
    padding: .2rem 0;
}

.pld-help-list,
.pld-help-steps {
    margin: .75rem 0 0;
    padding-left: 1.25rem;
}

.pld-help-list li,
.pld-help-steps li {
    padding: .25rem 0;
}

/* MudSimpleTable kennt weder Breakpoint noch DataLabel (wie .pld-meta-table):
   auf schmalen Geraeten zaehlt hier nur, dass nichts abgeschnitten wird.

   break-word und NICHT anywhere wie bei .pld-meta-table: dort steht der
   Storage-Key, eine unbrechbare Zeichenkette. Hier stehen normale Woerter, und
   anywhere erlaubt dem Tabellenalgorithmus, eine Spalte schmaler als ihr
   laengstes Wort zu machen – "Aufbewahrung" landete dadurch mit einem
   Trennstrich-losen Umbruch mitten im Wort. */
.pld-help-table td,
.pld-help-table th {
    overflow-wrap: break-word;
    vertical-align: top;
}

.pld-help-table th[scope="row"] {
    white-space: nowrap;
}

.pld-help-hint {
    color: var(--pld-text-secondary);
}

/* How-to-Video (Components/shared/HelpVideo.razor). Breite wie der
   Fliesstext darueber, damit es nicht ueber die Abschnittskarte laeuft;
   aspect-ratio haelt den Platz frei, bevor das Vorschaubild geladen ist. */
.pld-help-video {
    margin: 0 0 1.25rem;
}

/* Innerhalb einer Aufzaehlung folgt es auf Text statt auf die Ueberschrift. */
.pld-help-list .pld-help-video {
    margin: .75rem 0 .5rem;
}

.pld-help-video video {
    aspect-ratio: 16 / 9;
    border: 1px solid var(--pld-border);
    border-radius: 4px;
    display: block;
    height: auto;
    width: 100%;
}

.pld-help-video figcaption {
    color: var(--pld-text-secondary);
    font-size: .875rem;
    margin-top: .5rem;
}

.pld-help-video figcaption b {
    color: var(--pld-text-primary);
    display: block;
}

/* --- Dokumentvorschau (DESIGN.md, Abschnitt 10) ---------------------------
   Die Vorschau soll auf einem Laptop ohne Scrollen erkennbar sein, aber die
   Metadaten darunter nicht aus dem Bild schieben – daher eine Hoehe in vh mit
   Deckel, kein fester Pixelwert. */

/* Vollbild-Vorschau im Dialog (02.09.2026, DESIGN.md Abschnitt 10).
   dvh statt vh: auf dem Smartphone rechnet vh die ein- und ausfahrende
   Adressleiste nicht mit, der untere Rand des Dokuments landet dann unter
   ihr. 9rem sind Kopf- und Aktionszeile des Dialogs. */
.pld-preview-fullscreen {
    display: block;
    width: 100%;
    height: calc(100vh - 9rem);
    height: calc(100dvh - 9rem);
}

.pld-preview-frame {
    background: var(--pld-background);
    border: 1px solid var(--pld-border);
    border-radius: 8px;
    display: block;
    height: min(70vh, 760px);
    width: 100%;
}

/* Nur unter 600px sichtbar (siehe Media Query unten) - ersetzt dort das
   iframe, ist auf Laptop/Desktop nie im Bild. */
.pld-preview-mobile-open {
    display: none;
}

/* Der Kasten traegt den Hintergrund, nicht das Bild: ein PNG mit
   Transparenz waere auf der Flaeche sonst je nach Theme unlesbar.

   align-items bewusst flex-start, NICHT center (Fund 07.09.2026, Handyfoto
   eines Kassenbelegs): ueberragt ein Bild die Hoehe dieses Kastens - bei
   einem hochkant aufgenommenen Beleg der Normalfall, nicht die Ausnahme -,
   schneidet ein zentrierter Flex-Container die ueberstehende Haelfte oben
   UND unten ab, und die obere Haelfte bleibt dabei ausserhalb des
   erreichbaren Scrollbereichs - "ganz nach oben gescrollt" zeigt trotzdem
   nicht den Anfang des Bildes. Mit flex-start beginnt das Bild am oberen
   Rand des Kastens, komplett erreichbar durch Herunterscrollen. */
.pld-preview-image-box {
    align-items: flex-start;
    background: var(--pld-background);
    border: 1px solid var(--pld-border);
    border-radius: 8px;
    display: flex;
    justify-content: center;
    max-height: min(70vh, 760px);
    overflow: auto;
    padding: 1rem;
}

.pld-preview-image {
    max-width: 100%;
    object-fit: contain;
}

/* pre bricht von sich aus nicht um. Ohne pre-wrap laeuft eine CSV-Zeile
   waagrecht aus der Karte heraus. */
/* CSV als Tabelle statt Rohtext (04.09.2026). Teilt sich Rahmen, Hoehendeckel
   und Scrollverhalten mit .pld-preview-text - eine CSV ist derselbe Fall,
   nur besser lesbar, und zwei nebeneinanderliegende Scrollbereiche mit
   unterschiedlichen Deckeln waeren genau der Fehler, den der Kommentar
   weiter unten fuer das Handy beschreibt. */
.pld-preview-table {
    background: var(--pld-background);
    border: 1px solid var(--pld-border);
    border-radius: 8px;
    max-height: min(70vh, 760px);
    overflow: auto;
}

.pld-preview-table table {
    border-collapse: collapse;
    font-family: var(--pld-font-mono);
    font-size: .8125rem;
    line-height: 1.5;
    width: 100%;
}

.pld-preview-table th,
.pld-preview-table td {
    border-bottom: 1px solid var(--pld-border);
    padding: .4rem .75rem;
    text-align: left;
    /* Ziffernspalten sollen untereinander stehen - eine Betragsspalte ist der
       haeufigste Grund, warum jemand eine CSV ueberhaupt ansieht. */
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

/* Ohne das verteilt sich der freie Platz gleichmaessig auf alle Spalten: eine
   dreispaltige CSV im breiten Vorschaubereich bekam so 295px fuer ein
   zehnstelliges Datum, und die Spalten standen ueber die ganze Breite verteilt
   statt als Gruppe beieinander (gesehen im UI-Test-Screenshot, 04.09.2026).
   Die letzte Spalte nimmt den Rest - bei einer CSV ist das fast immer die
   Bezeichnung, also genau die, die den Platz braucht. Bei vielen Spalten
   greift die Regel ohnehin nicht, dann scrollt die Box. */
.pld-preview-table th:last-child,
.pld-preview-table td:last-child {
    width: 100%;
}

/* Der Kopf bleibt beim senkrechten Scrollen stehen; ohne das weiss man ab
   Zeile 20 nicht mehr, welche Spalte man liest. */
.pld-preview-table thead th {
    background: var(--pld-surface);
    color: var(--pld-text-secondary);
    font-weight: 600;
    position: sticky;
    top: 0;
    z-index: 1;
}

.pld-preview-table tbody tr:last-child td {
    border-bottom: 0;
}

.pld-preview-text {
    background: var(--pld-background);
    border: 1px solid var(--pld-border);
    border-radius: 8px;
    color: var(--pld-text-primary);
    font-family: var(--pld-font-mono);
    font-size: .8125rem;
    line-height: 1.5;
    margin: 0;
    max-height: min(70vh, 760px);
    overflow: auto;
    padding: 1rem;
    white-space: pre-wrap;
    word-break: break-word;
}

/* Auf dem Handy ist die Detailseite ohnehin einspaltig (Metadaten oben,
   Vorschau darunter) - der 70vh-Deckel oben ist fuer die zweispaltige
   Laptop-Ansicht gedacht und erzeugt hier nur einen zweiten, ineinander
   verschachtelten Scrollbereich (Seite + iframe/Bild-Box). Unter 600px
   bekommt die Vorschau die volle Bildschirmhoehe als eigene, einzige
   scrollbare Flaeche (14.08.2026).

   100vh zaehlt auf iOS Safari die maximale Viewport-Hoehe (Adressleiste
   eingeklappt), nicht die tatsaechlich sichtbare - die Vorschau ragt dadurch
   ueber den sichtbaren Bereich hinaus und die ganze Seite bekommt zusaetzlich
   zum Scrollen der Vorschau selbst einen eigenen, aeusseren Scrollbereich.
   100dvh (dynamic viewport height, iOS Safari ab 15.4) folgt der Adressleiste;
   100vh bleibt als Fallback fuer aeltere Browser stehen, die dvh nicht kennen
   (15.08.2026).

   Zusaetzlich: das eingebettete iframe selbst bleibt auf iOS Safari fuer PDFs
   unbrauchbar, unabhaengig von seiner Groesse - "#view=FitH" wird dort in
   einem iframe weitgehend ignoriert, die Seite erscheint in Originalbreite
   und erzwingt Scrollen in beide Richtungen (Fund 15.08.2026, keine
   Reproduktion in diesem Chromium-basierten Werkzeug moeglich, aber exakt das
   gemeldete Verhalten). Kein URL-Parameter loest das zuverlaessig; unter
   600px ersetzt darum .pld-preview-mobile-open das iframe komplett, statt es
   nur zu verkleinern - der eigene Vollbild-Betrachter des Geraets kann Zoom
   und Breite-einpassen von Haus aus. */
@media (max-width: 599.98px) {
    .pld-preview-frame {
        height: 100vh;
        height: 100dvh;
    }

    .pld-preview-frame-viewer {
        display: none;
    }

    .pld-preview-mobile-open {
        display: flex;
    }

    .pld-preview-image-box,
    .pld-preview-table,
    .pld-preview-text {
        max-height: 100vh;
        max-height: 100dvh;
    }
}

/* --- Signature 2: Systemdaten in Mono (DESIGN.md, Abschnitt 3) ------------
   Signalisiert "Maschinendaten" gegenueber Freitext. */

.pld-mono,
.pld-mono code {
    color: var(--pld-text-secondary);
    font-family: var(--pld-font-mono);
    font-size: .8125rem;
    letter-spacing: -.01em;
}

.pld-mono-strong {
    color: var(--pld-text-primary);
    font-family: var(--pld-font-mono);
    font-size: .8125rem;
}

/* --- Status-Chips: heller Tint statt vollem Farbfeld ----------------------
   Wirkt bei vielen Zeilen deutlich ruhiger als der MudBlazor-Default. */

.pld-status {
    align-items: center;
    border-radius: 999px;
    display: inline-flex;
    font-size: .75rem;
    font-weight: 600;
    gap: .4rem;
    line-height: 1;
    padding: .3rem .6rem .3rem .5rem;
    white-space: nowrap;
}

/* Punktgroesse und Tint-Anteil am 29.08.2026 leicht angehoben (6px/14% auf
   7px/20%) - KMU-Feedback: beim schnellen Scannen vieler Zeilen zu wenig
   Praesenz, um Status ohne Lesen des Texts zu unterscheiden. */
.pld-status::before {
    background: currentColor;
    border-radius: 50%;
    content: "";
    height: 7px;
    width: 7px;
}

.pld-status-eingegangen {
    background: color-mix(in srgb, var(--pld-info) 20%, transparent);
    color: var(--pld-info);
}

.pld-status-freigegeben {
    background: color-mix(in srgb, var(--pld-success) 20%, transparent);
    color: var(--pld-success);
}

.pld-status-bezahlt {
    background: color-mix(in srgb, var(--pld-primary) 20%, transparent);
    color: var(--pld-primary);
}

/* Fuer freie Statuswerte mit der Kategorie-Farbe "Accent" (CategoryStatus.cs,
   CategoryPresentation.StatusCssClass) - die anderen drei Kategorie-Farben
   sind ueber die bestehenden Klassen oben bereits abgedeckt. */
.pld-status-accent {
    background: color-mix(in srgb, var(--pld-accent) 20%, transparent);
    color: var(--pld-accent);
}

/* Fuer /admin/wartung: Status der zeitgesteuerten Wartungsjobs. */
.pld-status-fehlgeschlagen {
    background: color-mix(in srgb, var(--pld-error) 20%, transparent);
    color: var(--pld-error);
}

.pld-status-unbekannt {
    background: color-mix(in srgb, var(--pld-text-secondary) 20%, transparent);
    color: var(--pld-text-secondary);
}

/* Plattenplatz ueber der Warnschwelle (/admin/betrieb). Eigene Klasse statt
   einer der vier Statusfarben: Gelb gab es bis dahin nicht, und "Warnung"
   ist weder Info noch Fehler. */
.pld-status-warnung {
    background: color-mix(in srgb, var(--pld-accent) 22%, transparent);
    color: var(--pld-text-primary);
}

/* --- Speicherwachstum je Monat (/admin/betrieb) ----------------------------
   Waagrechte Balken statt eines Diagramms: zwoelf Zeilen lesen sich am
   Telefon besser als zwoelf schmale Saeulen, und die Zahl steht direkt
   daneben. Monat und Wert in Mono (DESIGN.md, Abschnitt 11). */
.pld-growth-list {
    display: grid;
    gap: .375rem;
}

.pld-growth-row {
    display: grid;
    grid-template-columns: 4.5rem minmax(0, 1fr) 5.5rem;
    gap: .75rem;
    align-items: center;
}

.pld-growth-track {
    height: .5rem;
    border-radius: 2px;
    background: color-mix(in srgb, var(--pld-border) 70%, transparent);
    overflow: hidden;
}

.pld-growth-fill {
    height: 100%;
    background: var(--pld-primary);
}

.pld-growth-row .pld-mono:last-child {
    text-align: right;
}

/* --- Nutzung (/admin/nutzung, 28.10.2026) -----------------------------------
   Dieselben waagrechten Balken, aber mit Namen statt Monat: die Spalte waechst
   bis 40 % und kuerzt dann mit Auslassung, der volle Name steht im Tooltip.
   Am Telefon (360 px) bleiben so Balken und Zahl in einer Zeile. */
.pld-usage-list .pld-growth-row {
    grid-template-columns: minmax(5rem, 40%) minmax(2rem, 1fr) auto;
}

.pld-usage-label {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.pld-usage-range {
    font-size: .8125rem;
    color: var(--pld-text-secondary);
}

/* Saeulen je Tag: eine Reihe, eine Farbe; die Zahlen stehen im Tooltip und
   in der Beschriftung fuer Bildschirmleser. Unten verankert, oben 2 px rund. */
.pld-usage-days-figure {
    margin: 0;
}

.pld-usage-days {
    display: flex;
    align-items: flex-end;
    gap: 2px;
    height: 6rem;
    border-bottom: 1px solid var(--pld-border);
}

.pld-usage-day {
    flex: 1 1 0;
    min-width: 0;
    height: 100%;
    display: flex;
    align-items: flex-end;
}

.pld-usage-day-fill {
    width: 100%;
    border-radius: 2px 2px 0 0;
    background: var(--pld-primary);
}

.pld-usage-day:hover .pld-usage-day-fill {
    filter: brightness(.85);
}

.pld-usage-days-axis {
    display: flex;
    justify-content: space-between;
    gap: .5rem;
    margin-top: .25rem;
    font-size: .75rem;
    color: var(--pld-text-secondary);
}

/* --- Formular-Dialoge (CategoryDialog, 21.10.2026) --------------------------
   Gruppen mit gleichem Abstand nach oben; unter jedem Schalter die Erklaerung,
   eingerueckt auf die Hoehe seiner Beschriftung: der Schalter belegt
   gemessen 58 px. Nicht nach links ziehen, um die Schiene buendig mit den
   Feldern zu setzen – der Rand rechts davon braucht der Knopf, er ueberdeckte
   sonst den Anfang der Beschriftung. Der aufklappbare Bereich verliert seinen
   eigenen Innenabstand, damit seine Felder am selben Rand beginnen. Am Handy
   fuellt der Dialog den Bildschirm: ein langes Formular in einem schwebenden
   Kasten mit Rand ringsum laesst dort kaum Platz zum Lesen, und
   Speichern/Abbrechen bleiben am unteren Rand. */
.pld-dialog-section {
    display: flex;
    flex-direction: column;
    gap: .75rem;
    margin-top: 1.5rem;
}

.pld-dialog-option .mud-typography-caption {
    display: block;
    padding-left: 58px;
    margin-top: -.25rem;
    color: var(--pld-text-secondary);
}

/* Hinweis zu einer ganzen Gruppe (z. B. unter den Grenzen eines Pakets):
   buendig mit den Feldern, nicht eingerueckt. */
.pld-dialog-section > .mud-typography-caption {
    color: var(--pld-text-secondary);
}

.pld-dialog-form .pld-dialog-panels {
    margin-top: 1.5rem;
    border-top: 1px solid var(--pld-border);
}

.pld-dialog-form .pld-dialog-panels .mud-expand-panel-header,
.pld-dialog-form .pld-dialog-panels .mud-expand-panel-content {
    padding-inline: 0;
}

.pld-dialog-panel-title {
    display: flex;
    flex-direction: column;
    gap: .125rem;
}

.pld-dialog-panel-title .mud-typography-caption {
    color: var(--pld-text-secondary);
}

@media (max-width: 599.98px) {
    .mud-dialog.pld-dialog-form {
        margin: 0;
        width: 100%;
        max-width: 100%;
        height: 100%;
        max-height: 100%;
        border-radius: 0;
    }

    .mud-dialog.pld-dialog-form .mud-dialog-content {
        flex: 1 1 auto;
    }
}

/* --- Saeulen je Tag (DayColumnChart, /admin/qwen-statistik) ----------------
   HTML statt SVG, damit die Achsenschrift am Telefon nicht mitschrumpft.
   Gitter und Achse zuruecknehmend, die Saeule in der Primaerfarbe wie die
   Balken des Speicherwachstums; 2 px Luft zwischen den Saeulen. */
.pld-daychart {
    display: grid;
    grid-template-columns: 3.75rem minmax(0, 1fr);
    grid-template-rows: 10rem auto;
    column-gap: .5rem;
    row-gap: .25rem;
}

.pld-daychart-yaxis {
    position: relative;
}

.pld-daychart-yaxis span {
    position: absolute;
    right: 0;
    transform: translateY(50%);
    color: var(--pld-text-secondary);
    font-family: var(--pld-font-mono);
    font-size: .6875rem;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.pld-daychart-plot {
    position: relative;
    border-bottom: 1px solid var(--pld-border);
}

.pld-daychart-grid {
    position: absolute;
    left: 0;
    right: 0;
    border-top: 1px dashed color-mix(in srgb, var(--pld-border) 80%, transparent);
}

.pld-daychart-cols {
    position: absolute;
    inset: 0;
    display: flex;
    gap: 2px;
    align-items: flex-end;
}

.pld-daychart-col {
    flex: 1 1 0;
    min-width: 0;
    height: 100%;
    display: flex;
    align-items: flex-end;
    border-radius: 3px 3px 0 0;
}

.pld-daychart-col:hover {
    background: color-mix(in srgb, var(--pld-primary) 8%, transparent);
}

.pld-daychart-bar {
    width: 100%;
    min-height: 2px;
    border-radius: 3px 3px 0 0;
    background: var(--pld-primary);
}

.pld-daychart-xaxis {
    display: flex;
    gap: 2px;
    color: var(--pld-text-secondary);
    font-family: var(--pld-font-mono);
    font-size: .6875rem;
}

.pld-daychart-xaxis span {
    flex: 1 1 0;
    min-width: 0;
    display: flex;
    justify-content: center;
    white-space: nowrap;
}

.pld-daychart-xaxis span:last-child {
    justify-content: flex-end;
}

/* Zeiten, Groessen und Zeitpunkte in Betreiber-Tabellen nie umbrechen:
   „1 min / 45 s“ auf zwei Zeilen liest sich als zwei Werte. Am Telefon
   schaltet die Tabelle ohnehin auf Karten um. */
.pld-nowrap-values td .pld-mono,
.pld-nowrap-values td .pld-mono-strong,
.pld-nowrap-values td .pld-status {
    white-space: nowrap;
}

/* --- KPI-Kacheln ---------------------------------------------------------- */

/* Werkstatt-Feinschliff (29.08.2026): die groesste Zahl auf der Seite lief
   bisher in der Fliesstext-Schrift (Work Sans) statt in der Marken-
   Ueberschriftenschrift, obwohl sie optisch die Rolle einer Ueberschrift
   spielt (vgl. .pld-document-frame-value/.pld-price-teaser-item .price auf
   der Website, beide in Bitter). Reine Typografie-Korrektur, kein neues
   Element. */
.pld-kpi-value {
    font-family: var(--pld-font-heading);
    font-size: 2rem;
    font-weight: 700;
    line-height: 1.1;
}

/* overflow/text-overflow/white-space zusammen: ohne sie brach ein langer
   Kategoriename (z. B. "Ausgangsrechnung") in eine zweite Zeile um und machte
   seine Kachel hoeher als die Nachbarkacheln in derselben Grid-Reihe. Der
   volle Name bleibt ueber AriaLabel und title erreichbar. */
.pld-kpi-label {
    color: var(--pld-text-secondary);
    font-size: .875rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.pld-kpi-context {
    color: var(--pld-text-secondary);
    font-family: var(--pld-font-mono);
    font-size: .75rem;
    letter-spacing: .02em;
}

/* --- Bewegung (DESIGN.md, Abschnitt 5) ------------------------------------
   Hover nur als leichte Elevation, keine Skalierung, kein Bounce. */

.pld-hoverable {
    transition: box-shadow 120ms ease-in-out;
}

.pld-hoverable:hover {
    box-shadow: 0 2px 8px rgba(26, 32, 39, .12);
}

.pld-fade-in {
    animation: pld-fade 140ms ease-out;
}

@keyframes pld-fade {
    from { opacity: 0; }
    to { opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
    .pld-hoverable,
    .pld-fade-in {
        animation: none;
        transition: none;
    }
}

/* --- Topbar / Marke -------------------------------------------------------- */

/* Jetzt ein <a href="/"> statt eines reinen div (Logo-Klick fuehrt zur
   Uebersicht, 14.08.2026) - Browser-Vorgabestile fuer Links zuruecksetzen,
   sonst unterstreicht/faerbt der Browser den Markennamen blau. */
.pld-brand {
    display: flex;
    align-items: center;
    gap: .625rem;
    color: inherit;
    text-decoration: none;
}

.pld-brand img {
    display: block;
    height: 28px;
    width: 28px;
}

.pld-brand-name {
    font-weight: 700;
    letter-spacing: -.01em;
}

.pld-tenant-name {
    border-left: 1px solid var(--pld-border);
    color: var(--pld-text-secondary);
    margin-left: .875rem;
    /* Ein langer Firmenname darf die Kopfzeile nicht auseinanderdruecken –
       er kuerzt mit Auslassungspunkten. */
    overflow: hidden;
    padding-left: .875rem;
    text-overflow: ellipsis;
    white-space: nowrap;
}

@media (max-width: 599.98px) {
    .pld-tenant-name {
        border-left: 0;
        margin-left: .5rem;
        max-width: 11rem;
        padding-left: 0;
    }
}

/* --- Fehlerbanner ---------------------------------------------------------- */

/* Ueber Seitenmenue (MudDrawer 1100) und Kopfleiste (MudAppBar 1300) - mit
   z-index 1000 lag der Satzanfang unter dem Menue, sichtbar blieb nur
   "...getreten. Neu laden". box-sizing, damit width:100% samt Innenabstand
   nicht ueber den rechten Rand ragt und das Schliessen-Kreuz mitnimmt.
   Farben aus dem MudTheme, damit die Leiste im Dark Mode kein heller Fleck ist. */
#blazor-error-ui {
    background: var(--mud-palette-error, var(--pld-brand-error));
    bottom: 0;
    box-shadow: 0 -2px 6px rgba(0, 0, 0, .25);
    box-sizing: border-box;
    color: var(--mud-palette-error-text, #fff);
    display: none;
    font-family: var(--pld-font-body);
    left: 0;
    padding: .75rem 3rem .75rem 1.25rem;
    position: fixed;
    width: 100%;
    z-index: 1600;
}

#blazor-error-ui .reload {
    color: inherit;
    font-weight: 600;
    text-decoration: underline;
}

#blazor-error-ui .dismiss {
    background: none;
    border: 0;
    color: inherit;
    cursor: pointer;
    font-size: 1.25rem;
    line-height: 1;
    padding: .25rem;
    position: absolute;
    right: .75rem;
    top: 50%;
    transform: translateY(-50%);
}

/* --- Anmeldung / Fehlerseiten (eigenstaendig, ohne MudBlazor-Provider) -----

   Diese Seiten laufen in Static-SSR ohne Blazor-Circuit (Cookie-Seiten, siehe
   Login.razor) und damit ohne <MudThemeProvider> – dessen JS-Interop braucht
   einen laufenden Circuit. Trotzdem NICHT auf feste Hex-Werte angewiesen:
   pldpro-tokens.css (Assets in App.razor) laedt auf jeder Seite, auch dieser,
   und bringt die --pld-brand-*-Variablen samt eigenem
   @media (prefers-color-scheme: dark) mit (UX-Audit 13.08.2026) – rein
   CSS-basiert, kein Interop noetig. Dieselben Werte wie PldProTheme.cs, nur
   ohne Circuit-Abhaengigkeit. */

.pld-minimal-layout {
    align-items: center;
    background: var(--pld-brand-background);
    color-scheme: light dark;
    display: flex;
    font-family: var(--pld-font-body);
    justify-content: center;
    /* dvh statt vh: auf dem Telefon rechnet vh die ein- und ausblendende
       Browserleiste nicht mit, die Karte springt dann beim Scrollen. */
    min-height: 100dvh;
    padding: 1.5rem;
}

.pld-minimal-card {
    background: var(--pld-brand-surface);
    border: 1px solid var(--pld-brand-border);
    border-radius: 10px;
    box-shadow: 0 1px 3px rgba(26, 32, 39, .08);
    color: var(--pld-brand-text-primary);
    max-width: 24rem;
    padding: 2rem;
    width: 100%;
}

@media (max-width: 599.98px) {
    .pld-minimal-layout { padding: 1rem; }
    .pld-minimal-card { padding: 1.5rem; }
}

/* --- Reconnect-Overlay (App.razor, wwwroot/js/reconnect.js) ---------------

   Ersetzt den englischen Standarddialog von blazor.web.js durch ein eigenes,
   deutschsprachiges Overlay im PLD-Pro-Design (Audit Phase B2, 14.09.2026).
   Bewusst wie .pld-minimal-card ohne MudBlazor: waehrend der Circuit haengt,
   ist dessen JS-Interop tot - reines CSS/HTML, einzige Abhaengigkeit ist
   pldpro-tokens.css.

   Sichtbarkeit und Zustand kommen von blazor.web.js selbst: es setzt eine
   der vier Klassen components-reconnect-{show,retrying,failed,rejected} auf
   #components-reconnect-modal. Ohne eine dieser Klassen bleibt das Overlay
   unsichtbar - das deckt sowohl den Ausgangszustand als auch "hide" (wieder
   verbunden) ab, das keine eigene Klasse traegt.

   .pld-reconnect-card bleibt bewusst LEER, bis reconnect.js sie bei einem
   Zustandswechsel per JS fuellt (Regression 14.09.2026: ein UI-Test brach an
   einem Text, der - nur per CSS verborgen - dauerhaft im DOM stand, weil
   Playwrights text=/has-text() unabhaengig von display:none sucht). Deshalb
   hier keine Selektoren fuer einzelne Texte/Zustaende - nur das Aussehen der
   Karte und ihrer Bausteine, unabhaengig davon, welcher Text gerade drinsteht. */
#components-reconnect-modal {
    align-items: center;
    background: color-mix(in srgb, var(--pld-brand-background) 85%, transparent);
    color-scheme: light dark;
    display: none;
    inset: 0;
    justify-content: center;
    position: fixed;
    z-index: 2000;
}

#components-reconnect-modal.components-reconnect-show,
#components-reconnect-modal.components-reconnect-retrying,
#components-reconnect-modal.components-reconnect-failed,
#components-reconnect-modal.components-reconnect-rejected {
    display: flex;
}

.pld-reconnect-card {
    background: var(--pld-brand-surface);
    border: 1px solid var(--pld-brand-border);
    border-radius: 10px;
    box-shadow: 0 4px 16px rgba(26, 32, 39, .16);
    color: var(--pld-brand-text-primary);
    font-family: var(--pld-font-body);
    margin: 1rem;
    max-width: 22rem;
    padding: 2rem;
    text-align: center;
    width: 100%;
}

.pld-reconnect-heading {
    font-family: var(--pld-font-heading);
    font-size: var(--pld-text-lg);
    font-weight: 700;
    margin: 0 0 .5rem;
}

.pld-reconnect-card p:last-child {
    color: var(--pld-brand-text-secondary);
    font-size: var(--pld-text-sm);
    margin: 0;
}

.pld-reconnect-actions {
    display: flex;
    flex-direction: column;
    gap: .5rem;
    margin-top: 1.25rem;
}

.pld-reconnect-button {
    background: var(--pld-brand-primary);
    border: 1px solid var(--pld-brand-primary);
    border-radius: 6px;
    color: var(--pld-brand-surface);
    cursor: pointer;
    font: inherit;
    font-weight: 600;
    padding: .6rem 1rem;
}

.pld-reconnect-button:hover {
    background: var(--pld-brand-primary-hover);
}

.pld-reconnect-button--secondary {
    background: transparent;
    color: var(--pld-brand-text-primary);
}

.pld-reconnect-button--secondary:hover {
    background: color-mix(in srgb, var(--pld-brand-primary) 8%, transparent);
}

/* Reiner CSS-Spinner - MudBlazors MudProgressCircular braucht denselben
   toten Circuit, den dieses Overlay gerade ueberbrueckt. */
.pld-reconnect-spinner {
    animation: pld-reconnect-spin 900ms linear infinite;
    border: 3px solid var(--pld-brand-border);
    border-radius: 50%;
    border-top-color: var(--pld-brand-accent);
    display: inline-block;
    height: 2rem;
    margin-bottom: 1rem;
    width: 2rem;
}

@media (prefers-reduced-motion: reduce) {
    .pld-reconnect-spinner { animation: none; }
}

@keyframes pld-reconnect-spin {
    to { transform: rotate(360deg); }
}

.pld-minimal-brand {
    align-items: center;
    display: flex;
    gap: .625rem;
    margin: 0 0 1.5rem;
}

.pld-minimal-brand img {
    height: 32px;
    width: 32px;
}

.pld-minimal-brand span {
    font-family: var(--pld-font-heading);
    font-size: 1.375rem;
    font-weight: 700;
}

.pld-minimal-brand .pld-minimal-brand-accent {
    color: var(--pld-brand-accent);
}

.pld-minimal-title {
    font-family: var(--pld-font-heading);
    font-size: 1.125rem;
    font-weight: 600;
    margin: 0 0 1rem;
}

.pld-field {
    display: block;
    margin-bottom: 1rem;
}

.pld-field > span {
    color: var(--pld-brand-text-secondary);
    display: block;
    font-size: .875rem;
    margin-bottom: .25rem;
}

.pld-field input {
    background: var(--pld-brand-surface);
    border: 1px solid var(--pld-brand-border);
    border-radius: 6px;
    box-sizing: border-box;
    color: var(--pld-brand-text-primary);
    font: inherit;
    padding: .55rem .65rem;
    width: 100%;
}

/* „Passwort anzeigen" auf den Freigabe-Seiten (02.09.2026, DESIGN.md
   Abschnitt 13). Der Knopf sitzt IM Feld, nicht daneben: daneben schrumpfte
   das Eingabefeld, und bei 360px stuenden Feld und Knopf untereinander. */
.pld-field-with-reveal {
    position: relative;
}

.pld-field-with-reveal input {
    /* Platz fuer den Knopf, damit ein langes Passwort nicht darunter laeuft. */
    padding-right: 2.75rem;
}

.pld-reveal-button {
    align-items: center;
    background: none;
    border: 0;
    border-radius: 6px;
    color: var(--pld-brand-text-secondary);
    cursor: pointer;
    display: flex;
    height: 2rem;
    justify-content: center;
    /* An der Oberkante des Eingabefelds ausgerichtet, nicht der Feldgruppe:
       darueber sitzt noch die Beschriftung. */
    position: absolute;
    right: .35rem;
    top: 1.4rem;
    width: 2rem;
}

.pld-reveal-button:hover {
    color: var(--pld-brand-text-primary);
}

.pld-reveal-button:focus-visible {
    outline: 2px solid var(--pld-brand-primary);
    outline-offset: 1px;
}

.pld-reveal-button svg {
    height: 1.15rem;
    width: 1.15rem;
}

/* Im gedrueckten Zustand das durchgestrichene Auge zeigen - der Knopf sagt
   dann, was ein Klick BEWIRKT (wieder verbergen), nicht was gerade gilt. */
.pld-reveal-button .pld-reveal-off,
.pld-reveal-button[aria-pressed="true"] .pld-reveal-on {
    display: none;
}

.pld-reveal-button[aria-pressed="true"] .pld-reveal-off {
    display: block;
}

.pld-field input:focus {
    border-color: var(--pld-brand-primary);
    outline: 2px solid color-mix(in srgb, var(--pld-brand-primary) 20%, transparent);
}

.pld-checkbox {
    /* Am Anfang ausrichten, nicht mittig (03.09.2026): solange die
       Beschriftung einzeilig war ("Angemeldet bleiben"), sahen beide Werte
       gleich aus. Seit die Registrierung dort zusaetzlich die
       Unternehmerbestaetigung nennt, ist der Text drei Zeilen lang - mit
       "center" schwebte das Kaestchen auf Hoehe der zweiten Zeile, statt
       neben dem Satzanfang zu stehen, zu dem es gehoert. */
    align-items: flex-start;
    display: flex;
    font-size: .875rem;
    gap: .5rem;
    margin-bottom: 1.25rem;
}

/* Optischer Ausgleich: das Kaestchen ist kleiner als die Zeilenhoehe, mit
   reinem flex-start sitzt es an deren Oberkante statt auf der Mittellinie
   des ersten Buchstabens. Der Wert ist die halbe Differenz aus Zeilenhoehe
   und Kaestchengroesse - nicht geraten, sondern so gewaehlt, dass ein
   EINZEILIGES Label (Login) exakt so aussieht wie vorher. */
.pld-checkbox input[type="checkbox"] {
    margin-top: .2rem;
}

.pld-button {
    background: var(--pld-brand-primary);
    border: none;
    border-radius: 6px;
    /* Ohne display:block bleibt <a class="pld-button"> ein inline-Element:
       padding faerbt dann zwar eine sichtbare Flaeche, reserviert aber
       keinen Platz im Zeilenfluss - der Button ueberlappt dadurch die
       Zeile davor/danach um seinen halben vertikalen Padding-Betrag. Bei
       einer laengeren letzten Zeile des vorangehenden Absatzes (z. B. eine
       lange E-Mail-Adresse auf RegisterConfirm.razor) deckt der Button dann
       sichtbar deren letzte Zeile ab (Fund 21.08.2026, Erik auf Test). */
    display: block;
    /* Kontrastfarbe wie PldProTheme.cs (PrimaryContrastText): im Hellmodus
       helle Schrift auf dunkler Tinte, im Dunkelmodus dunkle Schrift auf der
       hell umgekehrten Primaerflaeche (Werkstatt-Palette, DESIGN.md
       Abschnitt 2) – die Flaechenfarbe der jeweils anderen Palettenhaelfte
       trifft beides, ohne einen eigenen Kontrast-Token einzufuehren. */
    color: var(--pld-brand-surface);
    cursor: pointer;
    font: inherit;
    font-weight: 600;
    padding: .6rem 1rem;
    width: 100%;
}

.pld-button:hover {
    background: var(--pld-brand-primary-hover);
}

.pld-alert {
    background: color-mix(in srgb, var(--pld-brand-error) 10%, transparent);
    border-radius: 6px;
    color: var(--pld-brand-error);
    font-size: .875rem;
    margin: 0 0 1rem;
    padding: .6rem .75rem;
}

/* Gegenstueck zu .pld-alert fuer bestaetigende Meldungen im MinimalLayout
   (Passwort geaendert, Link angefordert). */
.pld-success {
    background: color-mix(in srgb, var(--pld-brand-primary) 10%, transparent);
    border-radius: 6px;
    color: var(--pld-brand-primary);
    font-size: .875rem;
    margin: 0 0 1rem;
    padding: .6rem .75rem;
}

.pld-hint {
    color: var(--pld-brand-text-secondary);
    font-size: .8125rem;
    /* Symmetrisch (nicht nur oben), seit ein Hinweistext auch MITTEN in
       einem Formular auftaucht (Passwort-Anforderungen auf Register.razor,
       21.08.2026) statt nur am Seitenende. Ohne unteren Rand klebte er dort
       am naechsten Feld, weil Labels selbst keinen oberen Rand mitbringen -
       margin-collapsing haette bei zwei aufeinanderfolgenden .pld-hint sonst
       trotzdem nur den groesseren der beiden Werte gezeigt, hier also
       unveraendert 1.25rem. */
    margin: 1.25rem 0;
}

/* Letztes Kind einer Anmeldekarte traegt keinen eigenen unteren Rand mehr -
   der wuerde sich zum Karten-Padding addieren (Rand und Padding kollabieren
   nicht ineinander) und den Abstand nach unten groesser wirken lassen als
   den nach oben, obwohl beide von derselben Werteskala kommen. */
.pld-minimal-card > *:last-child {
    margin-bottom: 0;
}

/* Ersetzt das bisherige nackte <p> um <a class="pld-button">
   (RegisterConfirm.razor, Freigabe.razor): dessen UA-Standardrand (~1em,
   browserabhaengig) ergab zusammen mit .pld-hint (1.25rem) oben einen
   anderen kollabierten Abstand als unten - der Button wirkte dadurch nicht
   mittig zwischen den beiden Texten (Fund 21.08.2026, Erik anhand
   Screenshot). Beide Seiten jetzt bewusst derselbe Wert wie .pld-hint. */
.pld-button-row {
    margin: 1.25rem 0;
}

/* Registrierung (Register.razor): Paket- und Abrechnungsauswahl. Radiogruppen
   statt Auswahlliste, weil drei bepreiste Pakete die Entscheidung der Seite
   sind und nicht ein Detail hinter einem Klick. Bewusst hier bei den uebrigen
   Formularelementen der Anmeldeseiten und nicht in einem eigenen Block - es
   sind dieselben Tokens und dasselbe Layout. */

.pld-fieldset {
    border: none;
    margin: 0 0 1.25rem;
    padding: 0;
}

.pld-fieldset legend {
    color: var(--pld-brand-text-secondary);
    font-size: .875rem;
    margin-bottom: .35rem;
    padding: 0;
}

.pld-radio {
    align-items: flex-start;
    background: var(--pld-brand-surface);
    border: 1px solid var(--pld-brand-border);
    border-radius: 6px;
    cursor: pointer;
    display: flex;
    gap: .6rem;
    margin-bottom: .5rem;
    padding: .6rem .7rem;
}

/* :has() traegt die Auswahl-Hervorhebung ohne JavaScript - der Rahmen haengt
   am Zustand des enthaltenen Eingabeelements, nicht an einer Klasse, die
   jemand pflegen muesste. */
.pld-radio:has(input:checked) {
    border-color: var(--pld-brand-primary);
    box-shadow: inset 0 0 0 1px var(--pld-brand-primary);
}

.pld-radio:has(input:focus-visible) {
    outline: 2px solid color-mix(in srgb, var(--pld-brand-primary) 35%, transparent);
    outline-offset: 1px;
}

.pld-radio > span {
    display: flex;
    flex-direction: column;
    gap: .1rem;
}

.pld-radio .pld-mono,
.pld-radio small {
    color: var(--pld-brand-text-secondary);
    font-size: .8125rem;
}

/* Registrierungsseite ist mit zwoelf Feldern die laengste Anmeldeseite,
   teilte sich aber unveraendert dieselbe schmale Kartenbreite (24rem), die
   fuer den zweifeldrigen Login gedacht ist - auf dem Desktop wirkte das wie
   eine nur in die Breite gezogene mobile Ansicht statt wie ein eigenstaendig
   gestaltetes Formular (Design-Review 21.08.2026, Erik anhand Screenshot).
   Eigene, breitere Karte nur fuer diese eine Seite, erkannt ueber :has()
   (bereits an .pld-radio im Einsatz, Zeile oben) statt einer Aenderung an
   LoginLayout.razor selbst - die uebrigen Seiten (Login, Passwort...,
   Kanzlei-Mandantenauswahl) behalten ihre bewusst schmale, fuer wenige
   Felder passende Kartenbreite. Die Markenflaeche bekommt denselben
   absoluten Zuwachs (58 - 34 = 24rem, ihr bisheriger Anteil an den 48rem des
   Login-Shells), damit ihr Anteil an der Gesamtbreite unveraendert bleibt
   und nicht zugunsten der breiteren Karte schrumpft. */
.pld-login-shell:has(.pld-register-page) {
    max-width: 58rem;
}

.pld-minimal-card:has(.pld-register-page) {
    max-width: 34rem;
}

/* Die entsperrte Freigabe-Ansicht zeigt ein eingebettetes Dokument, kein
   Formular (02.09.2026, DESIGN.md Abschnitt 13). In 24rem war der Beleg
   winzig, waehrend links und rechts Platz ungenutzt blieb.

   Deutlich breiter als die Registrierung (34rem): dort geht es um Felder, die
   ab einer gewissen Breite nicht besser werden - hier um eine A4-Seite, die
   von jedem zusaetzlichen Zentimeter profitiert. 64rem statt "so breit wie
   moeglich", damit die Karte auf einem sehr breiten Bildschirm nicht zum
   randlosen Band wird und der Beleg seine Proportion behaelt.

   Gilt NICHT fuer die Sammelfreigabe: die zeigt im entsperrten Zustand nur
   einen Download-Knopf, kein Dokument. */
.pld-minimal-card:has(.pld-share-view) {
    max-width: 64rem;
}

.pld-share-frame {
    border: 0;
    display: block;
    /* Am Telefon soll der Beleg den Bildschirm nutzen, am Desktop nicht ueber
       die Karte hinauswachsen. dvh aus demselben Grund wie beim Layout. */
    height: min(75dvh, 900px);
    width: 100%;
}

@media (min-width: 768px) {
    /* Strasse ueber die volle Breite, PLZ und Ort nebeneinander, Land wieder
       ueber die volle Breite - uebliches Muster fuer Adressformulare (z. B.
       Stripe Checkout), auf dem Handy bleiben die vier Felder unveraendert
       gestapelt (kein Grid ausserhalb dieser Media Query). */
    .pld-register-address {
        column-gap: .75rem;
        display: grid;
        grid-template-columns: 1fr 1fr;
    }

    .pld-register-address .pld-field:first-child,
    .pld-register-address .pld-field:last-child {
        grid-column: 1 / -1;
    }

    /* Paket- und Abrechnungsauswahl nebeneinander statt gestapelt - auf dem
       Desktop ist genug Breite fuer alle Optionen auf einen Blick, das spart
       auf der ohnehin laengsten Anmeldeseite spuerbar Bildschirmhoehe. */
    .pld-radio-row {
        display: flex;
        gap: .6rem;
    }

    .pld-radio-row .pld-radio {
        flex: 1 1 0;
        margin-bottom: 0;
    }
}

/* Login-Seite (LoginLayout.razor, UX-Audit 13.08.2026) - nur diese eine Seite,
   nicht die uebrigen sieben auf MinimalLayout. Karte/Rahmen ueber dieselben
   --pld-brand-*-Tokens wie der uebrige Block oben (Dark-Mode-Fix
   13.08.2026). */
.pld-login-shell {
    background: var(--pld-brand-surface);
    border: 1px solid var(--pld-brand-border);
    border-radius: 14px;
    box-shadow: 0 1px 3px rgba(26, 32, 39, .08);
    display: flex;
    max-width: 48rem;
    overflow: hidden;
    width: 100%;
}

/* Bewusst NICHT auf --pld-brand-primary umgestellt: die Markenflaeche ist ein
   fester Farbblock mit weissem Text, dessen eigener Kontrast unabhaengig vom
   Seitenthema stimmen muss (DESIGN.md, Abschnitt 1, "Spend your boldness in
   one place"). Seit der Werkstatt-Palette (29.08.2026) kehrt sich
   --pld-brand-primary im Dark Mode sogar um (helles Creme statt Tinte,
   #EDE8DF) - mit weisser Schrift waere dort gar kein Kontrast mehr uebrig.
   Die Flaeche bleibt deshalb in beiden Themen im Hellmodus-Tintenton fixiert. */
.pld-login-panel {
    background: #231F1A;
    color: #fff;
    display: none;
    flex: 1;
    flex-direction: column;
    justify-content: center;
    padding: 2.5rem;
}

.pld-login-panel-brand {
    font-family: var(--pld-font-heading);
    font-size: 1.75rem;
    font-weight: 700;
}

/* Bewusst fest statt ueber die Variable: die Panelflaeche selbst bleibt
   themenunabhaengig (siehe oben), ihr Akzent muss deshalb unabhaengig vom
   Seitenthema mitziehen - derselbe helle Rostton, den --pld-brand-accent im
   Dark Mode ohnehin annimmt (#C1745A), auf dem dunklen Panel gut lesbar. */
.pld-login-panel-brand .pld-minimal-brand-accent { color: #C1745A; }

.pld-login-panel-tagline {
    color: rgba(255, 255, 255, .85);
    font-size: 1rem;
    margin: .5rem 0 2rem;
}

.pld-login-panel-facts {
    display: flex;
    flex-direction: column;
    font-size: .875rem;
    gap: .75rem;
    list-style: none;
    margin: 0;
    padding: 0;
}

.pld-login-panel-facts li {
    padding-left: 1.4rem;
    position: relative;
}

.pld-login-panel-facts li::before {
    color: #C1745A;
    content: "✓";
    left: 0;
    position: absolute;
}

.pld-login-card {
    border: none;
    border-radius: 0;
    box-shadow: none;
}

.pld-login-card-brand { display: flex; }

@media (min-width: 768px) {
    .pld-login-panel { display: flex; }
    .pld-login-card-brand { display: none; }
}

/* Mandantenliste des Kanzlei-Kontos (/kanzlei/mandanten) – ein Formular je
   Zeile, .pld-button ist bereits width:100%, hier nur der Abstand dazwischen. */
.pld-mandate-list {
    display: flex;
    flex-direction: column;
    gap: .6rem;
}

.pld-mandate-list .pld-button:disabled {
    background: #9AA3AF;
    cursor: not-allowed;
}

.pld-link {
    color: var(--pld-brand-primary);
}

.validation-message {
    color: var(--pld-brand-error);
    display: block;
    font-size: .8125rem;
    margin-top: .25rem;
}

/* Bankkonten (Add-on bankabgleich, 30.10.2026): gewaehltes Konto in der
   Kontenliste, Vorzeichen der Umsaetze auch farblich, Spaltenzuordnung im
   Kontodialog zweispaltig ab Tablet. */
.pld-row-selected > td {
    background: color-mix(in srgb, var(--pld-brand-info) 8%, transparent);
}

.pld-amount-positive {
    color: var(--pld-success);
}

.pld-amount-negative {
    color: var(--pld-brand-text-primary);
}

.pld-bank-purpose {
    overflow-wrap: anywhere;
}

.pld-bank-mapping {
    display: grid;
    gap: 0 1rem;
    grid-template-columns: 1fr;
}

@media (min-width: 600px) {
    .pld-bank-mapping {
        grid-template-columns: 1fr 1fr;
    }
}

/* Zuordnen-Dialog (BankMatchDialog): Kopf mit Umsatz, darunter Zeilen je
   Beleg – links der Beleg, rechts Betrag und Knopf; am Handy untereinander. */
.pld-bank-match-head,
.pld-bank-match-row {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    justify-content: space-between;
    gap: .5rem 1rem;
}

.pld-bank-match-row {
    padding: .625rem 0;
    border-top: 1px solid var(--mud-palette-lines-default);
}

.pld-bank-match-amount {
    text-align: right;
}

.pld-bank-match-doc {
    flex: 1 1 16rem;
    min-width: 0;
    overflow-wrap: anywhere;
}

.pld-bank-match-action {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .5rem;
}

.pld-bank-match-pick {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .5rem 1rem;
    padding: 0 0 .75rem;
}

.pld-bank-reasons {
    display: flex;
    flex-wrap: wrap;
    gap: .25rem;
    margin-top: .25rem;
}

.pld-bank-match-cell {
    display: inline-flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .25rem .5rem;
}

/* Steuersätze aufteilen (TaxLinesDialog): Satz, Netto, USt, Entfernen in
   einer Zeile, auch am Handy (Satz 5,5 rem, Beträge teilen sich den Rest). */
.pld-tax-line {
    display: flex;
    align-items: flex-end;
    gap: 0 .5rem;
    padding-bottom: .75rem;
}

.pld-tax-rate {
    flex: 0 0 5.5rem;
}

.pld-tax-amount {
    flex: 1 1 4.5rem;
    min-width: 0;
}

/* Auswahl in einer Belegdaten-Zeile (DocumentEarRow): gleiche Schriftgröße wie
   der Tabellentext daneben, nicht die größere Vorgabe eines Formularfelds. */
.pld-select-in-table .mud-input,
.pld-select-in-table .mud-input-slot {
    font-size: var(--mud-typography-body2-size);
}

/* Einnahmen und Ausgaben (/auswertung/ear): drei Kennzahlen nebeneinander,
   am Handy untereinander; die Liste „Was noch fehlt“ ohne Aufzählungspunkte,
   je Eintrag Symbol und Text. */
.pld-ear-kpis {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));
    gap: 1rem 2rem;
}

.pld-ear-todos {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    gap: .5rem;
}

.pld-ear-todos li {
    display: flex;
    align-items: flex-start;
    gap: .5rem;
    overflow-wrap: anywhere;
}

.pld-ear-todos li .pld-mono {
    margin-left: auto;
    white-space: nowrap;
}
