html {
    font-size: var(--global-size, 14px);
}

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

/* DevExpress Utility Classes */
.dx-mt-5 {
    margin-top: 3rem !important;
}

.dx-mb-3 {
    margin-bottom: 1rem !important;
}

.dx-w-100 {
    width: 100% !important;
}

.dx-alert {
    padding: 0.75rem 1.25rem;
    margin-bottom: 1rem;
    border: 1px solid transparent;
    border-radius: 0.25rem;
}

.dx-alert-danger {
    color: var(--dxds-color-content-danger-default-rest);
    background-color: var(--dxds-color-surface-danger-subdued-rest);
    border-color: var(--dxds-color-border-danger-default-rest);
}

.dx-alert-success {
    color: var(--dxds-color-content-success-default-rest);
    background-color: var(--dxds-color-surface-success-subdued-rest);
    border-color: var(--dxds-color-border-success-default-rest);
}

.dx-justify-content-between {
    display: flex;
    justify-content: space-between;
}

.dx-justify-content-end {
    display: flex;
    justify-content: flex-end;
}

.dx-gap-2 {
    gap: 0.5rem;
}

.dx-mt-3 {
    margin-top: 1rem !important;
}

.dx-mt-2 {
    margin-top: 0.5rem !important;
}

.dx-me-3 {
    margin-right: 1rem !important;
}

.dx-flex {
    display: flex;
}

.dx-text-danger {
    color: var(--dxds-color-content-danger-default-rest) !important;
}

.dx-text-center {
    text-align: center !important;
}

.blazor-error-boundary {
    background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3LjgyOSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121;
    padding: 1rem 1rem 1rem 3.7rem;
    color: white;
}

    .blazor-error-boundary::after {
        content: "An error has occurred."
    }

.dxbl-splitter-pane-content {
    padding: 0 !important;
}

/* CreateFirmaPopup KlientenForm tabs — bound height + virtual-scroll grid.
   Die vh-Höhe ist der Fallback für den Fall, dass die Flex-Kette unten nicht
   greift; im Klientenstamm-Popup überschreibt sie .stamm-popup .stamm-tab. */
.stamm-tab {
    display: flex;
    flex-direction: column;
    height: calc(80vh - 170px);
    min-height: 320px;
    gap: 0.5rem;
    padding: 0.25rem 0;
    overflow: hidden;
}

/* ---------------------------------------------------------------------------
   Gemeinsame Höhenkette für größenveränderbare Popups (CssClass="aw-popup-flex").

   Warum überhaupt: DevExpress setzt beim Resize eine Inline-Höhe auf den Dialog.
   Alles im Inneren, dessen Höhe in vh gerechnet ist, hängt weiter am Viewport und
   bekommt davon nichts mit — das Popup wird größer, der Inhalt nicht. Erst diese
   Kette macht AllowResize zu mehr als einer Geste.

   dxbl-modal-body ist von Haus aus display:block mit eigenem overflow-y:auto und
   wird hier zur Flex-Spalte. Die direkten Kinder bekommen NUR min-height:0 (sonst
   schrumpfen Flex-Items nicht unter ihren Inhalt) — welches Kind die Resthöhe
   bekommt, entscheidet jedes Popup selbst über .aw-popup-fill bzw. sein eigenes
   scoped CSS. Ein pauschales flex:1 1 0 auf alle Kinder wäre falsch: das
   BuchungsPopup hat vier Geschwister im Body (Grid, Jahresergebnis, Formular),
   die Höhe wurde dann gleichmäßig verteilt und das Grid schrumpfte von ~485 auf
   158px. Gemessen, nicht vermutet.
   --------------------------------------------------------------------------- */
.aw-popup-flex .dxbl-modal-body {
    display: flex;
    flex-direction: column;
    min-height: 0;
    overflow: hidden;
}

.aw-popup-flex .dxbl-modal-body > * {
    min-height: 0;
}

/* Auf genau den Container setzen, der die Resthöhe bekommen soll. */
.aw-popup-flex .aw-popup-fill {
    flex: 1 1 0;
    min-height: 0;
    height: auto;
}

/* Klientenstamm-Popup ist verschieb- UND größenveränderbar (AllowDrag/AllowResize).
   Damit das Ziehen an der Kante etwas bringt, muss die Inhaltshöhe dem Popup folgen
   statt am Viewport zu hängen: DevExpress setzt beim Resize eine Inline-Höhe auf den
   Dialog, eine vh-Rechnung im Inneren bekäme davon nichts mit und der Tab bliebe
   gleich hoch (bzw. liefe über).
   Die Kette Body → dxbl-tabs → Panel → Content ist am gerenderten DOM abgelesen;
   dxbl-modal-body ist von Haus aus display:block mit eigenem overflow-y:auto und
   dxbl-tabs flex:0 1 auto — an diesen beiden Stellen reißt die Höhenweitergabe.
   min-height:0 überall, weil Flex-Items sonst nicht unter ihren Inhalt schrumpfen. */
