/* ==========================================================================
   S3.DocCenter – Theme & Base Styles
   Based on S3.NorthDataAutoExporter design system
   ========================================================================== */

/* ---------- CSS Custom Properties ---------- */

:root {
    --font-size: 16px;
    --background: #fafafa;
    --foreground: #1f1f1f;
    --card: #ffffff;
    --card-foreground: #1f1f1f;
    --popover: #ffffff;
    --popover-foreground: #1f1f1f;
    --primary: #0C5DA6;
    --primary-foreground: #ffffff;
    --secondary: #f5f5f5;
    --secondary-foreground: #1f1f1f;
    --muted: #f0f0f0;
    --muted-foreground: #6b6b6b;
    --accent: #e6f7ff;
    --accent-foreground: #0C5DA6;
    --destructive: #ff4444;
    --destructive-foreground: #ffffff;
    --border: #e8e8e8;
    --input: transparent;
    --input-background: #ffffff;
    --font-weight-medium: 500;
    --font-weight-normal: 400;
    --ring: #0C5DA6;
    --radius: 0;
    --sidebar: #333333;
    --sidebar-foreground: #e8e8e8;
    --sidebar-primary: #0C5DA6;
    --sidebar-primary-foreground: #ffffff;
    --sidebar-accent: #3a3a3a;
    --sidebar-accent-foreground: #ffffff;
    --sidebar-border: #444444;
    --sidebar-ring: #0C5DA6;
    --sidebar-submenu: #2b2b2b;
}

/* ---------- Base styles ---------- */

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

html, body {
    height: 100vh;
}

/* PDF.js erstellt versteckte Off-Screen-Canvases als Body-Children.
   Diese Canvases haben height:0 aber position im Dokument, was scrollHeight erhöht. */
body > canvas {
    position: fixed;
    top: 0;
    left: 0;
    pointer-events: none;
}

html {
    font-size: var(--font-size);
}

body {
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
    font-size: 1rem;
    font-weight: var(--font-weight-normal);
    line-height: 1.5;
    color: var(--foreground);
    background-color: var(--background);
}

h1 {
    font-size: 1.5rem;
    font-weight: var(--font-weight-medium);
    line-height: 1.5;
    border: none;
    outline: none;
}

h2 {
    font-size: 1.25rem;
    font-weight: var(--font-weight-medium);
    line-height: 1.5;
}

h3 {
    font-size: 1.125rem;
    font-weight: var(--font-weight-medium);
    line-height: 1.5;
}

h4 {
    font-size: 1rem;
    font-weight: var(--font-weight-medium);
    line-height: 1.5;
}

label {
    font-size: 1rem;
    font-weight: var(--font-weight-medium);
    line-height: 1.5;
}

button {
    font-size: 1rem;
    font-weight: var(--font-weight-medium);
    line-height: 1.5;
    cursor: pointer;
}

input {
    font-size: 1rem;
    font-weight: var(--font-weight-normal);
    line-height: 1.5;
}

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

a:hover {
    text-decoration: underline;
}

/* ---------- Shadow utilities ---------- */

.shadow-header {
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
}

.shadow-sidebar {
    box-shadow: 2px 0 8px rgba(0, 0, 0, 0.12);
}

.shadow-actionbar {
    box-shadow: 0 -1px 4px rgba(0, 0, 0, 0.06);
}

.shadow-card {
    box-shadow: 0 1px 6px rgba(0, 0, 0, 0.10);
}

.shadow-button {
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
}

.shadow-dropdown {
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);
}

/* ---------- Layout ---------- */

.layout {
    display: flex;
    flex: 1;
    overflow: hidden;
}

.sidebar {
    background-color: var(--sidebar);
    color: var(--sidebar-foreground);
    display: flex;
    flex-direction: column;
    flex-shrink: 0;
}

.sidebar-animating {
    transition: width 0.2s ease;
}

.sidebar-collapsed {
    width: 64px;
}

.header {
    height: 68px;
    background-color: var(--card);
    border-bottom: 1px solid var(--border);
    display: flex;
    align-items: center;
    padding: 0 1.5rem;
    gap: 1rem;
}

.action-bar {
    background-color: var(--card);
    padding: 0.5rem 2rem;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    flex-wrap: wrap;
    flex-shrink: 0;
    min-height: 48px;
    margin-top: 1rem;
    box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.10), 0 2px 10px rgba(0, 0, 0, 0.10);
    position: relative;
}

.action-bar-loader {
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    height: 3px;
    background-color: color-mix(in srgb, var(--primary) 15%, transparent);
    overflow: hidden;
    opacity: 0;
    transition: opacity 0.3s ease;
}

.action-bar-loader.active {
    opacity: 1;
}

.action-bar-loader::after {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    height: 100%;
    width: 40%;
    background-color: var(--primary);
    animation: actionbar-loading 1.2s ease-in-out infinite;
}

@keyframes actionbar-loading {
    0%   { left: -40%; }
    100% { left: 100%; }
}

.content-area {
    flex: 1;
    padding: 2rem;
    overflow-y: auto;
    width: 100%;
}

/* ---------- Content-Container (max-width + zentriert) ---------- */

/* Container-Varianten — die jeweilige Page wraps ihren Top-Level-Inhalt
   mit einer dieser Klassen. Breite steht statisch im Markup, kein
   Runtime-State, kein Page-Wechsel-Flicker. */
.container-narrow,
.container-standard,
.container-wide,
.container-full {
    width: 100%;
    margin: 0 auto;
}

.container-narrow   { max-width: 720px;  }
.container-standard { max-width: 1040px; }
.container-wide     { max-width: 1584px; }
.container-full     { max-width: none;   }

/* ---------- Status badges ---------- */

.badge {
    display: inline-flex;
    align-items: center;
    padding: 0.125rem 0.5rem;
    font-size: 0.75rem;
    font-weight: var(--font-weight-medium);
    border-radius: 9999px;
    white-space: nowrap;
}

.badge-success {
    background-color: #dcfce7;
    color: #166534;
}

.badge-warning {
    background-color: #fef9c3;
    color: #854d0e;
}

.badge-error {
    background-color: #fee2e2;
    color: #991b1b;
}

.badge-primary {
    background-color: color-mix(in srgb, var(--primary) 12%, transparent);
    color: var(--primary);
}

.badge-muted {
    background-color: var(--muted);
    color: var(--muted-foreground);
}

/* Pille, die einem Text in derselben Zelle nachgestellt ist - etwa das
   Gruppenkennzeichen hinter dem Besuchernamen. Ohne eigenen Abstand steht sie
   nur um das Leerzeichen aus dem Markup versetzt und klebt am Namen. */
.badge-nachgestellt {
    margin-left: 0.5rem;
}

/* ---------- Tables ---------- */

.data-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.875rem;
}

.data-table th {
    text-align: left;
    padding: 0.625rem 0.75rem;
    font-weight: var(--font-weight-medium);
    color: var(--muted-foreground);
    border-bottom: 2px solid var(--border);
    white-space: nowrap;
    /* Label oben verankern, damit Spalten ohne Filter dasselbe Label-Y
       haben wie Spalten mit Filter (sonst zentriert die default
       vertical-align: middle das Label in der Zelle). */
    vertical-align: top;
}