.stamm-popup .dxbl-modal-body {
    display: flex;
    flex-direction: column;
    min-height: 0;
    overflow: hidden;
}

.stamm-popup .dxbl-modal-body > dxbl-tabs {
    display: flex;
    flex-direction: column;
    flex: 1 1 0;
    min-height: 0;
}

.stamm-popup .dxbl-tabs-content-panel,
.stamm-popup .dxbl-tabs-content {
    min-height: 0;
}

.stamm-popup .dxbl-tabs-content.dxbl-active {
    display: flex;
    flex-direction: column;
}

/* Höhe kommt jetzt aus der Flex-Kette, nicht mehr aus dem Viewport. Die
   Untergrenze übernimmt MinHeight am Popup selbst. */
.stamm-popup .stamm-tab {
    height: auto;
    min-height: 0;
    flex: 1 1 0;
}

.stamm-tab .stamm-actions {
    flex: 0 0 auto;
    /* Echte Flex-Toolbar statt inline-Block-Fluss: richtet alle Buttons UND die
       inline-flex-Gruppe .zuordnung-copy (Combo + Button) vertikal mittig auf
       gleicher Höhe aus. Vorher liefen sie als inline-Boxen auf der Baseline,
       wodurch die Combo gegenüber den Buttons verrutschte. */
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.3rem;
}

.stamm-tab .dx-alert {
    flex: 0 0 auto;
}

/* StammdatenTab: Captions bleiben LINKS neben den Editoren — DevExpress stellt
   .dxbl-fl-item-horizontal unter 992px rein viewport-basiert auf column
   (nicht platzbasiert); mit den kompakten 90px-Editoren ist links immer Platz.
   Repliziert die Theme-Regeln aus @media (min-width:992px) ohne das Gate;
   Spezifität (0,4,0), damit sie die später ladende Theme-Query schlägt. */
.dxbl-fl.stamm-form .dxbl-fl-item.dxbl-fl-item-horizontal {
    flex-flow: row nowrap;
    --dxbl-fl-caption-padding-x: 0.75rem;
    --dxbl-fl-caption-padding-top: 0.25rem;
    --dxbl-fl-caption-padding-bottom: 0.25rem;
}

/* Caption so breit wie ihr Text, nicht auf feste 96px gestreckt: bei kurzen
   Beschriftungen („Name") stand das Label sonst am linken Rand einer 96px-Box und
   der Editor erst weit rechts davon. Den Abstand macht jetzt allein
   --dxbl-fl-caption-padding-x (0.75rem) — das ist der Theme-Standardabstand.
   Nebeneffekt: die Kopfzeile braucht spürbar weniger Breite, weshalb das Popup
   eine kleinere MinWidth verträgt. */
.dxbl-fl.stamm-form .dxbl-fl-item.dxbl-fl-item-horizontal > .dxbl-fl-cpt {
    flex: 0 0 auto;
    width: auto;
}

/* Kopfzeile ohne Spaltenraster: die beiden schmalen Felder so breit wie ihr Inhalt,
   „Name" nimmt den Rest. Das Item-Raster von DevExpress rechnet sonst in Zwölfteln,
   und ein Viertel muss so breit sein wie „Bilanzstichtag" + Datumsfeld — bei drei
   Feldern nebeneinander treibt das die Mindestbreite des Popups unnötig hoch. */
.dxbl-fl.stamm-form .dxbl-fl-item.stamm-item-fix {
    flex: 0 0 auto;
    width: auto;
    max-width: none;
}

.dxbl-fl.stamm-form .dxbl-fl-item.stamm-item-grow {
    flex: 1 1 auto;
    width: auto;
    max-width: none;
    min-width: 200px;
}

/* StammdatenTab (im DxPopup-Body, daher global statt scoped): kompakte
   Zahlen-/Datums-Editoren. Doppelklasse nötig: das Theme setzt
   .dxbl-text-edit { width:100% } und lädt nach app.css. */
.dxbl-text-edit.stamm-num-edit {
    width: 90px;
}

.dxbl-text-edit.stamm-date-edit {
    width: 110px;
}

.stamm-tab .stamm-grid {
    flex: 1 1 0;
    min-height: 0;
}

/* Datenfehler: Ktonr kommt bei Kontoart < 5 in mehreren Kontoarten vor
   (KontoService.KontenMitMehrfacherKtonr). Zeilenklasse per CustomizeElement im
   KontenTab und in der Saldenliste — global, damit beide ohne ::deep auskommen. Auf
   die Zellen gelegt wie die übrigen Grid-Tönungen; markiert = kräftigeres Rot, damit
   Auswahl und Fehler zugleich lesbar bleiben. */
tr.ktonr-konflikt > td {
    background-color: var(--dxds-color-surface-danger-subdued-rest);
}

tr.ktonr-konflikt.dxbl-grid-selected-row > td {
    background-color: var(--dxds-color-surface-danger-subdued-selected);
    color: var(--dxds-color-content-danger-default-rest);
}

/* StammdatenTab: die Kopfdaten (Klienten-Nr./Name/Stichtag) bleiben so hoch wie
   ihr Inhalt, das Zuordnungs-Grid darunter bekommt den ganzen Rest. */
.stamm-tab .stamm-kopf {
    flex: 0 0 auto;
}

/* Gruppenrahmen um das Zuordnungs-Grid. Bewusst ein eigenes fieldset statt einer
   DxFormLayoutGroup: die Höhe kommt über die Flex-Kette .stamm-tab →
   .stamm-gruppe → .stamm-grid, und die DX-Gruppe schöbe dazwischen mehrere
   eigene Ebenen ohne flex/min-height, an denen die Kette reißt (das Grid wüchse
   dann über den Tab hinaus, statt intern zu scrollen).
   min-height:0 ist Pflicht: Flex-Items haben min-height:auto und ein fieldset
   schrumpft sonst nie unter seinen Inhalt. */
.stamm-tab .stamm-gruppe {
    flex: 1 1 0;
    min-height: 0;
    /* fieldset hat per Default min-width:min-content und wüchse auf die Summe der
       Grid-MinWidths — der Tab (overflow:hidden) schnitte dann rechts ab, statt dass das
       Grid selbst scrollt. Am Handy sichtbar geworden. */
    min-width: 0;
    display: flex;
    flex-direction: column;
    margin: 0;
    padding: 0.25rem 0.5rem 0.5rem;
    border: 1px solid var(--dxbl-border-color, rgba(0, 0, 0, 0.15));
    border-radius: 4px;
}

/* Die Kopf-Gruppe teilt die Optik, aber nicht das Höhenverhalten: sie bleibt so
   hoch wie ihr Inhalt, damit die Zuordnungsgruppe den Rest bekommt. Sie trägt
   keine Legende (der Tab heißt schon „Stammdaten“) — deshalb oben derselbe
   Innenabstand wie unten, sonst klebten die Editoren am Rahmen. */
.stamm-tab .stamm-gruppe-kopf {
    flex: 0 0 auto;
    padding-top: 0.5rem;
}

/* Stammdaten-Tab seit der Adress-Erweiterung: lauter inhaltshohe Gruppen
   (Kopf, Adresse/Kontakt, Rechtliches, Logo) und kein füllendes Grid mehr —
   das lebt im eigenen Standardkonten-Tab. Wird das Popup zu klein, scrollt
   der Tab als Ganzes statt die Gruppen zu quetschen. */
.stamm-tab.stamm-tab-daten {
    overflow-y: auto;
}

/* Gruppen, die (anders als das Zuordnungsgrid) nicht wachsen sollen — gleiche
   Optik wie .stamm-gruppe, aber inhaltshoch. */
.stamm-tab .stamm-gruppe-fix {
    flex: 0 0 auto;
}

/* Standardkonten-Tab: die Grid-Gruppe trägt keine Legende (der Tab heißt schon
   so) — deshalb oben derselbe Innenabstand wie unten, wie bei der Kopf-Gruppe. */
.stamm-tab .stamm-gruppe-ohne-legende {
    padding-top: 0.5rem;
}

/* Zeilenabstand zwischen gestapelten Formular-Zeilen einer Gruppe (Adresse /
   Kontakt: Anschrift-Zeile über Erreichbarkeits-Zeile) — jede Zeile ist ein
   eigenes DxFormLayout, ohne den Abstand stießen die Editoren aneinander. */
.stamm-gruppe .stamm-form + .stamm-form {
    margin-top: 0.5rem;
}

/* Schmale Adress-/Nummernfelder (Doppelklasse gegen das später ladende
   Theme-width:100%, wie stamm-num-edit). */
.dxbl-text-edit.stamm-plz-edit {
    width: 70px;
}

.dxbl-text-edit.stamm-land-edit {
    width: 120px;
}

.dxbl-text-edit.stamm-tel-edit {
    width: 160px;
}

.dxbl-text-edit.stamm-nr-edit {
    width: 150px;
}

/* Logo-Zeile: Vorschau, Entfernen-Knopf und Datei-Auswahl nebeneinander. */
.stamm-logo-zeile {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.75rem;
    padding: 0.25rem 0;
}

.stamm-logo-vorschau {
    max-height: 64px;
    max-width: 220px;
    object-fit: contain;
}