.data-table td {
    padding: 0.625rem 0.75rem;
    border-bottom: 1px solid var(--border);
    vertical-align: middle;
}

.data-table tbody tr:nth-child(odd) {
    background-color: var(--background);
}

.data-table tbody tr:nth-child(even) {
    background-color: var(--card);
}

.data-table tbody tr:hover {
    background-color: var(--muted);
}

/* Klickbare Zeile — Cursor-Pointer als visuelle Affordance fuer
   Row-Click-Navigation. Action-Buttons in der Zelle haben
   `@onclick:stopPropagation`, damit sie nicht doppelt navigieren. */
.data-table tbody tr.clickable {
    cursor: pointer;
}

/* Fixed Layout — Spaltenbreiten werden aus <col>-Elementen übernommen,
   erlaubt sticky Header ohne Spalten-Verschiebung, schneidet lange
   Inhalte per `text-overflow: ellipsis` in Zellen mit `overflow: hidden`. */
.data-table.data-table-fixed {
    table-layout: fixed;
}

/* Header-Zelle: 2-zeilig — oben Label+Sort, unten Filter-Input/Select */
.data-table .th-label {
    display: flex;
    align-items: center;
    gap: 0.375rem;
    padding: 0.125rem 0;
    user-select: none;
}

.data-table .th-label.sortable {
    cursor: pointer;
}

.data-table .th-label.sortable:hover {
    color: var(--foreground);
}

.data-table .sort-icon {
    opacity: 0.45;
    flex-shrink: 0;
}

.data-table .sort-icon.sort-active {
    opacity: 1;
    color: var(--primary);
}

/* Robustes Safety-Net: greift auch dann, wenn ein Projekt das Sort-Icon ohne
   `sort-icon`-Klasse rendert (nur `icon-sm`) — passierte unabhängig in VDZ +
   HYTORC. Stylt direkt das svg im sortierbaren Header: inaktiv dezenter Grauton,
   aktiv hervorgehoben (egal ob `sort-active` am DIV oder am Icon hängt). */
.data-table .th-label.sortable svg {
    color: var(--muted-foreground);
    opacity: 0.4;
}

.data-table .th-label.sortable.sort-active svg,
.data-table .th-label.sortable svg.sort-active {
    color: var(--primary);
    opacity: 1;
}

.data-table .th-filter-input,
.data-table .th-filter-select {
    width: 100%;
    margin-top: 0.375rem;
    padding: 0.375rem 0.5rem;
    height: 34px;
    box-sizing: border-box;
    font-size: 0.8125rem;
    /* Formularelemente erben die Schriftart nicht von selbst. Ohne diese Zeile
       lief die ganze Filterzeile in Arial, waehrend die Tabelle darunter im
       Systemstack stand - in sich stimmig und deshalb schwer zu bemerken. */
    font-family: inherit;
    font-weight: var(--font-weight-normal);
    border: 1px solid var(--border);
    background-color: var(--card);
    color: var(--foreground);
    border-radius: var(--radius);
    outline: none;
    transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.data-table .th-filter-input:focus,
.data-table .th-filter-select:focus {
    border-color: var(--primary);
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--primary) 15%, transparent);
}

.data-table .th-filter-input.is-active,
.data-table .th-filter-select.is-active {
    border-color: var(--primary);
    background-color: color-mix(in srgb, var(--primary) 4%, var(--card));
}

.data-table .th-filter-select {
    appearance: none;
    -webkit-appearance: none;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23888' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><polyline points='6 9 12 15 18 9'/></svg>");
    background-repeat: no-repeat;
    background-position: right 0.375rem center;
    background-size: 14px;
    padding-right: 1.5rem;
}

/* Select wirkt wie Placeholder solange "Alle" gewählt ist (kein .is-active).
   Optionen im Dropdown bleiben in der normalen Schriftfarbe. */
.data-table .th-filter-select:not(.is-active) {
    color: var(--muted-foreground);
}

.data-table .th-filter-select option {
    color: var(--foreground);
}

/* ----- Filter-Input mit ×-Clear-Button -----
   Wrap übernimmt margin-top vom Input, damit der absolut positionierte
   Clear-Button vertikal mittig im Input sitzt (sonst rutscht er um halben
   Margin nach unten). */
.th-filter-wrap {
    position: relative;
    display: flex;
    align-items: center;
    margin-top: 0.375rem;
}

.th-filter-wrap .th-filter-input {
    flex: 1;
    margin-top: 0;
    padding-right: 1.75rem;
}

.th-filter-clear {
    position: absolute;
    right: 0.375rem;
    top: 50%;
    transform: translateY(-50%);
    display: flex;
    align-items: center;
    justify-content: center;
    width: 18px;
    height: 18px;
    background: var(--muted);
    border: none;
    border-radius: 50%;
    color: var(--muted-foreground);
    cursor: pointer;
    font-size: 0.75rem;
    font-weight: 600;
    line-height: 1;
    padding: 0;
    transition: background-color 0.15s, color 0.15s;
}

.th-filter-clear:hover {
    background: var(--destructive);
    color: #fff;
}

/* ===== Datum-Filter (Popover am Spalten-Header) =====
   Trigger ist ein <div> in der th-Zelle, Popover öffnet via JS-Interop
   (popover-position.js) als position:fixed. Pflicht: font-weight: 400 am
   Trigger, sonst erbt er die 500 von ".data-table th" und der "Zeitraum …"-
   Placeholder wirkt fetter als die Text-Filter-Placeholder daneben. */
.th-date-col {
    position: relative;
    overflow: visible;
}

.th-date-trigger {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.25rem;
    width: 100%;
    margin-top: 0.375rem;
    padding: 0.375rem 0.5rem;
    height: 34px;
    box-sizing: border-box;
    font-size: 0.8125rem;
    font-weight: 400;
    border: 1px solid var(--border);
    background-color: var(--card);
    border-radius: var(--radius);
    color: var(--muted-foreground);
    cursor: pointer;
    transition: border-color 0.15s ease;
}

.th-date-trigger:hover {
    border-color: var(--primary);
}

.th-date-trigger.has-value {
    color: var(--foreground);
}

.th-date-trigger.is-active {
    border-color: var(--primary);
    background-color: color-mix(in srgb, var(--primary) 4%, var(--card));
}

.th-date-display {
    flex: 1;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.date-chevron {
    margin-left: auto;
    flex-shrink: 0;
    display: flex;
    align-items: center;
    color: #999;
}

.date-popover-overlay {
    position: fixed;
    inset: 0;
    z-index: 49;
}

.date-popover-container {
    display: grid;
    grid-template-columns: auto auto;
    background: var(--card);
    border: 1px solid var(--border);
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.14);
}

.date-popover-presets {
    padding: 0.5rem;
    display: flex;
    flex-direction: column;
    gap: 0.125rem;
    min-width: 170px;
    border-right: 1px solid var(--border);
    flex-shrink: 0;
}

.date-presets-title {
    font-size: 0.75rem;
    font-weight: 600;
    color: var(--muted-foreground);
    text-transform: uppercase;
    letter-spacing: 0.03em;
    padding: 0.25rem 0.5rem 0.375rem;
}