.stamm-logo-fehler {
    color: var(--bs-danger, #dc3545);
}

.stamm-tab .stamm-gruppe > legend {
    /* float:none + width:auto: das Browser-Default für legend nimmt sonst die
       volle Breite und drückt das Grid nach unten. */
    float: none;
    width: auto;
    padding: 0 0.35rem;
    margin: 0;
    font-weight: 600;
    font-size: 0.875rem;
}

/* Konto-Zuordnungsgrid: In jeder Zeile steht dauerhaft eine ComboBox. Sie soll
   ihre Zelle füllen — 220px ist die Breite, ab der „25010 — Nicht fällige
   IST-Vorsteuer aus Teil…" noch etwas Bezeichnung zeigt, statt nur die Nummer.
   Doppelklasse, weil das Theme .dxbl-text-edit später lädt. */
.stamm-zuordnung-grid .dxbl-text-edit.stamm-konto-combo {
    width: 100%;
    min-width: 220px;
}

/* Die Editoren bringen ihre eigene Höhe mit; das übliche Zell-Padding käme
   28-mal obendrauf und machte aus dem Grid eine Scrollstrecke. */
.stamm-zuordnung-grid .dxbl-grid-table > tbody > tr > td {
    padding-top: 0.125rem;
    padding-bottom: 0.125rem;
}

/* UstUebersichtPage Drill-DxPopup (Width=78vw, Height=72vh) — gleicher
   bounded-flex-container Pattern wie .stamm-tab. Globale Regel, weil
   DxPopup seinen Body via JS aus dem Page-Subtree raus-teleportiert und
   scoped CSS dort nicht mehr greift. */
.ust-drill-wrap {
    display: flex;
    flex-direction: column;
    /* Höhe aus der Flex-Kette (aw-popup-flex), nicht aus dem Viewport — das Popup
       ist größenveränderbar; siehe Kommentar bei .aw-popup-flex. */
    flex: 1 1 0;
    min-height: 0;
    width: 100%;
    overflow: hidden;
}

.ust-drill-wrap .ust-drill-grid {
    flex: 1 1 0;
    min-height: 0;
}

/* AddTochterPopup — DxPopup-Body fluid, DxGrid füllt verbleibende Höhe.
   Höhe aus der Flex-Kette (aw-popup-flex), nicht aus dem Viewport. */
.add-tochter-body {
    display: flex;
    flex-direction: column;
    flex: 1 1 0;
    min-height: 0;
    width: 100%;
    overflow: hidden;
}

.add-tochter-body .add-tochter-grid {
    flex: 1 1 0;
    min-height: 0;
}

/* KtobezEditPopup + KonsBuchenPopup — einfaches Label/Value-Layout. */
.ktobez-edit-form,
.kons-buchen-form {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
}

.kons-buchen-form .kons-buchen-row {
    display: grid;
    grid-template-columns: 7rem 1fr;
    align-items: center;
    gap: 0.5rem;
}

.kons-buchen-form .kons-buchen-label {
    font-weight: 600;
}

.ktobez-edit-form .ktobez-edit-hint,
.kons-buchen-form .kons-buchen-hint {
    margin: 0;
    color: var(--dxds-color-content-neutral-subdued-rest);
    font-size: 0.85rem;
}

/* KonsErfolgsCheckPopup — Body fluid, DxGrid füllt verbleibende Höhe. */
.erfkns-check-body {
    display: flex;
    flex-direction: column;
    /* Höhe aus der Flex-Kette (aw-popup-flex), nicht aus dem Viewport. */
    flex: 1 1 0;
    min-height: 0;
    width: 100%;
    overflow: hidden;
    gap: 0.5rem;
}

.erfkns-check-actions {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex: 0 0 auto;
}

.erfkns-check-info {
    margin-left: auto;
    font-size: 0.85rem;
    color: var(--dxds-color-content-neutral-subdued-rest);
}

.erfkns-check-body .erfkns-check-grid {
    flex: 1 1 0;
    min-height: 0;
}

/* KonsolidierungPage-Filter-ComboBox: Item-Template mit ×-Icon zum
   Entfernen gespeicherter Filter. Dropdown-Items werden via Teleport
   ausgespielt → Styles MÜSSEN global stehen, nicht scoped. */
.kons-filter-item {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    width: 100%;
}

.kons-filter-item .kons-filter-item-text {
    flex: 1 1 auto;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.kons-filter-item .kons-filter-item-remove {
    flex: 0 0 auto;
    cursor: pointer;
    padding: 0 0.4rem;
    font-size: 1.1em;
    line-height: 1;
    opacity: 0.45;
    border-radius: 3px;
    user-select: none;
}

.kons-filter-item .kons-filter-item-remove:hover {
    opacity: 1;
    color: var(--dxds-color-content-danger-default-rest);
    background: var(--dxds-color-surface-danger-subdued-rest);
}

/* FirmaCopyPopup / FirmaExportPopup / FirmaLoadPopup — gemeinsames Layout. */
.firma-copy-form {
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
    padding: 0.25rem 0;
}

.firma-copy-row {
    display: grid;
    grid-template-columns: 110px 1fr;
    gap: 0.6rem;
    align-items: center;
}

.firma-copy-group {
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
    border: 1px solid var(--dxds-color-border-neutral-default-rest);
    border-radius: 4px;
    padding: 0.6rem 0.75rem 0.75rem;
    margin: 0;
}

/* Innerhalb von FirmaImport*Forms hat jedes Fieldset sein eigenes Grid mit
   max-content-Label-Spalte. Die einzelnen .firma-copy-row "lösen sich auf"
   (display: contents), sodass alle Labels eines Fieldsets dieselbe Spalte
   teilen und sich auf das breiteste Label dieses Fieldsets einrasten —
   kein fixer 200px-Block mehr, der bei kurzen Labels (Gerstl) lückt. */
.firma-import-form .firma-copy-group {
    display: grid;
    grid-template-columns: max-content 1fr;
    column-gap: 0.6rem;
    row-gap: 0.6rem;
    align-items: center;
}

.firma-import-form .firma-copy-group > :not(.firma-copy-row) {
    grid-column: 1 / -1;
}

.firma-import-form .firma-copy-row {
    display: contents;
}

.firma-copy-group > legend {
    padding: 0 0.4rem;
    font-weight: 600;
    color: var(--dxds-color-content-neutral-default-rest);
}

.firma-copy-filesize {
    color: var(--dxds-color-content-neutral-default-rest);
    font-size: 0.85em;
    margin-left: 0.25rem;
}

.firma-copy-clear {
    margin-left: 0.4rem;
    padding: 0 0.3rem;
    font-size: 0.85em;
    line-height: 1;
}

input[type="file"][disabled] {
    opacity: 0.5;
    cursor: not-allowed;
}

/* Footer-Template-Layout für Popups, die eine Inline-Progress-Anzeige
   (links) neben den Action-Buttons (rechts) zeigen. Verwendet in
   FirmaImportPopup und CreateFirmaPopup. */
.popup-footer-row {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    width: 100%;
}

.popup-footer-progress {
    flex: 1;
    min-width: 0;
}

.popup-footer-buttons {
    display: flex;
    gap: 0.4rem;
    flex-shrink: 0;
}

.firma-copy-group-row {
    display: flex;
    gap: 0.6rem;
    flex-wrap: wrap;
}

.firma-copy-group-row > .firma-copy-group {
    flex: 1 1 0;
    min-width: 200px;
}

/* Zuordnungen enthält nur zwei Buttons → auf Inhaltsbreite schrumpfen, damit die
   dropdown-lastige Importoptionen-Spalte mehr Platz bekommt (Voran-/Gerstl-Import).
   So muss der Popup nicht so breit sein. */
.firma-copy-group-row > .firma-copy-group-zuordnung {
    flex: 0 0 auto;
    min-width: 0;
}

/* Importoptionen (Auswahlfelder/Dropdowns) bekommt den Löwenanteil der Restbreite.
   min-width > 0, sonst wird die Gruppe beim Verengen zerquetscht statt umzubrechen. */
.firma-copy-group-row > .firma-copy-group-wide {
    flex: 2 1 0;
    min-width: 240px;
}

/* Datei-Inputs haben eine intrinsische Breite (~250px) und würden sonst ihre
   Grid-Zelle sprengen, wenn die 1fr-Spalte schmaler wird. */
.firma-import-form input[type="file"] {
    max-width: 100%;
}

/* Schmales Popup (Breite = 96vw): Gruppen der Gruppenzeile und die
   Label-Spalten stapeln, statt zu quetschen. */
@media (max-width: 640px) {
    .firma-copy-group-row {
        flex-direction: column;
    }

    .firma-copy-group-row > .firma-copy-group,
    .firma-copy-group-row > .firma-copy-group-zuordnung,
    .firma-copy-group-row > .firma-copy-group-wide {
        flex: 1 1 auto;
        min-width: 0;
    }

    .firma-import-form .firma-copy-group {
        grid-template-columns: 1fr;
        row-gap: 0.35rem;
    }

    .firma-copy-row {
        grid-template-columns: 1fr;
        row-gap: 0.15rem;
    }
}

.zuordnung-buttons {
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
}

.zuordnung-toolbar {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
    margin-bottom: 0.6rem;
    align-items: center;
}

/* Top-Level damit das „von Klient übernehmen"-Markup sowohl in der
   .zuordnung-toolbar (Zuordnungs-Popups) als auch in .stamm-actions
   (Klienten-Form-Tabs) konsistent gerendert wird. */
.zuordnung-copy {
    display: inline-flex;
    gap: 0.3rem;
    align-items: center;
}

.zuordnung-combo {
    min-width: 220px;
}

/* Den „von Klient übernehmen"-Button nicht schrumpfen lassen und sein Label
   einzeilig halten — sonst quetscht die nicht voll schrumpfende Combo daneben
   den Button zusammen und der Text bricht auf zwei Zeilen um. Child-Kombinator,
   damit nur der direkte Button getroffen wird, nicht die internen
   Chevron-/Clear-Buttons der Combo. */
.zuordnung-copy > .dxbl-btn {
    flex-shrink: 0;
    white-space: nowrap;
}

.zuordnung-grid {
    height: 420px;
}

.firma-copy-label {
    font-weight: 600;
    color: var(--dxds-color-content-neutral-default-rest);
}

.firma-copy-source {
    color: var(--dxds-color-content-neutral-default-rest);
}

.firma-copy-filename {
    font-family: ui-monospace, "SF Mono", "Cascadia Mono", "JetBrains Mono",
        Menlo, Consolas, monospace;
    background: var(--dxds-color-surface-neutral-default-rest);
    padding: 0.15rem 0.5rem;
    border-radius: 4px;
    border: 1px solid var(--dxds-color-border-neutral-default-rest);
    word-break: break-all;
    user-select: all;
}

.firma-copy-filename-input {
    width: 100%;
}

.firma-copy-filename-input .dxbl-text-edit-input {
    font-family: ui-monospace, "SF Mono", "Cascadia Mono", "JetBrains Mono",
        Menlo, Consolas, monospace;
}

/* Plain-HTML <input> Variante (Form-Submit-Pfad) — emuliert das
   DevExpress-TextBox-Aussehen. */
.firma-copy-filename-plain {
    font-family: ui-monospace, "SF Mono", "Cascadia Mono", "JetBrains Mono",
        Menlo, Consolas, monospace;
    width: 100%;
    padding: 0.35rem 0.6rem;
    border: 1px solid var(--dxds-color-border-neutral-default-rest);
    border-radius: 4px;
    background: var(--dxds-color-surface-neutral-default-rest);
    color: var(--dxds-color-content-neutral-default-rest);
    font-size: 0.875rem;
    line-height: 1.3;
    box-sizing: border-box;
}

.firma-copy-filename-plain:focus {
    outline: none;
    border-color: var(--dxds-color-border-focus-default);
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--dxds-color-border-focus-default) 30%, transparent);
}

.firma-copy-actions {
    display: flex;
    justify-content: flex-end;
    padding-top: 0.4rem;
}

.firma-copy-download-btn {
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
    padding: 0.45rem 1rem;
    background: var(--dxds-color-surface-primary-default-rest);
    color: var(--dxds-color-content-neutral-default-inverted-rest);
    border: 1px solid var(--dxds-color-surface-primary-default-rest);
    border-radius: 4px;
    text-decoration: none;
    font-weight: 500;
    font-size: 0.875rem;
    line-height: 1.2;
    cursor: pointer;
    transition: background 0.15s, border-color 0.15s, box-shadow 0.15s;
}

.firma-copy-download-btn:hover {
    background: var(--dxds-color-surface-primary-default-hovered);
    border-color: var(--dxds-color-surface-primary-default-hovered);
    text-decoration: none;
    color: var(--dxds-color-content-neutral-default-inverted-rest);
}

.firma-copy-download-btn:active {
    background: var(--dxds-color-surface-primary-default-active);
}

.firma-copy-download-btn:focus-visible {
    outline: 2px solid var(--dxds-color-border-focus-default);
    outline-offset: 2px;
}

.firma-copy-hint {
    margin: 0.5rem 0 0;
    color: var(--dxds-color-content-neutral-subdued-rest);
    font-size: 0.85rem;
    line-height: 1.35;
}