.date-preset-btn {
    font-size: 0.8125rem;
    padding: 0.4rem 0.625rem;
    background: none;
    border: none;
    text-align: left;
    cursor: pointer;
    color: var(--foreground);
    white-space: nowrap;
}

.date-preset-btn:hover {
    background: var(--muted);
}

.date-preset-btn.active {
    background: color-mix(in srgb, var(--primary) 10%, transparent);
    color: var(--primary);
    font-weight: 500;
}

.date-popover {
    padding: 0.75rem;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    min-width: 220px;
}

.date-popover-row {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

.date-popover-row label {
    font-size: 0.75rem;
    color: var(--muted-foreground);
    width: 28px;
    flex-shrink: 0;
}

.date-popover-row .date-input {
    flex: 1;
    min-width: 0;
    margin-top: 0;
}

/* Uhrzeitfeld neben dem Datum, nur in Spalten mit Uhrzeit (STANDARDS.md 3.2,
   Referenz S3.NorthDataAutoExporter). Die Klasse wird dort und im Standard
   verwendet, ist aber in keiner app.css definiert - Kandidat fuer den
   Rueckfluss. Feste Breite, damit das Datum die Zeile bestimmt und die
   Uhrzeit nicht mitwaechst. */
.date-popover-row .time-input {
    flex: 0 0 6.5rem;
    min-width: 0;
    margin-top: 0;
}

/* Mit Uhrzeit braucht die Formularhaelfte mehr Platz, sonst quetschen sich
   Datum und Uhrzeit in dieselbe Breite wie vorher das Datum allein. */
.date-popover-container.hat-uhrzeit .date-popover {
    min-width: 21rem;
}

.date-popover-actions {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin-top: 0.25rem;
    border-top: 1px solid var(--border);
    padding-top: 0.5rem;
}

.date-popover-apply {
    flex: 1;
    font-size: 0.75rem;
    padding: 0.4rem 0.75rem;
    background: var(--primary);
    color: var(--primary-foreground);
    border: 1px solid var(--primary);
    border-radius: var(--radius);
    cursor: pointer;
    text-align: center;
}

.date-popover-apply:hover {
    opacity: 0.9;
}

.date-popover-clear {
    font-size: 0.75rem;
    color: var(--muted-foreground);
    background: none;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    cursor: pointer;
    padding: 0.4rem 0.75rem;
}

.date-popover-clear:hover {
    color: var(--foreground);
    border-color: var(--foreground);
}

/* Optionale Selected-Row-Markierung — 3px Primary-Border links + leichter
   Primary-Tint. Wird auf `<tr class="selected">` angewendet. */
.data-table tbody tr.selected {
    background-color: color-mix(in srgb, var(--primary) 8%, var(--card)) !important;
    box-shadow: inset 3px 0 0 var(--primary);
}

/* Empty-State-Zeile innerhalb der Tabelle */
.data-table .empty-state-row td {
    padding: 2.5rem 0.75rem;
}

.empty-state {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.75rem;
    color: var(--muted-foreground);
    text-align: center;
}

/* Zelle mit Ellipsis — funktioniert nur in data-table-fixed (table-layout: fixed). */
.data-table .cell-ellipsis {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Action-Spalte (icon-only Buttons rechts in der Zeile). Header-Label und
   Body-Buttons rechtsbündig. Gap entsteht durch margin-left an Buttons,
   damit der `<td>` als table-cell-Layout intakt bleibt. */
.data-table .cell-actions {
    text-align: right;
    white-space: nowrap;
}

.data-table td.cell-actions .action-btn + .action-btn {
    margin-left: 0.25rem;
}

/* ---------- Cards ---------- */

.card {
    background-color: var(--card);
    color: var(--card-foreground);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: 0 1px 6px rgba(0, 0, 0, 0.10);
    width: 100%;
}

.card-header {
    padding: 1rem 1.25rem;
    border-bottom: 1px solid var(--border);
    font-weight: var(--font-weight-medium);
}

/* ---------- Buttons ---------- */

.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    padding: 0.5rem 1rem;
    font-size: 0.875rem;
    font-weight: var(--font-weight-medium);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background-color: var(--card);
    color: var(--foreground);
    cursor: pointer;
    transition: background-color 0.15s ease, border-color 0.15s ease;
    text-decoration: none;
}

.btn:hover {
    background-color: var(--muted);
}

.btn:disabled,
.btn[disabled] {
    opacity: 0.5;
    cursor: not-allowed;
    pointer-events: none;
}

.btn-primary {
    background-color: var(--primary);
    color: var(--primary-foreground);
    border-color: var(--primary);
}

.btn-primary:hover {
    background-color: color-mix(in srgb, var(--primary) 85%, #000);
    border-color: color-mix(in srgb, var(--primary) 85%, #000);
}

/* Speichern-Rueckmeldung am Knopf selbst (STANDARDS 3.19), nicht als Toast.
   Gruen aus HYTORC.LizenzService uebernommen (5,27:1 auf Weiss), Rot ist der
   Destructive-Wert aus STANDARDS 1 Farben (5,62:1) - beide ueber 4,5:1. */
.btn--saved,
.btn-primary.btn--saved,
.btn-primary.btn--saved:hover {
    background-color: #0a7d2c;
    border-color: #0a7d2c;
    color: #fff;
}

.btn--saved .icon-sm {
    animation: btn-saved-pop 0.35s cubic-bezier(0.34, 1.56, 0.64, 1);
}

@keyframes btn-saved-pop {
    0%   { transform: scale(0.4) rotate(-20deg); opacity: 0; }
    60%  { transform: scale(1.2) rotate(5deg); opacity: 1; }
    100% { transform: scale(1) rotate(0); opacity: 1; }
}

.btn--failed,
.btn-primary.btn--failed,
.btn-primary.btn--failed:hover {
    background-color: #c62828;
    border-color: #c62828;
    color: #fff;
}

.btn-secondary {
    background-color: var(--card);
    color: var(--foreground);
    border-color: var(--border);
}

.btn-secondary:hover {
    background-color: var(--muted);
}

.btn-danger {
    background-color: var(--destructive);
    color: var(--destructive-foreground);
    border-color: var(--destructive);
}

.btn-danger:hover {
    background-color: #e03030;
    border-color: #e03030;
}

.btn-sm {
    padding: 0.25rem 0.5rem;
    font-size: 0.8125rem;
}

.action-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    padding: 0;
    border: 1px solid transparent;
    border-radius: var(--radius);
    background: transparent;
    color: var(--foreground);
    cursor: pointer;
    transition: background-color 0.15s ease, color 0.15s ease;
}

.action-btn:hover {
    background-color: var(--muted);
}

.action-btn-danger:hover {
    background-color: #fee2e2;
    color: var(--destructive);
}

.action-bar-title {
    font-size: 1.125rem;
    font-weight: var(--font-weight-medium);
    line-height: 1.5;
    white-space: nowrap;
    border: none;
    outline: none;
    margin: 0;
    padding: 0;
}

.action-bar-title-with-back {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    min-width: 0;
}

/* ---------- Forms ---------- */

.form-input {
    width: 100%;
    padding: 0.5rem 0.75rem;
    font-size: 0.875rem;
    font-family: inherit;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background-color: var(--input-background);
    color: var(--foreground);
    outline: none;
    transition: border-color 0.15s ease;
}

/* Gleiche Hoehe fuer alles Einzeilige.
   Ohne sie standen drei Hoehen nebeneinander: Textfeld 39px, select 36px,
   datetime-local 41px. Padding und Rahmen sind ueberall gleich - der
   Unterschied kommt aus dem, was der Browser innen selbst beisteuert
   (Zeilenhoehe "normal" beim select, eigene Innenteile beim Datumsfeld).
   Dagegen hilft nur eine gesetzte Hoehe.

   Die Rechnung stammt aus den Werten darueber und bleibt richtig, wenn sie
   sich aendern: 1.5em Zeilenhoehe + 2x0.5rem Innenabstand + 2x1px Rahmen.

   Nur input und select, nicht textarea: Die traegt dieselbe Klasse und lebt
   von ihrer Zeilenzahl. */
input.form-input,
.form-select {
    height: calc(1.5em + 1rem + 2px);
    line-height: 1.5;
}

.form-input:focus {
    border-color: var(--ring);
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--ring) 15%, transparent);
}

.form-input[readonly],
.form-input:read-only {
    background-color: var(--background);
    color: var(--muted-foreground);
    cursor: default;
    border-color: var(--border);
}

.form-input[readonly]:focus,
.form-input:read-only:focus {
    border-color: var(--border);
    box-shadow: none;
}

/* Volle Spaltenbreite wie die Textfelder. Ohne Angabe passt sich ein select an
   seine laengste Option an - dann steht in einer zweispaltigen Zeile ein
   169px-Feld neben einem 269px-Feld, und die Zeile sieht aus, als waere sie
   falsch zusammengesetzt. Der Inhalt ist ausserdem variabel: Gastgeber und
   Besuchsgruende pflegt der Kunde selbst. */
.form-select {
    width: 100%;
    padding: 0.5rem 0.75rem;
    font-size: 0.875rem;
    /* Ein select erbt die Schriftart nicht von selbst - ohne diese Zeile stand
       es in Arial, waehrend daneben der Systemstack lief. Fiel als
       Hoehenunterschied auf, bevor es als Schriftunterschied auffiel. */
    font-family: inherit;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background-color: var(--input-background);
    color: var(--foreground);
    outline: none;
    cursor: pointer;
}

/* Ausnahme fuer feste Aufzaehlungen aus dem Code - Sprache, Rolle, Status.
   Die wachsen nicht mit den Daten des Kunden, und "Deutsch" in einem Feld ueber
   die halbe Zeile ist derselbe leere Platz wie bei einem Datum. Gastgeber und
   Besuchsgruende bleiben bei voller Breite: Die pflegt der Kunde, und der
   naechste Eintrag kann laenger sein als alle bisherigen. */
.form-select-kurz {
    width: auto;
    min-width: 10rem;
}

.form-select:focus {
    border-color: var(--ring);
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--ring) 15%, transparent);
}

.form-label {
    display: block;
    margin-bottom: 0.375rem;
    font-size: 0.875rem;
    font-weight: var(--font-weight-medium);
    color: var(--foreground);
}

.checkbox-label {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    cursor: pointer;
    font-size: 0.875rem;
    color: var(--foreground);
}

.form-actions {
    display: flex;
    gap: 0.5rem;
    justify-content: flex-end;
    margin-top: 0.5rem;
}

.form-group {
    margin-bottom: 0.875rem;
}

/* Zwei Felder nebeneinander. Bricht unter 560px um - im Modal ist das die
   Breite, ab der zwei Spalten zu schmal fuer eine Firmenbezeichnung werden. */
.form-row {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 0.75rem;
}

@media (max-width: 560px) {
    .form-row {
        grid-template-columns: 1fr;
    }
}

/* Zwischenueberschrift im Formular - gliedert lange Eingabemasken.
   Herkunft: DEVEX.CRM (.detail-abschnitt). */
.form-abschnitt {
    margin: 1.25rem 0 0.75rem;
    padding-top: 0.875rem;
    border-top: 1px solid var(--border);
    font-size: 0.875rem;
    font-weight: var(--font-weight-medium);
    color: var(--muted-foreground);
}

.form-abschnitt:first-child {
    margin-top: 0;
    padding-top: 0;
    border-top: none;
}

/* Erlaeuterung unter einem Feld - traegt die Begruendung, die sonst nur im
   Code steht (z.B. warum die PIN an die hinterlegte Adresse geht). */
/* Abstand nach oben fuer einen Block, der sonst am vorigen klebt - etwa eine
   Fehlermeldung unter dem letzten Feld. Vier Seiten benutzten dafuer
   ".portal-abstand-oben"; die Klasse steht aber nur im Stylesheet des Portals
   und blieb hier wirkungslos. */
.feld-abstand-oben {
    margin-top: 1rem;
}

.form-hinweis {
    margin: 0.375rem 0 0;
    font-size: 0.75rem;
    line-height: 1.4;
    color: var(--muted-foreground);
}

/* Fehlerbanner im Formular. Farblich identisch zu .login-error - der Standard
   sieht dafuer den Namen .alert-error vor; .login-error wird beim naechsten
   Touch der Login-Seiten darauf umgestellt. */
.alert-error {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.625rem 1rem;
    background-color: #fee2e2;
    color: #991b1b;
    font-size: 0.875rem;
    border-radius: var(--radius);
}

/* ---------- Treffervorschlag (OP-3) ---------- */
/* Der Vorschlag steht im Formularfluss, nicht als eigenes Modal: er ist eine
   Rueckfrage zur laufenden Eingabe, kein neuer Vorgang. */

.vorschlag {
    margin: 0.25rem 0 0.875rem;
    padding: 0.75rem 0.875rem;
    background-color: var(--background);
    border: 1px solid var(--border);
    border-left: 3px solid var(--primary);
    border-radius: var(--radius);
}

.vorschlag-bestaetigt {
    border-left-color: #0a7d2c;
}

.vorschlag-kopf {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-size: 0.8125rem;
    font-weight: var(--font-weight-medium);
    color: var(--muted-foreground);
}

.vorschlag-person {
    margin-top: 0.375rem;
    font-size: 0.9375rem;
}

.vorschlag-detail {
    margin-top: 0.125rem;
    font-size: 0.8125rem;
    color: var(--muted-foreground);
}

/* Auswaehlbarer Kandidat. Ein <button>, kein <div> mit Klick: Tastatur und
   Vorlesesoftware brauchen ein Bedienelement, kein angeklicktes Rechteck. */
.vorschlag-zeile {
    display: block;
    width: 100%;
    margin-top: 0.5rem;
    padding: 0.5rem 0.625rem;
    text-align: left;
    background-color: var(--card);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    font: inherit;
    cursor: pointer;
}

.vorschlag-zeile:hover {
    border-color: var(--primary);
    background-color: color-mix(in srgb, var(--primary) 4%, var(--card));
}

.vorschlag-zeile .vorschlag-person,
.vorschlag-zeile .vorschlag-detail {
    display: block;
    margin-top: 0;
}

.vorschlag-aktionen {
    display: flex;
    gap: 0.5rem;
    margin-top: 0.75rem;
}

/* Nebensaechliche Aktion im Fliesstext - kein Knopf, damit sie nicht mit den
   beiden Entscheidungen darueber konkurriert. */