.firma-copy-warn {
    margin: 0.5rem 0 0;
    padding: 0.5rem 0.75rem;
    border-left: 3px solid var(--dxds-color-border-warning-default-rest);
    background: var(--dxds-color-surface-warning-subdued-rest);
    font-size: 0.85rem;
    line-height: 1.4;
}


/* DxGrid-Summary-Fußzeile, fixierte Spalten: Das Fluent-Theme setzt
   --dxbl-grid-footer-bg auf den TRANSPARENTEN Surface-Token (rgb(… / 0%)) —
   die sticky Fixed-Footer-Zellen (z-index 3) lassen beim horizontalen
   Scrollen daher die durchlaufenden Footer-Zellen durchscheinen; die
   fixierten Gesamtsummen wirken überschrieben (KonsolidierungPage).
   Deckend auf den Grid-Hintergrund heben. Doppelklasse: app.css lädt VOR dem
   per DxResourceManager registrierten Theme, gleiche Spezifität verlöre. */
.dxbl-grid .dxbl-grid-table .dxbl-grid-footer-row > td.dxbl-grid-fixed-cell.dxbl-grid-fixed-cell {
    background: var(--dxbl-grid-bg);
}


/* Touch-Geräte (iPad): Long-Press öffnet das App-Kontextmenü
   (js/touch-contextmenu.js). Die iOS-Systemreaktionen auf langen Fingerdruck
   würden gleichzeitig aufpoppen und den Long-Press "stehlen": das Link-/Bild-
   Callout (body-weit abschalten ist verlustfrei) und die Textauswahl-Lupe —
   letztere nur auf den Kontextmenü-Flächen unterdrücken, damit normaler
   Seitentext (Hilfeseiten) markierbar bleibt. Eingabefelder sind vom Skript
   ohnehin ausgenommen und bleiben selektierbar. */