.btn-link {
    padding: 0;
    border: none;
    background: none;
    font: inherit;
    color: var(--primary);
    text-decoration: underline;
    cursor: pointer;
}

/* Aktion in einer Tabellenzeile - steht unter dem Zustand, nicht daneben, damit
   die schmale Spalte nicht bricht. */
.zeile-aktion {
    display: block;
    margin-top: 0.25rem;
    font-size: 0.75rem;
}

.btn-link:hover {
    color: color-mix(in srgb, var(--primary) 85%, #000);
}

/* Zwei Karten untereinander auf derselben Seite. */
.karte-abstand {
    margin-top: 1.25rem;
}

/* ---------- Sortieren per Ziehen ---------- */

.rang-zelle {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

/* Der Anfasser ist das Einzige, was gezogen wird - deshalb traegt er den
   Greifcursor und die Zeile nicht. */
.griff {
    cursor: grab;
    color: var(--muted-foreground);
    font-size: 1rem;
    line-height: 1;
    padding: 0.125rem 0.25rem;
    user-select: none;
}

.griff:active {
    cursor: grabbing;
}

/* Ausgeschaltet, solange die Liste nicht in Rangfolge steht - dann sagt die
   Bildschirmreihenfolge nichts ueber den Rang. */
.griff-aus {
    cursor: default;
    opacity: 0.35;
}

.griff-aus:active {
    cursor: default;
}

.rang-eingabe {
    width: 3.25rem;
    padding: 0.25rem 0.375rem;
    font-size: 0.875rem;
    font-family: inherit;
    text-align: center;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background-color: var(--input-background);
    color: var(--foreground);
}

.rang-eingabe:focus {
    outline: none;
    border-color: var(--ring);
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--ring) 15%, transparent);
}

/* Zielzeile waehrend des Ziehens. Eine Linie oben statt einer Flaeche - sie
   zeigt, wo der Eintrag landet, ohne den Text zu ueberdecken.

   box-shadow statt border-top: Ein Rahmen wuerde die Zeile um zwei Pixel
   hoeher machen, und die ganze Tabelle springt bei jedem Wechsel der
   Zielzeile. */
.data-table tbody tr.ziel-oben > td {
    box-shadow: inset 0 2px 0 var(--primary);
}

/* Beim Ziehen nach unten landet der Eintrag unter der Zielzeile - die Linie
   gehoert dann an deren Unterkante. */
.data-table tbody tr.ziel-unten > td {
    box-shadow: inset 0 -2px 0 var(--primary);
}

/* Die gezogene Zeile selbst. Ohne sie sieht man beim Ziehen nicht, was man
   gerade in der Hand hat. */
.data-table tbody tr.wird-gezogen > td {
    opacity: 0.45;
}

/* Waehrend des Ziehens duerfen die Zellinhalte keine eigenen Ziehereignisse
   ausloesen - sonst uebernimmt der Browser Text oder Bild als Ziehobjekt und
   der Cursor wechselt staendig die Form. */
.data-table tbody tr.clickable td {
    -webkit-user-drag: none;
}

/* ---------- Feldbreite nach Inhalt ---------- */
/* Ein Eingabefeld sagt durch seine Breite, was erwartet wird. Ein Vorname in
   einem Feld ueber die halbe Zeile behauptet Platz fuer einen Satz - und wenn
   jedes Feld gleich breit ist, unterscheidet nichts mehr eine Postleitzahl von
   einer Firmenbezeichnung. Deshalb bekommt jedes Feld die Breite seines
   erwarteten Inhalts, nicht die seiner Spalte.

   Umgesetzt als max-width auf der vollen Breite: In einer schmalen Spalte oder
   auf dem Telefon schrumpft das Feld weiter mit, es waechst nur nicht darueber
   hinaus. Ein festes width wuerde die Umbrueche zerlegen.

   Ueber den Typ, wo der Typ es hergibt - sonst muss jedes neue Feld daran
   denken, und das erste, das es vergisst, faellt niemandem auf. Die
   Filter-Popover setzen ihre eigene Breite ueber einen spezifischeren Selektor
   und bleiben davon unberuehrt. */

/* ~30 Zeichen. */
.form-input[type="email"] {
    max-width: 22rem;
}

/* Passwoerter sind laenger als sie aussehen, aber keine Saetze. */
.form-input[type="password"] {
    max-width: 20rem;
}

/* Vor- und Nachname, Ort - selten ueber 20 Zeichen. */
.feld-name {
    max-width: 16rem;
}

/* Firma, Bezeichnung, Titel, Ueberschrift - kann ein halber Satz werden. */
.feld-lang {
    max-width: 30rem;
}

/* PIN, Kuerzel, Zahl. */
.feld-kurz {
    max-width: 10rem;
}
/* Mehrzeiliger Text - Einleitung, Bestaetigungstext, Abschlusstext. Rund 95
   Zeichen je Zeile; darueber wird das Korrekturlesen muehsam, und genau dazu
   sind diese Felder da. */
.feld-flies {
    max-width: 44rem;
}

/* Bewusst ueber die Inhaltslaenge hinaus. Die Klasse steht im Markup, damit die
   Entscheidung sichtbar ist - ein Feld ohne Breitenangabe waere sonst nicht von
   einem unterscheidbar, bei dem jemand die Frage nur nicht gestellt hat. Wer
   sie setzt, schreibt den Grund daneben. */
.feld-voll {
    max-width: none;
}
.form-input[type="date"] {
    width: auto;
    min-width: 10rem;
}

.form-input[type="datetime-local"] {
    width: auto;
    min-width: 13rem;
}

.form-input[type="time"] {
    width: auto;
    min-width: 7rem;
}

/* Abschnitt in der Liste: Formular und ausgeklappter Text. */
.abschnitt-formular {
    padding: 0.5rem 0;
}

.abschnitt-text {
    margin-top: 0.375rem;
    white-space: pre-wrap;
    color: var(--foreground);
    font-size: 0.875rem;
    line-height: 1.55;
}

/* Verweis mit nachgestelltem Symbol. In einem Lesefeld steht sonst nur Text,
   und ein blosser Farbwechsel am Namen liest sich als Hervorhebung, nicht als
   Weg woandershin. */
.verweis-mit-symbol {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
}

.verweis-mit-symbol svg {
    /* Etwas gedaempft: Das Symbol begleitet den Namen, es konkurriert nicht. */
    opacity: 0.7;
    flex-shrink: 0;
}

.verweis-mit-symbol:hover svg {
    opacity: 1;
}

/* Unterschrift in ihrer Zeile der Nachweistabelle. Weisser Grund und Rahmen,
   weil das Bild selbst transparent ist - auf grauem Grund saehe der Strich
   blass aus.

   Es fuellt die Spalte, in der sonst die bestaetigte Fassung steht - mehr
   Platz gibt die Tabelle nicht her, und weniger waere unnoetig klein. */
.unterschrift-bild {
    display: block;
    width: 100%;
    padding: 0.25rem;
    background: #fff;
    border: 1px solid var(--border);
    border-radius: var(--radius);
}

/* Aufzaehlung ohne Punkte - fuer kurze Verweislisten in einer Karte. */
.liste-schlicht {
    list-style: none;
    margin: 0;
    padding: 0;
}

.liste-schlicht li {
    padding: 0.25rem 0;
}

/* ---------- Bearbeiten in der Zeile ---------- */
/* Schmaler als ein Formularfeld: Die Zeile soll ihre Hoehe behalten, sonst
   springt die ganze Tabelle beim Umschalten in den Aenderungsmodus. */
.zeilen-eingabe {
    padding: 0.25rem 0.5rem;
    font-size: 0.875rem;
}

.cell-actions {
    white-space: nowrap;
}

/* Gedaempft statt in der Markenfarbe: In der Zeile stehen drei Symbole
   nebeneinander, und wenn alle rot sind, hebt sich das Loeschen nicht mehr ab -
   die Markenfarbe des Hauses ist selbst ein Rot. */
.cell-actions .btn-link {
    padding: 0.125rem 0.25rem;
    vertical-align: middle;
    color: var(--muted-foreground);
}

.cell-actions .btn-link:hover {
    color: var(--foreground);
}

.cell-actions .btn-link-destructive,
.cell-actions .btn-link-destructive:hover {
    color: var(--destructive);
}

/* ---------- Klickbare Zeile ---------- */
/* Ein echter Link, kein @onclick: Nur so funktionieren Mittelklick, Tastatur,
   "Link in neuem Tab oeffnen" und "Adresse kopieren" - alles, was ein Benutzer
   von einem Listeneintrag erwartet. Der <a> bleibt leer und wird ueber die
   Zeile gestreckt; traege er den Namen, wuerde dessen overflow:hidden die
   Streckung abschneiden. Die Beschriftung kommt per aria-label.
   Muster aus DEVEX.CRM. */
.data-table tbody tr.clickable {
    cursor: pointer;
    position: relative;
}

.zeilen-link {
    position: absolute;
    inset: 0;
    z-index: 0;
}

/* Bedienelemente in der Zeile muessen ueber dem gestreckten Link liegen,
   sonst faengt er ihre Klicks ab. */
.data-table tbody tr.clickable .btn,
.data-table tbody tr.clickable .btn-link,
.data-table tbody tr.clickable button,
.data-table tbody tr.clickable input,
.data-table tbody tr.clickable select {
    position: relative;
    z-index: 1;
}

/* ---------- Mailvorschau ---------- */
/* Im iframe, weil der Mailinhalt eigene Stile mitbringt, die sonst in die
   Anwendung durchschlagen. */
.mail-vorschau {
    width: 100%;
    height: 460px;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background-color: #ffffff;
}

.mail-text {
    margin: 0.5rem 0 0;
    padding: 0.875rem;
    max-height: 320px;
    overflow: auto;
    background-color: var(--background);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    font-size: 0.8125rem;
    line-height: 1.5;
    white-space: pre-wrap;
}

.muster-leiste {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
}

/* ---------- Modals (STANDARDS 3.5) ---------- */
/* Herkunft: DEVEX.CRM/wwwroot/css/app.css, uebernommen. */

.modal-backdrop {
    position: fixed;
    inset: 0;
    background-color: rgba(0, 0, 0, 0.4);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 100;
}

.modal {
    background-color: var(--card);
    width: 600px;
    max-width: calc(100vw - 32px);
    max-height: 85vh;
    overflow-y: auto;
    padding: 1.5rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: 0 20px 50px rgba(0, 0, 0, 0.25);
}

.modal-wide {
    width: 1200px;
}

.modal-titel {
    margin: 0 0 1rem;
    font-size: 1.125rem;
    font-weight: var(--font-weight-medium);
}

.modal-actions {
    display: flex;
    justify-content: flex-end;
    gap: 0.5rem;
    margin-top: 1.25rem;
    padding-top: 1rem;
    border-top: 1px solid var(--border);
}

/* Setzt eine Aktion im Modal-Fuss nach links ab - fuer zerstoerende Aktionen,
   die nicht neben Abbrechen/Schliessen stehen sollen, wo man sie versehentlich
   trifft. Herkunft: DEVEX.CRM. */
.modal-actions-links {
    margin-right: auto;
}

.modal-mittig {
    text-align: center;
    padding: 1.5rem 0;
}

.modal-mittig .spinner {
    margin: 0 auto 0.5rem;
    display: block;
}

/* Angezeigter, nicht bearbeitbarer Wert im Formularraster. Bewusst kein
   readonly-Input: Ein Feld, das aussieht wie ein Feld, laedt zum Tippen ein. */
.feld-lesend {
    padding: 0.5rem 0;
    font-size: 0.875rem;
}

/* Zweite Zeile in einer Tabellenzelle - E-Mail unter dem Namen, Herkunft unter
   dem Zustand. */
.zeile-nebentext {
    font-size: 0.75rem;
    color: var(--muted-foreground);
    line-height: 1.4;
}

/* Zerstoerende Aktion. Farbwert aus STANDARDS 1 (#c62828, 5,62:1 auf Weiss) -
   der fruehere Hauswert #ff4444 unterschritt mit 3,41:1 die AA-Grenze. */
.btn-destructive {
    background-color: #c62828;
    border-color: #c62828;
    color: #fff;
}

.btn-destructive:hover {
    background-color: #a81f1f;
    border-color: #a81f1f;
}

.alert-success {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.625rem 1rem;
    background-color: #dcfce7;
    color: #166534;
    font-size: 0.875rem;
    border-radius: var(--radius);
}

.filter-label {
    font-size: 0.875rem;
    font-weight: var(--font-weight-medium);
    color: var(--muted-foreground);
    white-space: nowrap;
}

/* ---------- Pagination ---------- */

.pagination {
    display: flex;
    align-items: center;
    gap: 0.25rem;
}

.pagination-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 2rem;
    height: 2rem;
    padding: 0 0.5rem;
    font-size: 0.875rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background-color: var(--card);
    color: var(--foreground);
    cursor: pointer;
    transition: background-color 0.15s ease;
}

.pagination-btn:hover {
    background-color: var(--muted);
}

.pagination-btn-active {
    background-color: var(--primary);
    color: var(--primary-foreground);
    border-color: var(--primary);
}

.pagination-btn-active:hover {
    background-color: color-mix(in srgb, var(--primary) 85%, #000);
}

.pagination-container {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0.75rem 1rem;
    gap: 1rem;
    flex-wrap: wrap;
}

.pagination-info {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    font-size: 0.875rem;
    color: var(--muted-foreground);
}

.pagination-left,
.pagination-right {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-size: 0.875rem;
    color: var(--muted-foreground);
}

.pagination-range {
    font-variant-numeric: tabular-nums;
}

.pagination-ellipsis {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 2rem;
    height: 2rem;
    color: var(--muted-foreground);
    user-select: none;
}

/* Page-Size-Select in der Pagination-Card — eigenständig (nicht von
   .th-filter-select abgeleitet, sonst sind Höhe/Padding/Width vermischt). */
.page-size-select {
    height: 34px;
    box-sizing: border-box;
    padding: 0 1.75rem 0 0.625rem;
    font-size: 0.875rem;
    line-height: 1;
    border: 1px solid var(--border);
    background-color: var(--card);
    color: var(--foreground);
    border-radius: var(--radius);
    appearance: none;
    -webkit-appearance: none;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23888' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><polyline points='6 9 12 15 18 9'/></svg>");
    background-repeat: no-repeat;
    background-position: right 0.5rem center;
    background-size: 14px;
    cursor: pointer;
    outline: none;
    transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.page-size-select:focus {
    border-color: var(--primary);
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--primary) 15%, transparent);
}