@media (pointer: coarse) {
    body {
        -webkit-touch-callout: none;
    }

    .dxbl-grid,
    .firmen-tree-container,
    .tree-view,
    .kore-bab-pivot,
    .ilv-matrix {
        -webkit-user-select: none;
        user-select: none;
    }
}

/* „Zuordnen zu…“ (BilanzEditor): die Pfade „AKTIVA › A. … › 1. Konzessionen …“ sind lang, und
   der entscheidende letzte Teil stand rechts abgeschnitten — Einträge umbrechen. Die Liste
   rendert außerhalb des Komponenten-Scopes, daher global über DropDownCssClass. */
.bilanz-zuordnen-liste .dxbl-list-box-item,
.bilanz-zuordnen-liste [role=option] {
    white-space: normal;
}

/* Benutzermenü der TopBar. DxDropDown rendert seinen Inhalt außerhalb des TopBar-Scopes,
   ::deep in TopBar.razor.css greift dort nicht — deshalb global. Die Breite hält das Menü am
   Handy im Bild; lange Zeilen (Anmeldeinfo, Warnung) brechen dafür um. */
.user-dropdown-menu {
    /* width statt max-width: das Dropdown schrumpft sonst auf die Mindestbreite der Wörter. */
    width: min(24rem, calc(100vw - 1rem));
}

/* Selektor spiegelt die DX-core-Regel (white-space: nowrap) plus eine Klasse, sonst verliert er. */
.dxbl-menu.user-dropdown-menu .dxbl-menu-item-list > .dxbl-menu-list-item > .dxbl-menu-item > .dxbl-btn {
    min-width: 0;
    max-width: 100%;
}

.dxbl-menu.user-dropdown-menu .dxbl-menu-item-list > .dxbl-menu-list-item > .dxbl-menu-item > .dxbl-btn > .dxbl-menu-item-text-container .dxbl-menu-item-text {
    white-space: normal;
}

/* Fehlversuche-Warnung: das Item ist disabled (nur Info), soll aber rot auffallen statt grau. */
.user-dropdown-menu .user-menu-warning .dxbl-btn {
    color: #b3261e;
    font-weight: 600;
    opacity: 1;
}