/* Vertikaler Abstand zwischen Tabellen-Card und Pagination-Card. */
.list-page {
    display: flex;
    flex-direction: column;
    gap: 1rem;
}

/* ---------- Detail-Page ---------- */

.detail-card {
    padding: 1.5rem 2rem;
}

.detail-grid {
    display: grid;
    grid-template-columns: max-content 1fr;
    column-gap: 2rem;
    row-gap: 0.625rem;
    margin: 0;
    font-size: 0.875rem;
}

.detail-grid dt {
    color: var(--muted-foreground);
    font-weight: var(--font-weight-medium);
    margin: 0;
}

.detail-grid dd {
    margin: 0;
    color: var(--foreground);
}

/* ---------- Navigation ---------- */

.nav-link {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0 1rem;
    height: 40px;
    font-size: 0.875rem;
    color: var(--sidebar-foreground);
    text-decoration: none;
    border-radius: var(--radius);
    transition: background-color 0.15s ease;
}

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

.nav-link-active,
.nav-link.active {
    background-color: var(--sidebar-accent);
    color: var(--sidebar-accent-foreground);
    box-shadow: inset 4px 0 0 var(--sidebar-primary);
}

.nav-link-active:hover,
.nav-link.active:hover {
    background-color: var(--sidebar-accent);
    color: var(--sidebar-accent-foreground);
}

/* ---------- Tree / Nav-Row ---------- */
/* Flat + Tree-Items teilen sich die gleiche nav-link-Struktur.
   Active-Indicator (4px box-shadow) sitzt am Sidebar-Rand.
   Folder-Expand-Chevron ist rechts, damit das Icon direkt
   neben dem Indicator steht. */

.tree-link-folder {
    cursor: pointer;
}

.tree-chevron-right {
    margin-left: auto;
    opacity: 0.6;
    transition: transform 0.15s ease;
}

.tree-chevron-open {
    transform: rotate(90deg);
}

.tree-children {
    position: relative;
    margin-left: 16px;
}

.tree-children::before {
    content: '';
    position: absolute;
    left: 8px;
    top: 2px;
    bottom: 2px;
    width: 1px;
    background-color: var(--sidebar-border);
}

/* Collapsed Sidebar: Baumkinder werden komplett ausgeblendet — nur
   Level-0-Folder bleiben als Icons sichtbar. Dadurch fluchtet jedes
   sichtbare Icon mit den flachen NavLinks. */
.tree-children.sidebar-collapsed {
    display: none;
}

/* Collapsed Sidebar: Chevron am Folder-Header raus, sonst wuerde
   `margin-left: auto` das Folder-Icon aus der zentrierten Spur druecken. */
.nav-collapsed .tree-chevron-right {
    display: none;
}

/* ---------- Icon sizes ---------- */

.icon-sm {
    width: 16px;
    height: 16px;
    flex-shrink: 0;
}

.icon-md {
    width: 20px;
    height: 20px;
    flex-shrink: 0;
}

/* ---------- Blazor ReconnectModal ---------- */

.components-reconnect-first-attempt-visible,
.components-reconnect-repeated-attempt-visible,
.components-reconnect-failed-visible,
.components-pause-visible,
.components-resume-failed-visible,
.components-rejoining-animation {
    display: none;
}

#components-reconnect-modal.components-reconnect-show .components-reconnect-first-attempt-visible,
#components-reconnect-modal.components-reconnect-show .components-rejoining-animation,
#components-reconnect-modal.components-reconnect-paused .components-pause-visible,
#components-reconnect-modal.components-reconnect-resume-failed .components-resume-failed-visible,
#components-reconnect-modal.components-reconnect-retrying .components-reconnect-repeated-attempt-visible,
#components-reconnect-modal.components-reconnect-retrying .components-rejoining-animation,
#components-reconnect-modal.components-reconnect-failed .components-reconnect-failed-visible {
    display: block;
}

#components-reconnect-modal:not([open]) {
    display: none;
}

#components-reconnect-modal {
    background-color: white;
    width: 20rem;
    margin: 20vh auto;
    padding: 2rem;
    border: 0;
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3);
    color: var(--foreground);
    font-size: 0.875rem;
}

#components-reconnect-modal::backdrop {
    background-color: rgba(0, 0, 0, 0.4);
}

.components-reconnect-container {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1rem;
}

#components-reconnect-modal p {
    margin: 0;
    text-align: center;
}

#components-reconnect-modal button {
    border: 0;
    background-color: var(--primary);
    color: var(--primary-foreground);
    padding: 0.5rem 1.5rem;
    cursor: pointer;
    font-size: 0.875rem;
    font-weight: var(--font-weight-medium);
}

#components-reconnect-modal button:hover {
    background-color: color-mix(in srgb, var(--primary) 85%, #000);
}

.components-rejoining-animation {
    position: relative;
    width: 60px;
    height: 60px;
}

.components-rejoining-animation div {
    position: absolute;
    border: 3px solid var(--primary);
    opacity: 1;
    border-radius: 50%;
    animation: components-rejoining-animation 1.5s cubic-bezier(0, 0.2, 0.8, 1) infinite;
}

.components-rejoining-animation div:nth-child(2) {
    animation-delay: -0.5s;
}

@keyframes components-rejoining-animation {
    0%, 4.9% {
        top: 30px; left: 30px; width: 0; height: 0; opacity: 0;
    }
    5% {
        top: 30px; left: 30px; width: 0; height: 0; opacity: 1;
    }
    100% {
        top: 0; left: 0; width: 60px; height: 60px; opacity: 0;
    }
}

/* ---------- Formular-spezifisch (kompakte Inputs/Labels) ---------- */

.formular .form-input {
    font-size: 0.8125rem;
    padding: 0.25rem 0.5rem;
    height: 1.75rem;
    min-height: 1.75rem;
    max-height: 1.75rem;
    box-sizing: border-box;
    line-height: 1.2;
}

.formular .form-label {
    font-size: 0.6875rem;
    margin-bottom: 0.125rem;
    padding: 0 2px;
    color: var(--muted-foreground);
    font-weight: var(--font-weight-normal);
    display: block;
}

.formular input[type="date"].form-input {
    padding: 0 0.5rem;
    line-height: 1.75rem;
    font-family: inherit;
    -webkit-appearance: none;
    appearance: none;
}

.formular input[type="date"].form-input::-webkit-datetime-edit {
    padding: 0;
    line-height: 1.75rem;
}

.formular input[type="date"].form-input::-webkit-calendar-picker-indicator {
    padding: 0;
    margin: 0;
}

/* ---------- Text Picker (PDF → Input) ---------- */
/* Cursor im PDF bleibt unverändert (Text-Selektion bleibt natürlich) */

/* ---------- Animations ---------- */

/* Lade-Spinner: neutraler rotierender Ring. Ersetzt im Ladezustand ein Icon —
   Icons selbst drehen NIE (STANDARDS.md § Icons). Erbt die Farbe via currentColor. */
.spinner {
    display: inline-block;
    flex: none;
    border-radius: 50%;
    border: 2px solid currentColor;
    border-top-color: transparent;
    animation: spin 0.7s linear infinite;
    vertical-align: middle;
}

.spinner-sm { width: 16px; height: 16px; }
.spinner-md { width: 20px; height: 20px; }

@keyframes spin {
    from { transform: rotate(0deg); }
    to { transform: rotate(360deg); }
}

/* ---------- Login page ---------- */

.login-page {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    min-height: 100vh;
    background-color: var(--sidebar);
    padding: 1.5rem;
}

.login-card {
    width: 100%;
    max-width: 400px;
    padding: 2rem;
}

.login-logo {
    display: flex;
    justify-content: center;
    margin-bottom: 1.5rem;
}

.login-logo-img {
    height: 88px;
    width: auto;
}

/* Wortmarke statt Monogramm: ueber die Breite gesetzt, nicht ueber die Hoehe.
   Bei 88 px Hoehe waere sie 444 px breit und spraenge aus der 400-px-Karte.
   300 px Breite ergeben rund 59 px Hoehe - dabei bleibt die Zweitzeile
   "CASING & PACKAGING" lesbar, anders als in der schmalen Kopfleiste. */
.login-logo-wortmarke {
    height: auto;
    width: 100%;
    max-width: 300px;
}

.login-title {
    text-align: center;
    margin-bottom: 1.5rem;
    color: var(--foreground);
}

.login-field {
    margin-bottom: 1rem;
}

.login-btn {
    width: 100%;
    margin-top: 0.5rem;
}

.login-error {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.625rem 1rem;
    margin-bottom: 1rem;
    background-color: #fee2e2;
    color: #991b1b;
    font-size: 0.875rem;
    border-radius: var(--radius);
}

.login-footer {
    margin-top: 1.5rem;
    text-align: center;
    font-size: 0.6875rem;
    color: var(--sidebar-foreground);
    opacity: 0.5;
    line-height: 1.6;
}

.login-version {
    font-variant-numeric: tabular-nums;
    letter-spacing: 0.01em;
}

.login-fieldset {
    border: 0;
    padding: 0;
    margin: 0;
    min-width: 0;
}

/* ---------- Blazor-specific ---------- */

#blazor-error-ui {
    background: lightyellow;
    bottom: 0;
    box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
    display: none;
    left: 0;
    padding: 0.6rem 1.25rem 0.7rem 1.25rem;
    position: fixed;
    width: 100%;
    z-index: 1000;
}

#blazor-error-ui .dismiss {
    cursor: pointer;
    position: absolute;
    right: 0.75rem;
    top: 0.5rem;
}

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

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

.valid.modified:not([type=checkbox]) {
    outline: 1px solid #26b050;
}

.invalid {
    outline: 1px solid var(--destructive);
}

/* ==========================================================================
   Nicolaisen Casing & Packaging - Token-Overrides
   --------------------------------------------------------------------------
   SSOT der Werte: docs/00-kundenartefakte/branding/corporate-design.md.
   Werte dort ändern, nicht hier. Stand: 2026-08-05.
   Status: kundenseitig nicht freigegeben.

   Projektspezifisch werden nur Markenfarbe, Logo und Favicon gesetzt
   (CLAUDE.md, Regel "UI"). Alles Übrige bleibt S3-Standard.
   ========================================================================== */

:root {
    /* Markenfarbe #CD0438 - aus dem Live-CSS des Kunden (--primary_color),
       vom Logo unabhängig bestätigt (#CE0538, Differenz 1 je Kanal). */
    --primary: #CD0438;
    --primary-foreground: #ffffff;

    /* Hover-/Aktiv-Variante, ebenfalls aus dem Kunden-CSS. */
    --primary-hover: #B80332;

    /* Focus-Ring leitet sich vom Primary ab (STANDARDS.md 3.4). */
    --ring: #CD0438;

    /* Aktiv-Indikator in der Sidebar (STANDARDS.md 3.7). */
    --sidebar-primary: #CD0438;

    /* --destructive bleibt bewusst der Standardwert #ff4444.
       Messung siehe corporate-design.md: zwischen zwei gesättigten Rottönen
       sind in Buttongröße höchstens 1,68:1 Flächenkontrast erreichbar - über
       den Farbton ist der Konflikt nicht lösbar. Getrennt wird über die Form
       (Outline statt Füllung), siehe unten. */
}

/* Löschen-Button als Outline-Variante. Trennt Primary und Destructive über
   Füllung gegen Kontur statt über den Farbton. Behebt nebenbei die
   WCAG-Lücke des Standards (weiß auf #ff4444 ergibt 3,41:1, nötig 4,5:1).
   Alle Farbwerte stammen aus STANDARDS.md - die Abweichung liegt in der
   Form, nicht in der Palette. Begründung: ADR-003. */
.btn-danger {
    background-color: var(--card);
    color: #991B1B;
    border-color: var(--destructive);
}

.btn-danger:hover {
    background-color: #FEE2E2;
    border-color: var(--destructive);
    color: #991B1B;
}

/* --- .badge-primary wird in diesem Projekt nicht verwendet ----------------
   Der Standard definiert die Pille als 12 % Primary-Tint mit Primary-Text.
   Das ist für ein blaues Primary entworfen und liest sich dort informativ.
   Mit dem roten Markenprimary (#CD0438) sieht dieselbe Pille aus wie
   .badge-error (#fee2e2 auf #991b1b) - ein neutraler Zustand wie "anwesend"
   oder eine Sprachfassung wirkt dann wie ein Fehler.

   Neutrale Kennzeichen tragen deshalb .badge-muted. Farbe bleibt der
   Bedeutung vorbehalten: grün bestätigt, gelb Aufmerksamkeit, rot Fehler.
   Festgestellt von Daniel Simon am 2026-08-05 an der Besucherliste.

   Bewusst NICHT als Override umdefiniert: Ein .badge-primary, das grau
   aussieht, ist eine Falle für den Nächsten. Die Klasse bleibt, wie der
   Standard sie definiert - sie wird hier nur nicht benutzt.
   Kandidat für den Rückfluss: Der Standard sollte den Fall benennen, dass
   ein warmes Primary die Pille unbrauchbar macht. */

/* --- Ladezustand des Anmeldeknopfs ---------------------------------------
   Die Anmeldeseite ist statisch gerendert (das Auth-Cookie kann nur im
   HttpContext ausgestellt werden), ein Blazor-Ladezustand ist dort nicht
   möglich. Stattdessen schaltet form-submit-spinner.js den Knopf beim
   Absenden auf .is-loading. Übernommen aus DEVEX.CRM. */
.login-btn-spinner {
    display: none;
}

.login-btn.is-loading {
    pointer-events: none;
    opacity: 0.85;
}

.login-btn.is-loading .login-btn-spinner {
    display: inline-block;
}

/* Abmelden liegt in einem Formular (POST mit Antiforgery-Token). Das Formular
   darf im Dropdown keinen eigenen Kasten aufmachen. */
.header-dropdown-form {
    margin: 0;
    display: block;
}

.header-dropdown-form button {
    width: 100%;
    background: none;
    border: none;
    font: inherit;
    text-align: left;
}