/* ===== Handy-Ansicht (gleiche Query wie wwwroot/js/viewport.js) ===== */
@media (max-width: 767px), (max-height: 500px) and (pointer: coarse) {
    /* Popups. DX setzt Width/MinWidth/MinHeight als Inline-Style, die Desktop-Mindestmaße
       (z. B. MinWidth="620" am Firmenstamm) schoben das Popup samt ✕ und Speichern aus dem
       Bild — daher !important. Kleine Popups (Bestätigungen, Datumsabfragen) behalten ihre
       Größe und werden nur gekappt. */
    dxbl-modal-dialog.dxbl-popup {
        min-width: 0 !important;
        min-height: 0 !important;
        max-height: 100dvh !important;
    }

    /* Querformat (390px hoch): Der Dialog wird auf 100dvh gekappt, der Body schrumpfte als
       Flex-Kind aber nicht mit (min-height:auto) — „Jahresabschluss drucken“ schob so seinen
       Footer mit Drucken/Abbrechen unter den Bildschirmrand, ohne zu scrollen. Jetzt scrollt
       der Body, der Footer bleibt stehen. */
    dxbl-modal-dialog.dxbl-popup > .dxbl-modal-content {
        min-height: 0;
        max-height: 100dvh;
    }

    dxbl-modal-dialog.dxbl-popup > .dxbl-modal-content > .dxbl-modal-body {
        min-height: 0;
        overflow-y: auto;
    }

    /* Kontextmenüs (und deren Untermenüs) auf den Viewport kappen: das Firmenmenü ist mit
       24 Einträgen 635px hoch und lag im Querformat bei top -245px — die oberen neun Einträge
       waren unerreichbar. DX hat innen schon einen scrollenden Bereich
       (.dxbl-scroll-viewer-content), es fehlte nur die Höhengrenze außen; DX positioniert
       das gekappte Menü dann selbst ins Bild. */
    dxbl-itemlist-dropdown.dxbl-itemlist-dropdown {
        max-height: calc(100dvh - 16px) !important;
    }

    /* Kleine Popups: DX hält 28px Rand (--dxbl-popup-margin) zum Viewport, die Breite
       (meist min(…px, 96vw)) rechnet den Rand aber nicht ein — sie ragten rechts 12px,
       „Firma kopieren“ (560px) sogar 28px samt ✕ und Abbrechen aus dem Bild. Am Handy:
       8px Rand und Breite höchstens Viewport minus Rand. */
    dxbl-modal-dialog.dxbl-popup:not([class*="aw-pl-"]) {
        --dxbl-popup-margin: 8px;
        max-width: calc(100vw - 16px) !important;
    }

    /* Die großen, verschieb-/größenveränderbaren Popups (aw-pl-*, siehe popup-layout.js)
       werden bildschirmfüllend. transform/margin neutralisieren eine DX-Drag-Position; die
       Variable hebt die DX-Kappe des Inhalts (Viewport minus 2× Popup-Rand) bei Scrollable
       auf, sonst endet der weiße Inhalt ~50px vor dem unteren Rand. */
    dxbl-modal-dialog.dxbl-popup[class*="aw-pl-"] {
        width: 100vw !important;
        height: 100dvh !important;
        margin: 0 !important;
        transform: none !important;
        --dxbl-popup-scrollable-max-height: 100dvh;
    }

    dxbl-modal-dialog.dxbl-popup[class*="aw-pl-"] > .dxbl-modal-content {
        height: 100%;
        border-radius: 0;
    }

    /* Buchen-Popup: der Body scrollt als Ganzes (Grid mit fester Höhe + einspaltige
       Eingabe, siehe BuchungsPopup.razor.css). flex-shrink:0, sonst quetschte die
       Flex-Spalte von aw-popup-flex das Formular, statt zu scrollen. */
    .aw-pl-buchungen.aw-popup-flex .dxbl-modal-body {
        overflow-y: auto;
    }

    .aw-pl-buchungen.aw-popup-flex .dxbl-modal-body > * {
        flex-shrink: 0;
    }

    /* Zuordnungs-Popups: Klient-Auswahl + „von Klient übernehmen“ als eigene volle Zeile unter
       „Einzelnachweis einlesen“ + „Weitere“ (statt vier umbrechender Zeilen); die Combo
       schrumpft statt ihrer 220px-Mindestbreite. Nur in .zuordnung-toolbar — dieselbe
       .zuordnung-copy steht auch in den Stammdaten-Leisten. */
    .zuordnung-toolbar > .zuordnung-copy {
        order: 1;
        flex: 1 1 100%;
        min-width: 0;
    }

    .zuordnung-toolbar > .zuordnung-copy > .zuordnung-combo {
        flex: 1 1 auto;
        min-width: 0;
    }

    /* StammdatenTab einspaltig: Beschriftung über dem Feld, ein Feld pro Zeile. Hebt die
       Desktop-Regeln oben auf (Captions links, natürliche Breiten nebeneinander). */
    .dxbl-fl.stamm-form .dxbl-fl-item.dxbl-fl-item-horizontal {
        flex-flow: column nowrap;
        align-items: stretch;
    }

    .dxbl-fl.stamm-form .dxbl-fl-item.stamm-item-fix,
    .dxbl-fl.stamm-form .dxbl-fl-item.stamm-item-grow {
        flex: 1 1 100%;
        width: 100%;
        min-width: 0;
    }

    /* Stammdaten-Grid-Tabs (StammAktionsLeiste): die Kopier-Gruppe (Firmen-Picker +
       „von Klient übernehmen“) bekommt eine eigene volle Zeile, der Picker den Rest neben
       dem Knopf statt seiner Desktop-Mindestbreite von 220px. */
    .stamm-actions-block {
        flex: 1 1 100%;
        min-width: 0;
    }

    .stamm-actions-block .zuordnung-copy {
        display: flex;
        width: 100%;
    }

    .stamm-actions-block .zuordnung-combo {
        flex: 1 1 auto;
        min-width: 0;
    }

    /* Standardkonten-Tab: die Desktop-Mindestbreite der Konto-Combo (220px) ragte über die
       am Handy schmalere Konto-Spalte hinaus (StandardkontenTab: MinWidth 150). */
    .stamm-zuordnung-grid .dxbl-text-edit.stamm-konto-combo {
        min-width: 0;
    }

    .dxbl-text-edit.stamm-num-edit,
    .dxbl-text-edit.stamm-date-edit,
    .dxbl-text-edit.stamm-plz-edit,
    .dxbl-text-edit.stamm-land-edit,
    .dxbl-text-edit.stamm-tel-edit,
    .dxbl-text-edit.stamm-nr-edit {
        width: 100%;
    }
}
