/* ==========================================================================
   IT-SB Business Suite - Stylesheet
   Markenfarben abgeleitet vom Firmenlogo (schwarzes "IT", rotes Quadrat "SB",
   schwarzes Bergsymbol): Rot als Akzent, tiefes Anthrazit/Schwarz fuer Sidebar
   und Kontraste, ruhige Grautoene fuer Flaechen, Weiss fuer Karten.
   ========================================================================== */

:root {
    /* Markenfarben */
    --color-accent: #c1272d;
    --color-accent-dark: #98181d;
    --color-accent-darker: #7a1317;
    --color-accent-light: #fdecec;
    --color-accent-soft: #f2c9cb;

    --color-ink: #1c1d21;
    --color-ink-2: #2a2b30;
    --color-ink-soft: #4b4d55;

    /* Flaechen */
    --color-bg: #f2f3f5;
    --color-surface: #ffffff;
    --color-surface-alt: #f8f8fa;
    --color-border: #e3e4e8;
    --color-border-strong: #d1d3d9;
    --color-muted: #6b6d74;

    /* Status */
    --color-success: #1e7a3d;
    --color-success-bg: #e7f5eb;
    --color-success-border: #bfe3c9;
    --color-warning: #92650a;
    --color-warning-bg: #fdf1dc;
    --color-warning-border: #f2d79a;
    --color-info: #235a94;
    --color-info-bg: #e8f1fb;
    --color-info-border: #bdd9f2;
    --color-danger: #c1272d;
    --color-danger-bg: #fbe9e9;
    --color-danger-border: #f0c1c3;

    /* Layout */
    --sidebar-width: 258px;
    --topbar-height: 64px;

    /* Radien & Schatten */
    --radius-sm: 6px;
    --radius: 10px;
    --radius-lg: 16px;
    --shadow-card: 0 1px 2px rgba(20, 20, 25, 0.04), 0 2px 10px rgba(20, 20, 25, 0.05);
    --shadow-elevated: 0 18px 44px rgba(15, 15, 20, 0.22);
    --shadow-menu: 0 10px 28px rgba(15, 15, 20, 0.14);
    --shadow-focus: 0 0 0 3px rgba(193, 39, 45, 0.16);

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

    /* ---- Modulton (siehe Abschnitt "Farbtoene je Modul" weiter unten) ----
       Standardton ist die Markenfarbe; <main class="content tone-*"> setzt ihn
       je Bereich um. Bauteile lesen ausschliesslich diese drei Variablen und
       brauchen deshalb keine eigenen Farbvarianten. */
    --tone: var(--color-accent);
    --tone-bg: var(--color-accent-light);
    --tone-border: var(--color-accent-soft);
    --tone-on-dark: #ef9296;

    font-size: 16px;
}

/* ==========================================================================
   Dunkelmodus (Umschalter oben rechts in der Topbar, siehe
   assets/js/theme-toggle.js) - ueberschreibt ausschliesslich die oben
   definierten Farbtoken. Fast alle Bauteile lesen ausschliesslich diese
   Variablen und passen sich dadurch automatisch an. Sidebar und Login-Seite
   bleiben bewusst unveraendert dunkel (eigene, vom Farbschema unabhaengige
   Markenflaeche, siehe .sidebar/.auth-brand-panel - dort steht deshalb
   bewusst ein fester Hex-Wert statt var(--color-ink)). */
:root[data-theme="dark"] {
    --color-accent: #dd4b51;
    --color-accent-dark: #ea6b70;
    --color-accent-darker: #f4989c;
    --color-accent-light: #3a2225;
    --color-accent-soft: #5c3438;

    --color-ink: #e8e9ec;
    --color-ink-2: #cfd0d5;
    --color-ink-soft: #a3a5ac;

    --color-bg: #15161a;
    --color-surface: #1e1f24;
    --color-surface-alt: #262730;
    --color-border: #34353d;
    --color-border-strong: #454650;
    --color-muted: #93959d;

    --color-success: #4caf6f;
    --color-success-bg: #16321f;
    --color-success-border: #2c5c3a;
    --color-warning: #d9a53f;
    --color-warning-bg: #3a2d10;
    --color-warning-border: #5c4a1f;
    --color-info: #5b9bdb;
    --color-info-bg: #16283a;
    --color-info-border: #2c4a68;
    --color-danger: #e8636a;
    --color-danger-bg: #3a1d1f;
    --color-danger-border: #5c2f33;

    --shadow-card: 0 1px 2px rgba(0, 0, 0, 0.35), 0 2px 12px rgba(0, 0, 0, 0.4);
    --shadow-elevated: 0 18px 44px rgba(0, 0, 0, 0.6);
    --shadow-menu: 0 10px 28px rgba(0, 0, 0, 0.55);
    --shadow-focus: 0 0 0 3px rgba(232, 99, 106, 0.28);
}

/* Modultoene fuer den Dunkelmodus - dieselbe Systematik wie im Abschnitt
   "Farbtoene je Modul" weiter unten, nur mit den dort bereits fuer dunklen
   Grund vorgesehenen Werten (--tone-on-dark) als Textton plus neu
   abgedunkelten Flaechen/Rahmen. */
:root[data-theme="dark"] .tone-brand  { --tone: #ef9296; --tone-bg: #3a2225; --tone-border: #5c3438; }
:root[data-theme="dark"] .tone-blue   { --tone: #8fbbe8; --tone-bg: #182636; --tone-border: #2c4258; }
:root[data-theme="dark"] .tone-green  { --tone: #7fc99a; --tone-bg: #16301f; --tone-border: #2a4c34; }
:root[data-theme="dark"] .tone-amber  { --tone: #ddb264; --tone-bg: #362a12; --tone-border: #55431f; }
:root[data-theme="dark"] .tone-violet { --tone: #a99add; --tone-bg: #29233d; --tone-border: #423a5c; }
:root[data-theme="dark"] .tone-teal   { --tone: #6fc0b8; --tone-bg: #133330; --tone-border: #234c47; }
:root[data-theme="dark"] .tone-slate  { --tone: #b0b2ba; --tone-bg: #292a30; --tone-border: #40414a; }

/* .settings-tab.is-active (siehe weiter unten) nutzt im Hellmodus bewusst
   var(--color-ink) als dunklen Pillen-Hintergrund - im Dunkelmodus waere das
   ein fast weisser Hintergrund mit weisser Schrift (unsichtbar). Dort im
   Dunkelmodus die Markenfarbe als Hervorhebung statt "dunkel" verwenden. */
:root[data-theme="dark"] .settings-tab.is-active {
    background: var(--color-accent);
}

/* ---------- Reset & Grundlagen ---------- */

* {
    box-sizing: border-box;
}

html, body {
    margin: 0;
    padding: 0;
}

body {
    font-family: var(--font-sans);
    background: var(--color-bg);
    color: var(--color-ink);
    line-height: 1.55;
    -webkit-font-smoothing: antialiased;
    text-rendering: optimizeLegibility;
}

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

a:hover {
    text-decoration: underline;
}

h1, h2, h3, h4 {
    color: var(--color-ink);
    font-weight: 600;
    letter-spacing: -0.01em;
    margin: 0 0 0.6em;
}

h1 { font-size: 1.6rem; }
h2 { font-size: 1.2rem; }
h3 { font-size: 1.05rem; }

p {
    margin: 0 0 1em;
}

code {
    font-family: "Cascadia Code", Consolas, "Courier New", monospace;
    background: var(--color-surface-alt);
    border: 1px solid var(--color-border);
    border-radius: 4px;
    padding: 1px 6px;
    font-size: 0.9em;
}

hr.divider {
    border: none;
    border-top: 1px solid var(--color-border);
    margin: 20px 0;
}

::selection {
    background: var(--color-accent-soft);
}

/* ---------- Auth-Seiten (Login, Verify) ohne Sidebar ---------- */

/* Der Verlauf steht bewusst auf <html>, NICHT auf .auth-body: Browser malen
   die KOMPLETTE Canvas (den ganzen sichtbaren Bereich, IMMER, unabhaengig von
   jeder Element-Boxgroesse/vh-Einheit) mit dem Hintergrund des Wurzelelements
   (html), sofern dort einer gesetzt ist - das ist die einzige Stelle, die
   wirklich verlaesslich "die ganze Seite" abdeckt, ganz ohne
   vh/dvh/lvh-Rateraten oder den nachweislich fehlerhaften position:fixed-
   Ansatz (beide wurden vorher ausprobiert, siehe Git-Historie/vorige
   Kommentare). Reichte .auth-body's eigene Box (zuvor per min-height:100lvh
   grob an die Bildschirmhoehe angenaehert) auf einem Geraet nicht bis zum
   echten unteren Rand, blieb darunter zuvor nur eine FLACHE Fallback-Farbe
   sichtbar statt des Verlaufs - jetzt ist es ueberall derselbe Verlauf, egal
   wie hoch .auth-body tatsaechlich gerendert wird. Ueber die eigene Klasse
   auth-html gescoped (login.php/verify.php setzen sie direkt am
   <html>-Tag) statt per :has() - :has() wird von aelteren/manchen mobilen
   Safari-Versionen NICHT unterstuetzt, eine nicht unterstuetzte Selektor-
   Regel wird komplett ignoriert, und OHNE Fallback blieb dort dann der
   gesamte Hintergrund WEISS statt nur an einer Kante fehlerhaft. Eine
   einfache Klasse funktioniert ausnahmslos ueberall. */
html.auth-html,
.auth-body {
    /* Bewusst DIESELBE Deklaration auf BEIDEN Elementen (nicht nur auf
       <html>) - der eigentliche Bug zuvor war genau diese Asymmetrie: body
       erbte ohne eigene Deklaration die allgemeine body{background:
       var(--color-bg)}-Regel (helles Grau) weiter oben in dieser Datei, die
       undurchsichtig UEBER dem nur auf <html> gesetzten Verlauf lag - nicht
       :has()-Unterstuetzung oder Caching (beides vorher faelschlich
       vermutet). Mit dem Verlauf auf beiden Elementen ist es jetzt egal,
       welches der beiden sichtbar ist (z.B. am Rand bei -webkit-overflow-
       scrolling/Bounce) - beide zeigen exakt dasselbe. */
    background:
        radial-gradient(circle at 15% 20%, rgba(193, 39, 45, 0.25), transparent 45%),
        radial-gradient(circle at 85% 80%, rgba(193, 39, 45, 0.12), transparent 50%),
        linear-gradient(160deg, #131316 0%, #1c1d21 55%, #232428 100%);
}

.auth-body {
    /* dvh statt lvh - jetzt, wo html/body dieselbe Deklaration tragen (siehe
       oben), macht dvh (folgt der TATSAECHLICH aktuellen Symbolleisten-
       Groesse in Echtzeit) evtl. weniger Probleme als lvh (nimmt immer die
       groesstmoegliche, eingefahrene Groesse an - bei sichtbarer Leiste ggf.
       zu hoch fuer den echten sichtbaren Bereich). Da diese Datei ohnehin nur
       den Hintergrund von .auth-body selbst betrifft (der Verlauf kommt seit
       der Korrektur oben IMMER zusaetzlich von <html>/der Canvas), ist ein
       Groessenfehler hier weit weniger kritisch als zuvor - reiner Test, ob
       dvh in Kombination mit der jetzt behobenen html/body-Redundanz das
       verbleibende weisse Stueck am unteren Rand behebt. */
    min-height: 100vh;
    min-height: 100dvh;
    padding: env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left);
    display: flex;
    align-items: stretch;
    justify-content: center;
}

.auth-shell {
    width: 100%;
    max-width: 960px;
    margin: auto;
    padding: 32px;
    display: grid;
    grid-template-columns: 1fr 1fr;
    align-items: stretch;
    gap: 0;
}

.auth-brand-panel {
    background: linear-gradient(155deg, var(--color-ink) 0%, #101114 100%);
    color: #f4f4f5;
    border-radius: var(--radius-lg) 0 0 var(--radius-lg);
    padding: 48px 40px;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    position: relative;
    overflow: hidden;
}

.auth-brand-panel::after {
    content: "";
    position: absolute;
    right: -60px;
    bottom: -60px;
    width: 220px;
    height: 220px;
    border-radius: 50%;
    background: radial-gradient(circle, rgba(193, 39, 45, 0.35), transparent 70%);
}

/* Hoehenlinien-Zeichnung im Hintergrund der Markenspalte - liegt hinter allem
   anderen und faengt nie einen Klick ab. */
.auth-brand-pattern {
    position: absolute;
    left: 0;
    right: 0;
    bottom: -34px;
    width: 100%;
    color: #ffffff;
    opacity: 0.06;
    pointer-events: none;
}

.auth-brand-logo {
    max-width: 150px;
    display: block;
    background: #fff;
    padding: 10px 14px;
    border-radius: var(--radius-sm);
    position: relative;
}

.auth-brand-copy {
    position: relative;
}

.auth-brand-list {
    list-style: none;
    margin: 24px 0 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.auth-brand-list li {
    display: flex;
    align-items: center;
    gap: 11px;
    color: #d3d4d8;
    font-size: 0.86rem;
    line-height: 1.35;
}

.auth-brand-copy h2 {
    color: #fff;
    font-size: 1.5rem;
    margin-bottom: 0.4em;
}

.auth-brand-copy p {
    color: #c7c8cc;
    font-size: 0.95rem;
    max-width: 30ch;
}

.auth-brand-foot {
    color: #8c8d93;
    font-size: 0.8rem;
    position: relative;
}

.auth-card {
    background: var(--color-surface);
    border-radius: 0 var(--radius-lg) var(--radius-lg) 0;
    box-shadow: var(--shadow-elevated);
    padding: 48px 44px;
    width: 100%;
    display: flex;
    flex-direction: column;
    justify-content: center;
}

.auth-card-standalone {
    border-radius: var(--radius-lg);
    max-width: 420px;
    margin: auto;
}

.auth-divider {
    display: flex;
    align-items: center;
    text-align: center;
    color: #8c8d93;
    font-size: 0.8rem;
    margin: 4px 0 20px;
}
.auth-divider::before,
.auth-divider::after {
    content: "";
    flex: 1;
    border-bottom: 1px solid var(--color-border);
}
.auth-divider span {
    padding: 0 12px;
}

.auth-logo-mobile {
    display: none;
}

.auth-card h1 {
    font-size: 1.4rem;
    margin-bottom: 0.2em;
}

.auth-card .auth-subtitle {
    color: var(--color-muted);
    font-size: 0.92rem;
    margin-bottom: 1.6em;
}

.auth-tabs {
    display: flex;
    gap: 4px;
    margin-bottom: 22px;
    background: var(--color-surface-alt);
    padding: 4px;
    border-radius: var(--radius-sm);
    border: 1px solid var(--color-border);
}

.auth-tab {
    flex: 1;
    text-align: center;
    padding: 9px 10px;
    cursor: pointer;
    border: none;
    background: none;
    font: inherit;
    font-weight: 600;
    font-size: 0.88rem;
    color: var(--color-muted);
    border-radius: 5px;
    transition: background 0.15s ease, color 0.15s ease;
}

.auth-tab:hover {
    color: var(--color-ink);
}

.auth-tab.is-active {
    color: #fff;
    background: var(--color-ink);
}

.auth-panel {
    display: none;
}

.auth-panel.is-active {
    display: block;
    animation: fade-in 0.15s ease;
}

@keyframes fade-in {
    from { opacity: 0; transform: translateY(2px); }
    to { opacity: 1; transform: translateY(0); }
}

/* ---------- Formulare ---------- */

/* Skip-Link: unsichtbar bis zum Fokus (erster Tab-Stopp der Seite) - ohne das
   muss jede Tastatur-Nutzung erst die komplette Sidebar-Navigation
   durchtabben, bevor der eigentliche Seiteninhalt erreichbar ist. */
.form-group {
    margin-bottom: 18px;
}

/* Radio-Gruppen nutzen <fieldset class="form-group"> statt <div> (mit
   <legend> statt <label>) fuer korrekte Screenreader-Gruppierung - ohne
   diesen Reset wuerden Browser-Standard-Rahmen/-Innenabstand des <fieldset>
   das bisherige .form-group-Layout verschieben. */
fieldset.form-group {
    border: none;
    padding: 0;
    margin: 0 0 18px;
    min-width: 0;
}

fieldset.form-group legend {
    display: block;
    font-size: 0.88rem;
    font-weight: 600;
    margin-bottom: 6px;
    padding: 0;
    color: var(--color-ink-soft);
}

label {
    display: block;
    font-size: 0.88rem;
    font-weight: 600;
    margin-bottom: 6px;
    color: var(--color-ink-soft);
}

input[type="text"],
input[type="password"],
input[type="email"],
input[type="number"],
input[type="date"],
select,
textarea {
    appearance: none;
    -webkit-appearance: none;
    -moz-appearance: none;
    box-sizing: border-box;
    margin: 0;
    box-shadow: none;
    line-height: 1.2;
    vertical-align: middle;
    width: 100%;
    padding: 10px 12px;
    border: 1px solid var(--color-border-strong);
    border-radius: var(--radius-sm);
    font: inherit;
    font-size: 0.95rem;
    background: var(--color-surface);
    color: var(--color-ink);
    transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

/* Feste, einheitliche Hoehe fuer alle Einzeilen-Formularfelder UND Buttons
   (siehe .btn weiter unten) - browserabhaengig weichen <select>/
   <input type="date"> sonst leicht von <input type="text">/<button> ab
   (unterschiedliche native UI-Chrome trotz identischem Padding), was ueberall
   dort auffaellt, wo beide nebeneinander stehen (Filterleisten, Datei-Upload
   neben einem Text-/Bezeichnungsfeld usw.). textarea bewusst ausgenommen -
   soll mehrzeilig frei wachsen. */
input[type="text"],
input[type="password"],
input[type="email"],
input[type="number"],
input[type="date"],
select {
    height: 42px;
    min-height: 42px;
    max-height: 42px;
}

/* WICHTIG: explizite Hoehe allein reicht bei <select> nicht - der Browser
   rendert dessen native Dropdown-Pfeil-Flaeche ueber die eigene OS-Theme-
   Engine, was optisch (nicht im CSS-Boxmodell messbar, getBoundingClientRect
   zeigt identische Werte!) 1-2px von einem <input>/<button> abweichen kann.
   appearance:none entfernt diese native Chrome komplett, eigener Pfeil per
   Hintergrundbild ersetzt sie 1:1 gleich hoch wie alle anderen Felder. */
/* select:not([multiple]):not([size]) matcht/schlaegt die Spezifitaet der
   nativen UA-Stylesheet-Regel, die genau diese Selektor-Form fuer die
   Standard-appearance verwendet (Chromium/Edge) - ein einfaches "select{}"
   reicht bei manchen Chromium-Versionen (u.a. Edge) NICHT, um die native
   Chrome zuverlaessig zu schlagen, was exakt so eine 1-2px-Hoehenabweichung
   verursachen kann, die im CSS-Boxmodell/getBoundingClientRect unsichtbar
   bleibt. Zusaetzlich !important als letzte Absicherung. */
select,
select:not([multiple]):not([size]) {
    appearance: none !important;
    -webkit-appearance: none !important;
    -moz-appearance: none !important;
    padding-right: 36px;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%236f7178' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 10px center;
    background-size: 16px;
}

select::-ms-expand {
    display: none;
}

/* <input type="date"> rendert seinen Kalender-Knopf ueber die native OS-Theme-
   Engine (kleines graues Standard-Glyph) - das ist der einzige Ort, an dem
   nach dem appearance:none oben noch unstilisierte Browser-Chrome durchschlug
   und neben dem eigenen <select>-Pfeil sichtbar fremd wirkte. Hier durch
   dasselbe Icon-Vokabular wie alle uebrigen Icons ersetzt (Feather-Kalender,
   currentColor-Grauton der Palette), Klickverhalten bleibt unveraendert. */
input[type="date"] {
    padding-right: 36px;
}

input[type="date"]::-webkit-calendar-picker-indicator {
    width: 16px;
    height: 16px;
    margin: 0;
    padding: 0;
    cursor: pointer;
    opacity: 0.75;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%236f7178' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='4' width='18' height='18' rx='2'/%3E%3Cline x1='16' y1='2' x2='16' y2='6'/%3E%3Cline x1='8' y1='2' x2='8' y2='6'/%3E%3Cline x1='3' y1='10' x2='21' y2='10'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: center;
    background-size: 16px 16px;
    transition: opacity 0.15s ease;
}

input[type="date"]::-webkit-calendar-picker-indicator:hover {
    opacity: 1;
}

/* Auswahlkaestchen/Radios app-weit in der Markenfarbe statt im Browser-Blau -
   vorher galt das nur fuer .checkbox-row, weshalb z.B. das MwSt.-Kaestchen
   unter Einstellungen > Firma als einziges grau/blau blieb. */
input[type="checkbox"],
input[type="radio"] {
    accent-color: var(--color-accent);
    width: 16px;
    height: 16px;
    cursor: pointer;
}

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

input::placeholder, textarea::placeholder {
    color: #9b9da3;
}

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

/* Checkboxen/Radios haben keinen sichtbaren border-color-Wechsel (anders als
   Text/Select/Textarea oben) - der einzige verbleibende Fokus-Hinweis waere
   der box-shadow-Ring aus var(--shadow-focus), dessen tatsaechlich gerenderte
   Farbe (halbtransparentes Rot auf Weiss gemischt) nur ~1.3:1 Kontrast zum
   Hintergrund hat und damit fuer schwache Sehkraft praktisch unsichtbar ist.
   Eigene, deckende Outline-Farbe statt des (hier wirkungslosen) box-shadow-Rings. */
input[type="checkbox"]:focus-visible,
input[type="radio"]:focus-visible {
    outline: 2px solid var(--color-accent);
    outline-offset: 2px;
}

input:disabled, select:disabled, textarea:disabled {
    background: var(--color-surface-alt);
    color: var(--color-muted);
    cursor: not-allowed;
}

input[readonly] {
    background: var(--color-surface-alt);
    color: var(--color-ink-soft);
}

.field-error {
    color: var(--color-danger);
    font-size: 0.82rem;
    margin-top: 5px;
}

/* Client-seitige Inline-Validierung (assets/js/form-validation.js) - hebt das
   betroffene Feld hervor, bis es wieder gueltig ist. */
.field-invalid {
    border-color: var(--color-danger) !important;
}

.field-hint {
    color: var(--color-muted);
    font-size: 0.82rem;
    margin-top: 5px;
}

/* Adress-Autocomplete (Nominatim) - Von/Nach-Felder der KM-Erfassung UND
   Strasse-Feld bei Kunde anlegen/bearbeiten teilen sich dieselben Klassen. */
.address-autocomplete-field {
    position: relative;
}

.address-autocomplete-suggestions {
    position: absolute;
    z-index: 20;
    top: 100%;
    left: 0;
    right: 0;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    box-shadow: 0 8px 20px rgba(0, 0, 0, 0.12);
    max-height: 220px;
    overflow-y: auto;
    margin-top: 2px;
}

.address-autocomplete-suggestion-item {
    padding: 8px 12px;
    font-size: 0.88rem;
    cursor: pointer;
}

.address-autocomplete-suggestion-item:hover,
.address-autocomplete-suggestion-item.is-active {
    background: var(--color-surface-alt);
}

/* "Keine Treffer"-Platzhalter (global-search.js/command-palette.js) - bewusst
   kein role="option", daher eine eigene Klasse statt -suggestion-item, aber
   optisch identisch (ohne den cursor:pointer einer echten Auswahl). */
.address-autocomplete-suggestion-empty {
    padding: 8px 12px;
    font-size: 0.88rem;
    color: var(--color-muted);
}

/* Als <a> statt <div> genutzt in der globalen Suche (assets/js/global-search.js) -
   Browser-Standardstil eines Links zurücksetzen, damit es optisch identisch
   zu den bestehenden Klick-Handler-<div>s der Adress-Autocomplete bleibt. */
a.address-autocomplete-suggestion-item {
    display: block;
    color: inherit;
    text-decoration: none;
}

.address-autocomplete-suggestion-group {
    padding: 6px 12px 2px;
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--color-muted);
}

/* Globale Suche im Topbar (templates/layout/header.php) - zwischen dem
   Datums-Kontext links und den Aktions-Icons rechts, wächst mit dem
   verfügbaren Platz statt fester Breite. */
.topbar-search {
    position: relative;
    flex: 1;
    max-width: 420px;
    margin: 0 16px;
    display: flex;
    align-items: center;
}

.topbar-search-icon {
    position: absolute;
    left: 12px;
    width: 16px;
    height: 16px;
    color: var(--color-muted);
    pointer-events: none;
}

.topbar-search input {
    width: 100%;
    padding: 8px 12px 8px 34px;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    background: var(--color-bg);
    font-size: 0.88rem;
}

/* button.mobile-search-trigger-btn (Element+Klasse) statt nur der Klasse -
   der Knopf trägt zusätzlich .theme-toggle-btn fürs Erscheinungsbild, deren
   eigene "display: inline-flex"-Regel (weiter unten in dieser Datei definiert)
   sonst bei GLEICHER Spezifität durch die spätere Position in der
   Kaskade gewinnen würde, unabhängig von dieser Regel hier - live per
   getComputedStyle() bestätigt, dass genau das ohne den Element-Zusatz
   passiert waere. */
button.mobile-search-trigger-btn {
    display: none;
}

@media (max-width: 960px) {
    .topbar-search {
        display: none;
    }

    /* Ersatz-Zugang zur Suche, solange .topbar-search oben ausgeblendet ist -
       ohne diesen Knopf war die Suche (und ihre einzige, rein tastatur-
       basierte Alternative, die Befehlspalette) unterhalb dieser Breite
       komplett unerreichbar. 44x44px statt der von .theme-toggle-btn
       geerbten 38x38px - dies ist hier (anders als beim Theme-/Hamburger-
       Knopf) der EINZIGE Zugang zu einer haeufig genutzten Kernfunktion auf
       Touch-Geraeten, nicht nur ein gelegentlich genutztes Utility. */
    button.mobile-search-trigger-btn {
        display: inline-flex;
        width: 44px;
        height: 44px;
    }
}

.checkbox-row {
    display: flex;
    align-items: center;
    gap: 9px;
    margin-bottom: 18px;
}

.tracking-number-row {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 8px;
}

.tracking-number-row input {
    flex-grow: 1;
}

.checkbox-row input {
    width: auto;
    accent-color: var(--color-accent);
}

.checkbox-row label {
    margin: 0;
    font-weight: 400;
    color: var(--color-ink);
}

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

.btn {
    appearance: none;
    -webkit-appearance: none;
    -moz-appearance: none;
    margin: 0;
    box-shadow: none;
    vertical-align: middle;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    height: 42px;
    min-height: 42px;
    max-height: 42px;
    padding: 0 20px;
    border-radius: var(--radius-sm);
    border: 1px solid transparent;
    font: inherit;
    font-size: 0.92rem;
    font-weight: 600;
    cursor: pointer;
    text-align: center;
    transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease, transform 0.05s ease;
    line-height: 1.2;
    box-sizing: border-box;
}

.btn:active {
    transform: translateY(1px);
}

/* Siehe assets/js/busy-button.js - aria-disabled statt der nativen disabled-
   Eigenschaft, damit ein Knopf waehrend einer laufenden Aktion fokussierbar
   bleibt (Tastatur-Tab-Reihenfolge bricht sonst ab). */
.btn[aria-disabled="true"] {
    opacity: 0.6;
    cursor: not-allowed;
}

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

.btn-primary:hover {
    background: var(--color-accent-dark);
    border-color: var(--color-accent-dark);
    text-decoration: none;
}

.btn-success {
    background: var(--color-success);
    border-color: var(--color-success);
    color: #fff;
    width: 100%;
}

.btn-success:hover {
    background: #17602f;
    border-color: #17602f;
    text-decoration: none;
}

.btn-secondary {
    background: var(--color-surface);
    color: var(--color-ink);
    border: 1px solid var(--color-border-strong);
    width: 100%;
}

.btn-secondary:hover {
    background: var(--color-surface-alt);
    border-color: var(--color-ink-soft);
    text-decoration: none;
}

.btn-link {
    background: none;
    border: none;
    color: var(--color-accent);
    cursor: pointer;
    font: inherit;
    font-size: 0.9rem;
    font-weight: 600;
    padding: 0;
}

.btn-link:hover {
    color: var(--color-accent-dark);
}

/* Ein <summary> mit .btn/.btn-link-Klassen soll wie der jeweilige Knopf/Link
   aussehen, ohne den nativen Ausklapp-Pfeil des Browsers davor - konsistent
   mit dem gleichen Muster bei .sidebar-nav-group-toggle/.order-summary. */
summary.btn,
summary.btn-link {
    list-style: none;
}

summary.btn::-webkit-details-marker,
summary.btn-link::-webkit-details-marker {
    display: none;
}

.btn-link-danger {
    color: var(--color-danger);
}

.btn-link-danger:hover {
    color: var(--color-danger);
    opacity: 0.8;
}

/* Bewusst NICHT flaechig eingefaerbt: .btn-danger steht in den Listen einmal
   pro Zeile (Produkte/Kunden/KM-Abrechnung: 13-50 Zeilen pro Seite). Als
   gefuellter roter Block ergab das eine ganze Wand aus Rot, die optisch mit
   der einen echten Primaeraktion der Seite konkurrierte. Jetzt ruhige weisse
   Flaeche mit rotem Text/Rand - die Gefahren-Semantik bleibt (Farbe + Papierkorb-
   Icon), die Dringlichkeit entsteht erst beim Hover. */
.btn-danger {
    background: var(--color-surface);
    color: var(--color-danger);
    border: 1px solid var(--color-danger-border);
}

.btn-danger:hover {
    background: var(--color-danger-bg);
    border-color: var(--color-danger);
    text-decoration: none;
}

.btn-inline {
    width: auto;
}

.btn-sm {
    padding: 7px 14px;
    font-size: 0.85rem;
}

/* ---------- Alerts & Badges ---------- */

/* Meldungen tragen ihr Symbol per ::before statt in der Vorlage - so bekommen
   ALLE Meldungen app-weit dasselbe Zeichen, ohne dass jede der rund 40
   Fundstellen angefasst werden muesste. Bewusst absolut positioniert statt
   per Flexbox: eine Meldung enthaelt mal reinen Text, mal eine <ul> mit
   Validierungsfehlern, mal beides - als Flexbox stuenden Text und Liste
   nebeneinander statt untereinander. */
.alert {
    position: relative;
    padding: 13px 16px 13px 45px;
    border-radius: var(--radius-sm);
    margin-bottom: 20px;
    font-size: 0.92rem;
    border: 1px solid transparent;
}

.alert::before {
    content: "";
    position: absolute;
    left: 16px;
    top: 14px;
    width: 18px;
    height: 18px;
    background-repeat: no-repeat;
    background-position: center;
    background-size: 18px 18px;
}

.alert ul {
    margin: 0;
    padding-left: 20px;
}

.alert-error {
    background: var(--color-danger-bg);
    color: var(--color-danger);
    border-color: var(--color-danger-border);
}

/* stroke='currentColor' statt eines fest kodierten Hex-Werts: ::before erbt
   "color" von .alert-error (var(--color-danger)) - dadurch passt sich das
   Symbol automatisch dem Dunkelmodus an, ohne eine zweite, dort abweichende
   SVG-Kopie zu brauchen. */
.alert-error::before {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'/%3E%3Cline x1='12' y1='8' x2='12' y2='13'/%3E%3Cline x1='12' y1='16.5' x2='12' y2='16.5'/%3E%3C/svg%3E");
}

.alert-success {
    background: var(--color-success-bg);
    color: var(--color-success);
    border-color: var(--color-success-border);
}

.alert-success::before {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M22 11.1V12a10 10 0 1 1-5.9-9.1'/%3E%3Cpolyline points='22 4 12 14.01 9 11.01'/%3E%3C/svg%3E");
}

.alert-info {
    background: var(--color-info-bg);
    color: var(--color-info);
    border-color: var(--color-info-border);
}

.alert-info::before {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'/%3E%3Cline x1='12' y1='16' x2='12' y2='11'/%3E%3Cline x1='12' y1='7.5' x2='12' y2='7.5'/%3E%3C/svg%3E");
}

.alert-warning {
    background: var(--color-warning-bg);
    color: var(--color-warning);
    border-color: var(--color-warning-border);
}

.alert-warning::before {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M10.29 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z'/%3E%3Cline x1='12' y1='9' x2='12' y2='13'/%3E%3Cline x1='12' y1='17' x2='12' y2='17'/%3E%3C/svg%3E");
}

.text-muted {
    color: var(--color-muted);
    font-size: 0.88rem;
}

.text-center {
    text-align: center;
}

.badge {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 4px 11px;
    border-radius: 999px;
    font-size: 0.76rem;
    font-weight: 700;
    letter-spacing: 0.01em;
    white-space: nowrap;
}

.badge::before {
    content: "";
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: currentColor;
    flex-shrink: 0;
}

.badge-success {
    background: var(--color-success-bg);
    color: var(--color-success);
}

.badge-muted {
    background: var(--color-bg);
    /* Nicht die globale --color-muted-Variable (wird an vielen anderen Stellen
       gegen einen helleren/anderen Hintergrund verwendet, wo sie ausreichend
       Kontrast hat) - hier speziell etwas dunkler, da Text UND Hintergrund
       dieses Badges beide helles Grau sind: --color-muted auf --color-bg
       erreichte im Hellmodus nur 4.389:1 (WCAG AA verlangt 4.5:1 fuer normal
       grossen Text). #6a6c73 erreicht ca. 4.72:1. */
    color: #6a6c73;
}
:root[data-theme="dark"] .badge-muted {
    /* Im Dunkelmodus bestand --color-muted bereits mit 5.465:1 - dort bleibt
       die urspruengliche Variable unveraendert. Dieses Projekt nutzt einen
       reinen Umschalter (assets/js/theme-toggle.js, [data-theme="dark"]),
       keine prefers-color-scheme-Media-Query - :root ohne dieses Attribut
       ist hier immer der Hellmodus. */
    color: var(--color-muted);
}

.badge-info {
    background: var(--color-info-bg);
    color: var(--color-info);
}

.badge-warning {
    background: var(--color-warning-bg);
    color: var(--color-warning);
}

.badge-danger {
    background: var(--color-danger-bg);
    color: var(--color-danger);
}

.azure-setup-box {
    background: var(--color-bg);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    padding: 14px 16px;
    margin-bottom: 4px;
}

.azure-setup-status {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
}

.azure-setup-devicecode {
    margin-top: 12px;
    padding: 12px 14px;
    background: var(--color-surface);
    border: 1px dashed var(--color-border);
    border-radius: var(--radius-sm);
}

/* ---------- Angemeldeter Bereich: Sidebar-Layout ---------- */

.app-shell {
    display: flex;
    min-height: 100vh;
}

.sidebar {
    width: var(--sidebar-width);
    flex-shrink: 0;
    /* Bewusst fester Hex-Wert statt var(--color-ink): die Seitenleiste bleibt
       unabhaengig vom Hell-/Dunkelmodus immer dunkel (eigene Markenflaeche). */
    background: linear-gradient(190deg, #1c1d21 0%, #111114 100%);
    color: #f1f1f1;
    display: flex;
    flex-direction: column;
    padding: 22px 0 16px;
    position: sticky;
    top: 0;
    height: 100vh;
    overflow-y: auto;
}

.sidebar-brand {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 0 22px;
    margin-bottom: 22px;
}

.sidebar-logo {
    display: block;
    width: 42px;
    height: 42px;
    border-radius: 8px;
    object-fit: cover;
    flex-shrink: 0;
    background: #fff;
}

.sidebar-brand-text {
    line-height: 1.25;
    min-width: 0;
}

.sidebar-brand-name {
    display: block;
    font-weight: 700;
    font-size: 0.95rem;
    color: #fff;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.sidebar-brand-sub {
    display: block;
    font-size: 0.72rem;
    color: #8c8d93;
    text-transform: uppercase;
    letter-spacing: 0.05em;
}

.sidebar-nav {
    list-style: none;
    margin: 0;
    padding: 4px 12px;
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.sidebar-nav li a,
.sidebar-nav li button {
    display: flex;
    align-items: center;
    gap: 12px;
    width: 100%;
    text-align: left;
    padding: 10px 12px;
    color: #c7c8cc;
    border: none;
    border-radius: var(--radius-sm);
    background: none;
    font: inherit;
    font-size: 0.92rem;
    font-weight: 500;
    cursor: pointer;
    transition: background 0.15s ease, color 0.15s ease;
}

.nav-icon {
    flex-shrink: 0;
    width: 18px;
    height: 18px;
    opacity: 0.85;
    transition: color 0.15s ease, opacity 0.15s ease;
}

.sidebar-nav li a:hover,
.sidebar-nav li button:hover {
    background: rgba(255, 255, 255, 0.07);
    color: #fff;
    text-decoration: none;
}

/* Im Ruhezustand bleiben ALLE Symbole der Seitenleiste grau - erst beim
   Ueberfahren nimmt das Symbol den Ton seines Bereichs an. Dadurch ist immer
   nur EIN Farbton gleichzeitig sichtbar; faerbte man alle dauerhaft ein,
   stuende dort eine Regenbogenliste aus 13 Farben. Die Toene sind fuer den
   dunklen Grund aufgehellt (--tone-on-dark). */
.sidebar-nav > li:hover > a .nav-icon,
.sidebar-nav > li > details > .sidebar-nav-group-toggle:hover .nav-icon {
    color: var(--tone-on-dark);
    opacity: 1;
}

.sidebar-nav > li > a.is-active .nav-icon {
    color: #fff;
}

.sidebar-nav li a.is-active {
    background: var(--color-accent);
    color: #fff;
    box-shadow: 0 4px 14px rgba(193, 39, 45, 0.35);
}

.sidebar-nav li a.is-active .nav-icon {
    opacity: 1;
}

.sidebar-nav-group-toggle {
    display: flex;
    align-items: center;
    gap: 12px;
    width: 100%;
    padding: 10px 12px;
    color: #c7c8cc;
    border-radius: var(--radius-sm);
    font-size: 0.92rem;
    font-weight: 500;
    cursor: pointer;
    transition: background 0.15s ease, color 0.15s ease;
    list-style: none;
}

.sidebar-nav-group-toggle::-webkit-details-marker {
    display: none;
}

.sidebar-nav-group-toggle:hover {
    background: rgba(255, 255, 255, 0.07);
    color: #fff;
}

.sidebar-nav-group-toggle span {
    flex: 1;
}

.nav-caret {
    flex-shrink: 0;
    width: 16px;
    height: 16px;
    opacity: 0.7;
    transition: transform 0.15s ease;
}

.sidebar-nav-group[open] .nav-caret {
    transform: rotate(180deg);
}

.sidebar-subnav {
    list-style: none;
    margin: 2px 0 4px;
    padding: 0 0 0 30px;
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.sidebar-subnav a {
    display: block;
    padding: 8px 12px;
    color: #a9aab0;
    border-radius: var(--radius-sm);
    font-size: 0.86rem;
    font-weight: 500;
    text-decoration: none;
    transition: background 0.15s ease, color 0.15s ease;
}

.sidebar-subnav a:hover {
    background: rgba(255, 255, 255, 0.07);
    color: #fff;
}

.sidebar-subnav a.is-active {
    background: var(--color-accent);
    color: #fff;
    box-shadow: 0 4px 14px rgba(193, 39, 45, 0.35);
}

.sidebar-footer {
    padding: 14px 22px 4px;
    border-top: 1px solid rgba(255, 255, 255, 0.09);
    margin: 8px 10px 0;
}

.sidebar-footer form {
    margin: 0;
}

.sidebar-footer button {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    text-align: left;
    padding: 9px 4px;
    color: #9d9ea4;
    border: none;
    background: none;
    font: inherit;
    font-size: 0.88rem;
    font-weight: 600;
    cursor: pointer;
    border-radius: var(--radius-sm);
}

.sidebar-footer button:hover {
    color: #fff;
}

.main-area {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
}

/* Der Topbar ist eine Werkzeugleiste, keine Ablage fuer ein einzelnes Element:
   links die Kontextangabe (Datum), rechts die Aktionen. Beide Enden sind
   verankert - vorher stand nur ein roter Knopf ganz links in einer sonst leeren
   weissen Flaeche und wirkte dadurch wie ein freischwebender Block. */
.topbar {
    background: var(--color-surface);
    border-bottom: 1px solid var(--color-border);
    padding: 0 32px;
    height: var(--topbar-height);
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    position: sticky;
    top: 0;
    z-index: 5;
}

.topbar-context {
    display: flex;
    align-items: center;
    gap: 10px;
    min-width: 0;
}

.topbar-context-icon {
    width: 18px;
    height: 18px;
    flex-shrink: 0;
    color: var(--color-muted);
}

.topbar-context-value {
    display: block;
    font-size: 0.88rem;
    font-weight: 600;
    line-height: 1.2;
    color: var(--color-ink);
}

/* Gleiche Wert-ueber-Label-Struktur wie bei .attention-chip und .stat-list -
   die Leiste folgt damit derselben Mikrotypografie wie der Inhaltsbereich. */
.topbar-context-label {
    display: block;
    margin-top: 2px;
    font-size: 0.68rem;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--color-muted);
}

.topbar-actions {
    display: flex;
    align-items: center;
    gap: 8px;
}

/* Schnellzugriff-Menü im Topbar: bewusst als ruhiges Leisten-Element
   (Umrandung statt Vollflaeche) gestaltet. Rot bleibt damit den primaeren
   Seitenaktionen (".btn-primary" im .page-header) und der aktiven Navigation
   vorbehalten - vorher konkurrierte ein roter "Neu"-Block direkt ueber dem
   ebenfalls roten "Neuer Kunde" der Seite und ueberstrahlte die H1. */
.theme-toggle-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 38px;
    height: 38px;
    padding: 0;
    background: var(--color-surface);
    color: var(--color-ink);
    border: 1px solid var(--color-border-strong);
    border-radius: var(--radius-sm);
    cursor: pointer;
    flex-shrink: 0;
    transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}

/* Hamburger-Menu-Knopf - nur auf schmalen Bildschirmen sichtbar (siehe
   @media max-width:800px), oeffnet die Sidebar als Off-Canvas-Schublade
   (assets/js/sidebar-toggle.js). Gleiche Optik wie .theme-toggle-btn. */
.sidebar-toggle-btn {
    display: none;
    align-items: center;
    justify-content: center;
    /* 44px statt vormals 38px - einziger Zugang zur kompletten Navigation auf
       Mobile, gleiche Mindestgroesse wie .mobile-search-trigger-btn. */
    width: 44px;
    height: 44px;
    padding: 0;
    background: var(--color-surface);
    color: var(--color-ink);
    border: 1px solid var(--color-border-strong);
    border-radius: var(--radius-sm);
    cursor: pointer;
    flex-shrink: 0;
    margin-right: 10px;
}

.sidebar-close-btn {
    display: none;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    padding: 0;
    margin-left: auto;
    flex-shrink: 0;
    background: none;
    color: #c7c8cc;
    border: none;
    border-radius: var(--radius-sm);
    cursor: pointer;
}

.sidebar-close-btn:hover {
    background: rgba(255, 255, 255, 0.08);
    color: #fff;
}

.sidebar-close-btn svg {
    width: 20px;
    height: 20px;
}

.theme-toggle-btn:hover {
    background: var(--color-surface-alt);
    border-color: var(--color-ink-soft);
}

.theme-toggle-btn svg {
    width: 18px;
    height: 18px;
}

.theme-toggle-btn .theme-icon-dark {
    display: none;
}

:root[data-theme="dark"] .theme-toggle-btn .theme-icon-light {
    display: none;
}

:root[data-theme="dark"] .theme-toggle-btn .theme-icon-dark {
    display: inline;
}

.quickcreate {
    position: relative;
}

.quickcreate-toggle {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    list-style: none;
    cursor: pointer;
    background: var(--color-surface);
    color: var(--color-ink);
    border: 1px solid var(--color-border-strong);
    border-radius: var(--radius-sm);
    padding: 7px 10px 7px 11px;
    font-size: 0.85rem;
    font-weight: 600;
    user-select: none;
    transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}

.quickcreate-toggle::-webkit-details-marker,
.quickcreate-toggle::marker {
    display: none;
    content: '';
}

.quickcreate-plus {
    width: 16px;
    height: 16px;
    flex-shrink: 0;
    color: var(--color-accent);
}

.quickcreate-caret {
    width: 14px;
    height: 14px;
    flex-shrink: 0;
    color: var(--color-muted);
    transition: transform 0.15s ease;
}

.quickcreate-toggle:hover {
    background: var(--color-surface-alt);
    border-color: var(--color-accent-soft);
}

.quickcreate[open] .quickcreate-toggle {
    background: var(--color-accent-light);
    border-color: var(--color-accent-soft);
    color: var(--color-accent-dark);
}

.quickcreate[open] .quickcreate-caret {
    transform: rotate(180deg);
    color: var(--color-accent-dark);
}

.quickcreate-panel {
    position: absolute;
    top: calc(100% + 8px);
    right: 0;
    min-width: 232px;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    box-shadow: var(--shadow-menu);
    margin: 0;
    padding: 8px;
    z-index: 20;
}

.quickcreate-group + .quickcreate-group {
    margin-top: 6px;
    padding-top: 6px;
    border-top: 1px solid var(--color-border);
}

.quickcreate-group-label {
    display: block;
    padding: 4px 10px 5px;
    font-size: 0.68rem;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--color-muted);
}

.quickcreate-panel a {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 10px;
    border-radius: var(--radius-sm);
    color: var(--color-ink);
    text-decoration: none;
    font-size: 0.88rem;
    font-weight: 500;
}

/* Icons entsprechen den Symbolen der jeweiligen Zielbereiche in der
   Seitenleiste - der Menueeintrag zeigt damit, wo er hinfuehrt. */
.quickcreate-panel a svg {
    width: 16px;
    height: 16px;
    flex-shrink: 0;
    color: var(--color-muted);
}

.quickcreate-panel a:hover {
    background: var(--color-accent-light);
    color: var(--color-accent-dark);
    text-decoration: none;
}

.quickcreate-panel a:hover svg {
    color: var(--color-accent);
}

.content {
    padding: 26px 32px 40px;
    flex: 1;
    width: 100%;
}

/* ---------- Kacheln / Karten ---------- */

.tile-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: 20px;
    margin-top: 20px;
}

.tile {
    background: var(--color-surface);
    border-radius: var(--radius);
    box-shadow: var(--shadow-card);
    padding: 22px 24px;
    border: 1px solid var(--color-border);
    /* Oberkante und Symbol folgen dem Modulton statt fest Rot zu sein - auf
       der KM-Abrechnung standen sonst drei rote Kachelkanten neben einem
       ansonsten petrolfarbenen Seitenkopf. */
    border-top: 3px solid var(--tone);
    position: relative;
}

.tile .tile-value {
    font-size: 2.1rem;
    font-weight: 700;
    color: var(--color-ink);
    margin: 6px 0;
    letter-spacing: -0.02em;
    font-variant-numeric: tabular-nums;
}

.tile .tile-label {
    color: var(--color-muted);
    font-size: 0.82rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
}

a.tile {
    display: block;
    text-decoration: none;
    color: inherit;
    transition: transform 0.12s ease, box-shadow 0.12s ease, border-color 0.12s ease;
}

a.tile:hover {
    transform: translateY(-2px);
    box-shadow: 0 4px 8px rgba(20, 20, 25, 0.06), 0 8px 24px rgba(20, 20, 25, 0.09);
    border-color: var(--tone);
}

.tile-icon {
    position: absolute;
    top: 18px;
    right: 20px;
    width: 34px;
    height: 34px;
    padding: 7px;
    border-radius: 9px;
    background: var(--tone-bg);
    color: var(--tone);
}

.dashboard-section {
    margin-top: 32px;
}

.dashboard-section:first-of-type {
    margin-top: 24px;
}

.dashboard-section h2 {
    font-size: 0.85rem;
    font-weight: 700;
    color: var(--color-muted);
    text-transform: uppercase;
    letter-spacing: 0.05em;
    margin: 0 0 12px;
}

/* ---------- Dashboard: Aufmerksamkeit-Zeile, Diagramm, kompakte Listen ----------
   Ersetzt die vorherige Version mit 13 gleichrangigen Kacheln (User-Feedback:
   wirkte unübersichtlich) - Zahlen mit Handlungsbedarf sind jetzt farblich
   abgesetzt, der Rest steht kompakt als Liste statt als grosse Kachel. */
/* Einheitlicher Vertikalrhythmus: alle Bloecke im Inhaltsbereich stehen im
   20px-Raster (vorher 20/22/24/28 gemischt). */
.attention-row {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: 14px;
    margin: 0 0 20px;
}

.attention-chip {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 14px 16px;
    border-radius: var(--radius);
    border: 1px solid var(--color-border);
    text-decoration: none;
    color: inherit;
    background: var(--color-surface);
    transition: transform 0.12s ease, box-shadow 0.12s ease;
}

.attention-chip:hover {
    transform: translateY(-2px);
    box-shadow: var(--shadow-card);
}

.attention-chip.is-warn {
    background: var(--color-warning-bg);
    border-color: var(--color-warning-border);
}

.attention-chip.is-ok {
    background: var(--color-success-bg);
    border-color: var(--color-success-border);
}

.attention-chip-icon {
    width: 36px;
    height: 36px;
    padding: 8px;
    border-radius: 10px;
    flex-shrink: 0;
}

.attention-chip.is-warn .attention-chip-icon {
    color: var(--color-warning);
    background: rgba(146, 101, 10, 0.13);
}

.attention-chip.is-ok .attention-chip-icon {
    color: var(--color-success);
    background: rgba(30, 122, 61, 0.13);
}

.attention-chip-value {
    font-size: 1.5rem;
    font-weight: 700;
    line-height: 1;
    font-variant-numeric: tabular-nums;
}

.attention-chip-label {
    font-size: 0.78rem;
    color: var(--color-muted);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    margin-top: 2px;
}

/* Schmale, IMMER sichtbare Statuszeile fuer die MWST-Frist (siehe
   templates/dashboard.php) - bewusst KEINE Kachel im .attention-row-Raster,
   da es sich um einen Dauerstatus handelt, nicht um einen taeglichen
   Handlungspunkt. Deutlich flacher als .attention-chip, damit sie visuell
   klar als eigene Kategorie erkennbar ist. */
.vat-status-line {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 14px;
    border-radius: var(--radius);
    border: 1px solid var(--color-border);
    text-decoration: none;
    color: inherit;
    font-size: 0.85rem;
    font-weight: 600;
    margin: 0 0 16px;
    background: var(--color-surface);
    transition: transform 0.12s ease, box-shadow 0.12s ease;
}

.vat-status-line:hover {
    transform: translateY(-1px);
    box-shadow: var(--shadow-card);
}

.vat-status-line.is-warn {
    background: var(--color-warning-bg);
    border-color: var(--color-warning-border);
    color: var(--color-warning);
}

.vat-status-line.is-ok {
    background: var(--color-success-bg);
    border-color: var(--color-success-border);
    color: var(--color-success);
}

.vat-status-icon {
    width: 18px;
    height: 18px;
    flex-shrink: 0;
}

.dashboard-columns {
    display: grid;
    grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr);
    gap: 20px;
    align-items: start;
}

@media (max-width: 1080px) {
    .dashboard-columns {
        grid-template-columns: 1fr;
    }
}

.chart-stats {
    display: flex;
    gap: 28px;
    margin-bottom: 16px;
}

.chart-stat {
    text-decoration: none;
    color: inherit;
    display: block;
}

.chart-stat-value {
    font-size: 1.35rem;
    font-weight: 700;
    color: var(--color-ink);
    font-variant-numeric: tabular-nums;
}

.chart-stat-label {
    font-size: 0.75rem;
    color: var(--color-muted);
    text-transform: uppercase;
    letter-spacing: 0.03em;
}

.chart-bars {
    display: flex;
    align-items: flex-end;
    gap: 10px;
    height: 130px;
    margin-top: 8px;
    border-top: 1px solid var(--color-border);
    padding-top: 10px;
}

.chart-bar-col {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: flex-end;
    height: 100%;
}

.chart-bar-value {
    font-size: 0.7rem;
    color: var(--color-muted);
    margin-bottom: 4px;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.chart-bar {
    width: 100%;
    max-width: 40px;
    background: var(--color-accent);
    opacity: 0.55;
    border-radius: 3px 3px 0 0;
    min-height: 3px;
}

.chart-bar-col.is-current .chart-bar {
    opacity: 1;
}

.chart-bar-col.is-current .chart-bar-value {
    color: var(--color-ink);
    font-weight: 700;
}

.chart-bar-label {
    font-size: 0.72rem;
    color: var(--color-muted);
    margin-top: 6px;
    text-transform: uppercase;
    letter-spacing: 0.02em;
}

.stat-list-card + .stat-list-card {
    margin-top: 20px;
}

.stat-list {
    list-style: none;
    margin: 0;
    padding: 0;
}

.stat-list li + li {
    border-top: 1px solid var(--color-border);
}

.stat-list a {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 11px 6px;
    text-decoration: none;
    color: inherit;
    border-radius: 6px;
}

.stat-list a:hover {
    background: var(--color-surface-alt);
}

/* Das Symbol sitzt in einer getoenten Plakette statt nackt in der Zeile.
   Padding/Hintergrund werden direkt auf das <svg> gelegt - so bleibt die
   Vorlage unveraendert (ein SVG ist ein ersetztes Element, Innenabstand und
   Hintergrund wirken darauf ganz normal, box-sizing:border-box gilt global). */
.stat-list-icon {
    width: 32px;
    height: 32px;
    padding: 7px;
    border-radius: 9px;
    background: var(--tone-bg);
    color: var(--tone);
    flex-shrink: 0;
    transition: background 0.15s ease, color 0.15s ease;
}

.stat-list a:hover .stat-list-icon {
    background: var(--tone);
    color: #fff;
}

.stat-list-label {
    flex: 1;
    font-size: 0.9rem;
    color: var(--color-ink);
}

.stat-list-value {
    font-size: 0.95rem;
    font-weight: 700;
    color: var(--color-ink);
    font-variant-numeric: tabular-nums;
}

.card {
    background: var(--color-surface);
    border-radius: var(--radius);
    box-shadow: var(--shadow-card);
    border: 1px solid var(--color-border);
    padding: 26px 28px;
    margin-bottom: 20px;
}

.card > h2:first-child,
.card > h3:first-child {
    margin-top: 0;
}

/* Kartentitel sind EINE Hierarchiestufe, unabhaengig davon, ob die Vorlage
   historisch <h2> oder <h3> verwendet (die Aufwertung von h3 auf h2 ist in
   den Vorlagen nachgezogen, diese Regel haelt kuenftige Abweichungen davon
   optisch trotzdem auf einer Linie). Vorher war "Firmendaten" (h2, 1.2rem)
   sichtbar groesser als "Positionen" (h3, 1.05rem) - zwei Karten desselben
   Rangs auf zwei verschiedenen Seiten in zwei Groessen. */
.card > h2,
.card > h3,
.card-title-row h2,
.card-title-row h3 {
    font-size: 1.05rem;
    font-weight: 600;
    letter-spacing: -0.005em;
}

.order-card {
    padding: 0;
}

.order-summary {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    padding: 18px 28px;
    cursor: pointer;
    list-style: none;
    font-size: 0.95rem;
    flex-wrap: wrap;
}

.order-summary::-webkit-details-marker {
    display: none;
}

.order-summary-main {
    display: flex;
    align-items: baseline;
    gap: 10px;
}

.order-summary-meta {
    display: flex;
    align-items: center;
    gap: 14px;
    color: var(--color-muted);
    font-size: 0.88rem;
}

/* Feste Spaltenbreiten fuer Typ/Status/Datum/Total/Dokumente-Anzahl, damit sie
   ueber alle Auftragszeilen hinweg sauber untereinander ausgerichtet sind -
   ohne feste Breite richtet sich jede Spalte nur nach ihrem eigenen Inhalt
   (z.B. "Rechnung" vs. "Auftragsbestätigung") und rutscht von Zeile zu Zeile. */
.order-meta-col {
    flex: 0 0 auto;
}

.order-meta-type {
    width: 150px;
}

.order-meta-status {
    width: 110px;
}

.order-meta-date {
    width: 80px;
}

.order-meta-total {
    width: 100px;
    text-align: right;
}

.order-meta-count {
    width: 110px;
}

.order-caret {
    opacity: 0.6;
}

.order-card[open] .order-summary {
    border-bottom: 1px solid var(--color-border);
}

.order-card[open] .order-caret {
    transform: rotate(180deg);
}

.order-card .table-scroll {
    padding: 4px 28px 22px;
}

.card-title-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    margin-bottom: 18px;
}

.card-title-row h2, .card-title-row h3 {
    margin: 0;
}

table {
    width: 100%;
    border-collapse: collapse;
}

table th, table td {
    padding: 11px 14px;
    border-bottom: 1px solid var(--color-border);
    text-align: left;
    font-size: 0.92rem;
    vertical-align: top;
}

table th {
    color: var(--color-muted);
    font-size: 0.76rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    background: var(--color-surface-alt);
    border-bottom: 1px solid var(--color-border-strong);
    /* Unten statt oben ausgerichtet: sobald EIN Spaltentitel zweizeilig
       umbricht ("Preis (CHF)", "Betrag CHF"), stehen sonst alle uebrigen
       Titel oben und der lange haengt darunter - unten ausgerichtet sitzen
       alle Titel auf derselben Grundlinie direkt ueber der Trennlinie. */
    vertical-align: bottom;
}

/* Betraege/Mengen gehoeren rechtsbuendig und mit gleich breiten Ziffern -
   sonst fluchten die Kommastellen untereinander nicht, was in einer
   Geschaeftsanwendung sofort unsauber wirkt. Gilt fuer Kopf UND Zelle,
   damit der Spaltentitel ueber seinen Zahlen steht. */
table th.num,
table td.num {
    text-align: right;
    font-variant-numeric: tabular-nums;
}

table tbody tr {
    transition: background 0.13s ease, box-shadow 0.13s ease;
}

/* Beim Ueberfahren bekommt die Zeile zusaetzlich zur Flaeche eine schmale
   Markierung am linken Rand im Modulton - in langen Tabellen findet man die
   Zeile, in der der Zeiger steht, dadurch deutlich schneller wieder. */
table tbody tr:hover {
    background: var(--color-surface-alt);
    box-shadow: inset 3px 0 0 var(--tone);
}

.doc-list {
    display: flex;
    flex-direction: column;
    margin-bottom: 20px;
}

.doc-list-item {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: 16px;
    padding: 14px 10px;
    border-bottom: 1px solid var(--color-border);
    border-radius: 6px;
}

.doc-list-item:first-child {
    padding-top: 4px;
}

.doc-list-item:last-child {
    border-bottom: none;
}

.doc-list-item-main {
    min-width: 0;
}

.doc-list-item-title {
    margin: 0 0 4px 0;
    font-weight: 600;
}

.doc-list-item-title a {
    color: var(--color-ink);
    text-decoration: none;
}

.doc-list-item-title a:hover {
    color: var(--color-accent);
    text-decoration: underline;
}

.doc-list-item-summary {
    margin: 0 0 6px 0;
    color: var(--color-muted);
    font-size: 0.88rem;
    line-height: 1.4;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.doc-list-item-meta {
    margin: 0;
    color: var(--color-muted);
    font-size: 0.78rem;
}

.doc-list-item-notes {
    margin: 6px 0 0 0;
    color: var(--color-warning);
    font-size: 0.82rem;
}

.doc-list-item-actions {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 6px;
    flex-shrink: 0;
    white-space: nowrap;
    padding-top: 2px;
}

.doc-list-item-actions form {
    margin: 0;
}

.inventory-doc-row-active,
.ho-doc-row-active {
    background: var(--color-surface-alt);
    box-shadow: inset 3px 0 0 var(--color-border-strong);
}

/* Gemeinsame Pager-Leiste am Ende paginierter Listen (siehe templates/partials/pagination.php). */
.pagination {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 12px;
    margin-top: 18px;
    padding-top: 16px;
    border-top: 1px solid var(--color-border);
}

.pagination-info {
    color: var(--color-muted);
    font-size: 0.85rem;
}

.pagination-nav {
    display: flex;
    gap: 10px;
}

/* Generische Mehrfachdatei-Upload-Zone mit Drag&Drop (z.B. Büroraum-Dokumente) -
   analog zum Muster in templates/expenses/list.php, hier zentral statt inline. */
.file-dropzone {
    border: 2px dashed var(--color-border);
    border-radius: var(--radius-sm);
    padding: 24px 16px;
    text-align: center;
    transition: border-color .15s, background .15s;
}

.file-dropzone.is-dragover {
    border-color: var(--color-accent);
    background: var(--color-surface-alt);
}

.file-dropzone-input {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

.file-dropzone-icon {
    width: 44px;
    height: 44px;
    padding: 11px;
    border-radius: 12px;
    background: var(--tone-bg);
    color: var(--tone);
    display: block;
    margin: 0 auto 12px;
    transition: transform 0.15s ease;
}

.file-dropzone.is-dragover .file-dropzone-icon {
    transform: translateY(-3px);
}

.file-dropzone label.btn {
    cursor: pointer;
}

/* .file-dropzone-input selbst ist auf 1x1px geclippt - siehe Kommentar bei
   .file-input-pretty:focus-visible weiter oben, gleicher Grund/gleiche Loesung. */
.file-dropzone-input:focus-visible ~ label.btn {
    outline: 2px solid var(--color-accent);
    outline-offset: 2px;
    box-shadow: var(--shadow-focus);
}

.file-dropzone-list {
    list-style: none;
    margin: 14px auto 0;
    padding: 0;
    max-width: 480px;
    text-align: left;
}

.file-dropzone-list li {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 6px 10px;
    margin-bottom: 5px;
    background: var(--color-surface-alt);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    font-size: 0.85rem;
}

.file-dropzone-name {
    flex: 1;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.file-dropzone-size {
    color: var(--color-muted);
    font-size: 0.78rem;
    flex-shrink: 0;
}

.file-dropzone-remove {
    flex-shrink: 0;
    width: 20px;
    height: 20px;
    line-height: 1;
    border: none;
    border-radius: 50%;
    background: transparent;
    color: var(--color-muted);
    font-size: 1.1rem;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: background .15s, color .15s;
}

.file-dropzone-remove:hover {
    background: var(--color-danger);
    color: #fff;
}

.pill-muted {
    display: inline-block;
    margin-left: 6px;
    padding: 2px 8px;
    border-radius: 999px;
    background: var(--color-bg);
    color: var(--color-ink-soft);
    font-size: 0.72rem;
    font-weight: 700;
    text-decoration: none;
    white-space: nowrap;
    vertical-align: middle;
}

.pill-muted:hover {
    background: var(--color-border);
    text-decoration: none;
}

/* Ohne diese Regel gewinnt ".pill-muted { display: inline-block; }" gegen die
   UA-Stylesheet-Regel "[hidden] { display: none; }" (gleiche Spezifitaet,
   aber die Autoren-Regel steht spaeter in der Kaskade) - die externe-
   Datenquellen-Badges (".pill-muted.data-source-badge[hidden]", siehe
   Kunden-/Dokument-/KM-/Firmen-Formulare) waeren dadurch IMMER sichtbar
   gewesen, unabhaengig vom hidden-Attribut. */
.pill-muted[hidden] {
    display: none;
}

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

.card > .table-scroll:first-child table th:first-child,
.card table th:first-child,
.card table td:first-child {
    padding-left: 4px;
}

.qr-box {
    text-align: center;
    margin: 16px 0;
}

.qr-box img {
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    padding: 10px;
    background: #fff;
}

/* ---------- Kunden & Produkte: Listen/Formulare ---------- */

/* Der Seitenkopf ist eine eigene Zone mit abschliessender Haarlinie. Zusammen
   mit der Unterkante des Topbars rahmen zwei parallele Linien den Kopfbereich -
   Leiste und Inhalt lesen sich dadurch als ein gestapeltes Kopfsystem statt als
   zwei unverbundene Flaechen. */
.page-header {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    margin-bottom: 20px;
    padding-bottom: 16px;
    border-bottom: 1px solid var(--color-border);
    flex-wrap: wrap;
}

/* Kurzes farbiges Stueck auf der Abschluss-Haarlinie des Seitenkopfs. Es
   traegt den Ton des jeweiligen Moduls (siehe <main class="content tone-*">)
   und ist damit der einzige Akzent, der auf JEDER Seite automatisch da ist -
   ohne dass eine einzelne Vorlage etwas dafuer tun muesste. */
.page-header::after {
    content: "";
    position: absolute;
    left: 0;
    bottom: -1px;
    width: 54px;
    height: 2px;
    border-radius: 2px;
    background: var(--tone);
}

.page-header h1 {
    margin: 0;
}

/* Titelblock mit farbiger Icon-Plakette links davor. Die Plakette wiederholt
   das Symbol des Bereichs aus der Seitenleiste - der Kopf der Seite und der
   aktive Navigationseintrag zeigen damit dasselbe Zeichen. */
.page-title {
    display: flex;
    align-items: center;
    gap: 14px;
    min-width: 0;
}

.page-title > div {
    min-width: 0;
}

.page-title p {
    margin-bottom: 0;
}

.page-header-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

/* Jedes Filterfeld bekommt ein Label OBERHALB des Feldes (konsistent ueber
   alle Filterleisten hinweg) - dafuer .filter-field als eigene Spalte
   (Label+Feld gestapelt), damit alle Felder gleich hoch sind. align-items:
   flex-end statt center sorgt dafuer, dass der "Filtern"-Knopf (ohne eigenes
   Label darueber) trotzdem auf gleicher Hoehe wie die Eingabefelder sitzt,
   statt an allen Feldern inkl. Label vertikal zentriert und damit verschoben
   zu wirken (siehe z.B. vorher Von/Bis bei Ausgaben). */
.filter-bar {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: 10px;
    margin-bottom: 20px;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    padding: 14px 16px;
}

.filter-field {
    display: flex;
    flex-direction: column;
    gap: 6px;
    min-width: 0;
}

.filter-field label {
    margin-bottom: 0;
    white-space: nowrap;
}

.filter-field-grow {
    flex: 1;
    min-width: 220px;
}

.filter-bar input[type="text"],
.filter-bar input[type="date"] {
    width: 100%;
}

.filter-bar select {
    width: auto;
}

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

/* Klick-zum-Waehlen-Icon hinter formatierten Telefonnummern (siehe
   Itsb\Support\PhoneFormatter::renderLink()) - Kontakte/Kunden-Listen. */
.phone-call-link {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    vertical-align: middle;
    margin-left: 6px;
    color: var(--color-accent);
}

.phone-call-link:hover {
    color: var(--color-accent-dark);
}

.phone-call-icon {
    width: 14px;
    height: 14px;
}

.form-row {
    display: flex;
    flex-wrap: wrap;
    gap: 16px;
}

.form-row .form-group {
    flex: 1;
    min-width: 160px;
}

.form-group-small {
    flex: 0 0 110px !important;
}

.form-group-grow {
    flex: 2 !important;
}

/* Vorwahl-Dropdown + Rufnummer-Rest fuer Telefon/Handy bei Kontakten (siehe
   assets/js/phone-input.js) - beide kombinieren sich in ein verstecktes Feld. */
.phone-input-group {
    display: flex;
    gap: 8px;
}

.phone-input-group .phone-dial-code {
    flex: 0 0 150px;
}

.phone-input-group .phone-number-rest {
    flex: 1;
    min-width: 0;
}

.form-section-heading {
    font-size: 0.76rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.4px;
    color: var(--color-muted);
    margin: 22px 0 12px 0;
    padding-bottom: 6px;
    border-bottom: 1px solid var(--color-border);
}

/* Kleiner Tonpunkt vor jeder Abschnittsueberschrift - laesst die langen
   Formulare (Kunde, Mitarbeiter, Firma) optisch in Bloecke zerfallen, statt
   nur aus grauen Grossbuchstabenzeilen zu bestehen. */
.form-section-heading::before {
    content: "";
    display: inline-block;
    width: 6px;
    height: 6px;
    margin-right: 9px;
    border-radius: 2px;
    background: var(--tone);
    vertical-align: 1px;
}

.form-section-heading:first-child {
    margin-top: 0;
}

.info-grid {
    display: flex;
    flex-wrap: wrap;
    gap: 24px;
}

.info-grid > div {
    min-width: 160px;
}

.info-grid p:first-child {
    margin-bottom: 2px;
}

.info-grid p:last-child {
    margin-bottom: 0;
    font-weight: 600;
}

.table-scroll {
    overflow-x: auto;
}

/* Responsive Tabellen: nur horizontales Scrollen zu erzwingen, um an
   Bearbeiten/Löschen-Knöpfe am rechten Rand zu kommen, fühlt sich auf
   Mobile wie fehlende Funktionen an (User-Feedback) - deshalb wird jede
   Zeile einer table.responsive-stack auf schmalen Bildschirmen zu einer
   eigenen Karte, jede Spalte zeigt ihren Spaltentitel als Label darueber
   (aus dem data-label-Attribut der jeweiligen <td>), Aktions-Buttons bleiben
   immer sofort sichtbar statt am Ende einer breiten Zeile versteckt. */
@media (max-width: 700px) {
    table.responsive-stack thead {
        display: none;
    }

    table.responsive-stack,
    table.responsive-stack tbody,
    table.responsive-stack tfoot,
    table.responsive-stack tr,
    table.responsive-stack td {
        display: block;
        width: 100%;
    }

    /* Gleicher Bug wie .pill-muted[hidden] weiter oben: "display: block" auf
       table.responsive-stack tr hat dieselbe Spezifitaet wie die native
       [hidden]-UA-Regel und gewinnt, da Autoren-Stylesheets nach UA-Stylesheets
       geladen werden - ohne diese Regel bliebe eine per hidden-Attribut
       ausgeblendete Zeile (z.B. die "Status verfolgen"-Ergebniszeile) auf
       schmalen Viewports trotzdem sichtbar UND liesse sich nie mehr einklappen. */
    table.responsive-stack tr[hidden] {
        display: none;
    }

    table.responsive-stack tr {
        margin-bottom: 14px;
        border: 1px solid var(--color-border);
        border-radius: var(--radius);
        padding: 12px 14px;
    }

    table.responsive-stack tbody tr:last-child {
        margin-bottom: 0;
    }

    table.responsive-stack td {
        border-bottom: none;
        padding: 6px 0;
    }

    table.responsive-stack td[data-label]::before {
        content: attr(data-label);
        display: block;
        font-size: 0.72rem;
        font-weight: 700;
        text-transform: uppercase;
        letter-spacing: 0.03em;
        color: var(--color-muted);
        margin-bottom: 2px;
    }

    table.responsive-stack td.table-actions {
        text-align: left;
        margin-top: 8px;
        padding-top: 12px;
        border-top: 1px solid var(--color-border);
    }

    table.responsive-stack td.num {
        text-align: left;
    }
}

.branding-preview {
    display: flex;
    align-items: center;
    padding: 10px;
    margin-bottom: 8px;
    background: repeating-conic-gradient(#f0f0f2 0% 25%, #ffffff 0% 50%) 50% / 16px 16px;
    border: 1px solid #e3e4e8;
    border-radius: 6px;
    width: fit-content;
}

.branding-preview-logo {
    max-width: 220px;
    max-height: 90px;
}

.branding-preview-favicon {
    width: 40px;
    height: 40px;
}

.progress-bar-track {
    width: 100%;
    max-width: 420px;
    height: 10px;
    background: var(--color-border);
    border-radius: 6px;
    overflow: hidden;
}

.progress-bar-fill {
    height: 100%;
    width: 0%;
    background: var(--color-accent);
    transition: width 0.4s ease;
}

/* Bewusst KEIN display:flex hier - ein <td> mit display:flex wird zur echten
   Flexbox und verlaesst damit die normale Tabellenzellen-Boxgroesse: seine
   Randlinie/Hoehe folgt dann nur noch seinem eigenen (kleineren) Inhalt statt
   der Zeilenhoehe, was bei Zeilen mit mehrzeiligem Inhalt in anderen Spalten
   (z.B. mehrere Firmen-Badges) zu einer sichtbar falsch positionierten
   unteren Trennlinie fuehrt. Stattdessen bleibt die Zelle ein normales
   table-cell und die Kinder (Links/Formulare) werden per Margin statt Gap
   auf Abstand gehalten. */
.table-actions {
    white-space: nowrap;
    text-align: right;
}

.table-actions > * {
    margin-right: 14px;
}

.table-actions > *:last-child {
    margin-right: 0;
}

/* Automatisch eingeblendete KM-Spesen-Zeile in der Ausgaben-Liste (kein
   eigener Beleg, aus der KM-Abrechnung uebernommen) - dezent kursiv, damit
   sie sich von echten hochgeladenen Belegen unterscheidet. */
.expense-row-mileage {
    font-style: italic;
    color: var(--color-muted);
}

.inline-form {
    display: inline;
}

/* Bleibt beim Scrollen durch viele Positionszeilen sichtbar am unteren
   Viewport-Rand (Dokument-Formulare, templates/documents/show.php und
   form.php) statt dass man fuers Speichern immer ganz nach unten scrollen
   muss - negative Rand-Korrektur gleicht das .card-Padding aus, damit die
   Leiste ueber die volle Kartenbreite geht. */
.sticky-action-bar {
    position: sticky;
    bottom: 0;
    margin: 16px -28px -28px;
    padding: 14px 28px;
    background: var(--color-surface);
    border-top: 1px solid var(--color-border);
    border-radius: 0 0 var(--radius) var(--radius);
    z-index: 10;
}

.actions-row {
    display: flex;
    flex-wrap: wrap;
    gap: 24px;
    align-items: flex-end;
}

.button-row {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    align-items: center;
    margin-top: 4px;
}

/* ---------- Dokumente: Positionen/Summen ---------- */

#line-items-table input,
#line-items-table select {
    padding: 7px 9px;
    font-size: 0.88rem;
}

#line-items-table input:disabled,
#line-items-table select:disabled {
    background: var(--color-surface-alt);
    color: var(--color-ink-soft);
}

/* vertical-align:middle statt des geerbten "top": in einer Positionszeile
   stehen sonst reine Textzellen (der Betrag) am oberen Zellenrand, waehrend
   die Eingabefelder derselben Zeile durch ihr eigenes Padding rund 8px tiefer
   sitzen - der Betrag schwebte sichtbar ueber seiner Zeile. */
.li-line-total {
    text-align: right;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
    font-weight: 600;
    vertical-align: middle;
}

.li-drag-handle {
    cursor: grab;
    text-align: center;
    color: var(--color-ink-soft);
    user-select: none;
    font-size: 1rem;
}
.li-drag-handle:active {
    cursor: grabbing;
}
tr.line-item-row.is-dragging {
    opacity: 0.4;
}

.doc-summary {
    max-width: 320px;
    margin-left: auto;
    margin-top: 18px;
}

.doc-summary-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 12px;
    padding: 7px 0;
    border-bottom: 1px solid var(--color-border);
    font-size: 0.94rem;
}

.doc-summary-row input {
    text-align: right;
}

.doc-summary-total {
    font-weight: 700;
    font-size: 1.15rem;
    border-bottom: none;
    border-top: 2px solid var(--color-ink);
    margin-top: 4px;
    padding-top: 12px;
    color: var(--color-ink);
}

.doc-summary-total span:last-child {
    color: var(--color-accent);
}

/* Zugehoerige Dokumente (Offerte -> AB -> Rechnung -> Lieferschein) als
   horizontale Kette statt einer schlichten Aufzaehlungsliste - zeigt Typ,
   Nummer und Status jedes Dokuments auf einen Blick, aktuelles Dokument
   hervorgehoben. */
.doc-chain-flow {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px;
}

.doc-chain-item {
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding: 8px 14px;
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    background: var(--color-surface-alt);
    text-decoration: none;
    color: inherit;
    transition: border-color 0.15s ease, background 0.15s ease;
}

a.doc-chain-item:hover {
    border-color: var(--color-accent);
    background: var(--color-surface);
}

.doc-chain-current {
    border-color: var(--color-accent);
    background: var(--color-surface);
    box-shadow: 0 0 0 1px var(--color-accent);
}

.doc-chain-type {
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--color-muted);
}

.doc-chain-number {
    font-weight: 700;
    font-size: 0.92rem;
}

.doc-chain-arrow {
    display: flex;
    align-items: center;
    color: var(--color-muted);
    flex-shrink: 0;
}

.doc-chain-arrow svg {
    width: 16px;
    height: 16px;
}

/* Einfache Ergebnisliste der globalen Suche (templates/search/results.php) -
   je Kategorie-Karte eine schlichte Link-Liste statt einer Tabelle, da hier
   nur ein Label + Link pro Treffer noetig ist, keine Spalten. */
.doc-chain-list-plain {
    list-style: none;
    margin: 0;
    padding: 0;
}

.doc-chain-list-plain li {
    padding: 8px 0;
    border-bottom: 1px solid var(--color-border);
}

.doc-chain-list-plain li:last-child {
    border-bottom: none;
}

/* ---------- Inventar: Seriennummern-Zuordnung in Positionen ---------- */

.serial-list {
    margin: 0;
    padding-left: 16px;
    font-size: 0.85rem;
}

.serial-list li {
    padding: 1px 0;
}

/* ---------- Platzhalter-Liste (E-Mail-Vorlagen): Copy-Button ---------- */

.placeholder-copy-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 20px;
    height: 20px;
    margin-left: 4px;
    padding: 0;
    border: 1px solid var(--color-border);
    border-radius: 4px;
    background: var(--color-surface);
    color: var(--color-muted);
    cursor: pointer;
    vertical-align: middle;
    line-height: 1;
}

/* ---------- Datei-auswählen-Buttons: nativen Input verstecken, Label als Button (siehe assets/js/file-input-pretty.js) ---------- */

.file-input-pretty-wrap {
    display: inline-flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 10px;
}

.file-input-pretty {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

.file-input-pretty-label {
    cursor: pointer;
}

/* .file-input-pretty selbst ist auf 1x1px geclippt (siehe oben) - ein
   Tastatur-Fokus darauf war dadurch bisher komplett unsichtbar, da der
   fokussierte Input selbst nirgends sichtbar auf dem Bildschirm liegt. Der
   sichtbare Label-"Button" direkt danach im DOM bekommt daher stellvertretend
   den Fokus-Ring. */
.file-input-pretty:focus-visible ~ .file-input-pretty-label {
    outline: 2px solid var(--color-accent);
    outline-offset: 2px;
    box-shadow: var(--shadow-focus);
}

.file-input-pretty-filename {
    color: var(--color-muted);
    font-size: 0.85rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 320px;
}

.placeholder-copy-btn:hover {
    background: var(--color-border);
    color: var(--color-ink);
}

.placeholder-copy-btn svg {
    width: 12px;
    height: 12px;
}

.placeholder-copy-btn.is-copied {
    border-color: var(--color-success-border);
    background: var(--color-success-bg);
    color: var(--color-success);
}

.serial-checkbox-list {
    display: flex;
    flex-direction: column;
    gap: 4px;
    max-height: 140px;
    overflow-y: auto;
}

.serial-checkbox {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 0.85rem;
    font-weight: 400;
}

.serial-checkbox.is-disabled {
    opacity: 0.6;
    cursor: not-allowed;
}

.serial-checkbox.is-disabled input[aria-disabled="true"] {
    pointer-events: none;
}

/* ---------- Einstellungen: Tab-Leiste (Sicherheit / Firma / Vorlagen) ---------- */

.settings-tabs {
    display: flex;
    gap: 4px;
    margin-bottom: 20px;
    background: var(--color-surface);
    padding: 4px;
    border-radius: var(--radius-sm);
    border: 1px solid var(--color-border);
    width: fit-content;
    max-width: 100%;
    overflow-x: auto;
}

.settings-tab {
    flex-shrink: 0;
    padding: 9px 18px;
    border-radius: 5px;
    font-size: 0.88rem;
    font-weight: 600;
    color: var(--color-muted);
    transition: background 0.15s ease, color 0.15s ease;
}

.settings-tab:hover {
    color: var(--color-ink);
    text-decoration: none;
    background: var(--color-surface-alt);
}

.settings-tab.is-active {
    color: #fff;
    background: var(--color-ink);
}

/* ---------- Responsive ---------- */

@media (max-width: 960px) {
    :root {
        --sidebar-width: 210px;
    }

    .content {
        padding: 22px 24px 32px;
    }

    .card {
        padding: 20px;
    }
}

@media (max-width: 800px) {
    .app-shell {
        flex-direction: column;
    }

    /* Vollflaechiges Overlay mit Drill-Down statt der fruehreren schmalen
       Off-Canvas-Schublade mit Inline-Akkordeon (siehe Verlaufskommentare in
       frueheren Runden) - eine 260px-Schublade mit allen 13 Hauptpunkten UND
       einem aufgeklappten Untermenue (z.B. "Einstellungen" mit 8 Punkten)
       brauchte trotz mehrfacher Kompaktierung fast immer eine Scrollbar, und
       der Firmenname/Logo-Kopf wirkte auf schmalen Schirmen abgeschnitten.
       Jetzt: die Sidebar nimmt den ganzen Bildschirm ein, und ein Tippen auf
       eine Gruppe (z.B. "Kunden") zeigt NUR noch deren Positionen an (siehe
       :has()-Regeln unten) statt sie unter den anderen 12 Punkten einzublenden
       - "Zurueck" ist ein erneuter Tipp auf dieselbe Gruppen-Kopfzeile (jetzt
       mit Rueck-Pfeil statt Aufklapp-Chevron). assets/js/sidebar-toggle.js
       sorgt dafuer, dass a) nie mehr als eine Gruppe gleichzeitig offen ist
       und b) beim Schliessen des Menuees immer wieder bei der Hauptliste
       begonnen wird. */
    .sidebar {
        position: fixed;
        top: 0;
        left: 0;
        width: 100%;
        max-width: 100vw;
        height: 100vh;
        flex-direction: column;
        overflow-x: hidden;
        overflow-y: auto;
        padding: 0;
        transform: translateX(-100%);
        transition: transform 0.2s ease;
        z-index: 60;
    }

    .sidebar.is-open {
        transform: translateX(0);
    }

    .sidebar-backdrop {
        display: none;
    }

    .sidebar-nav li a,
    .sidebar-nav li button {
        white-space: normal;
    }

    .sidebar-toggle-btn {
        display: flex;
    }

    .sidebar-close-btn {
        display: flex;
    }

    .sidebar-brand {
        /* env(safe-area-inset-top) haelt Logo/Firmenname bei Geraeten mit
           Notch/Dynamic-Island unter der Status-/Kamera-Aussparung frei -
           ohne das sass die Kopfzeile bei manchen Geraeten sichtbar zu weit
           oben und wirkte "abgeschnitten". */
        padding: max(16px, env(safe-area-inset-top)) 16px 14px;
        margin-bottom: 4px;
        flex-shrink: 0;
    }

    .sidebar-logo {
        width: 36px;
        height: 36px;
    }

    .sidebar-nav {
        padding: 6px 12px;
        gap: 2px;
    }

    .sidebar-nav li a,
    .sidebar-nav li button,
    .sidebar-nav-group-toggle {
        padding: 12px 14px;
        font-size: 0.95rem;
    }

    /* Aktive Gruppe: Kopfzeile wird zur "Zurueck"-Zeile, Chevron zeigt statt
       nach unten/oben zurueck zur Hauptliste. Nur EINE Gruppe kann laut JS
       gleichzeitig [open] sein, daher ist diese Regel eindeutig. */
    .sidebar-nav-group[open] > .sidebar-nav-group-toggle .nav-caret {
        transform: rotate(90deg);
    }

    .sidebar-nav-group[open] > .sidebar-nav-group-toggle span::before {
        content: "← ";
    }

    /* Drill-Down: sobald irgendeine Gruppe offen ist, alle ANDEREN
       Hauptpunkte ausblenden - es bleibt nur deren eigene Kopfzeile (jetzt
       als "Zurueck") plus ihre eigene Positionsliste sichtbar, wie ein
       eigener Bildschirm. */
    .sidebar-nav:has(.sidebar-nav-group[open]) > li:not(:has(.sidebar-nav-group[open])) {
        display: none;
    }

    .sidebar:has(.sidebar-nav-group[open]) .sidebar-footer {
        display: none;
    }

    .sidebar-subnav {
        margin: 2px 0 4px;
        padding-left: 0;
        gap: 2px;
    }

    .sidebar-subnav a {
        padding: 12px 14px 12px 42px;
        font-size: 0.93rem;
    }

    .sidebar-footer {
        padding: 10px 16px max(10px, env(safe-area-inset-bottom));
        margin: 4px 8px 0;
        flex-shrink: 0;
    }

    .sidebar-footer button {
        padding: 10px 6px;
    }

    /* Falls trotz der vollen Bildschirmhoehe noch gescrollt werden muss (z.B.
       ein sehr niedriger Viewport UND die "Einstellungen"-Gruppe mit 10
       Punkten): schmale, dezente Scrollbar statt der vollen OS-Standardbreite. */
    .sidebar {
        scrollbar-width: thin;
        scrollbar-color: rgba(255, 255, 255, 0.25) transparent;
    }

    .sidebar::-webkit-scrollbar {
        width: 5px;
    }

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

    .sidebar::-webkit-scrollbar-thumb {
        background: rgba(255, 255, 255, 0.25);
        border-radius: 3px;
    }

    /* .order-summary (Aufträge-Liste, geschachtelte Auftragskette) hat auf
       Desktop 5 feste Spaltenbreiten fuer sauberes Ausrichten uebereinander
       liegender Karten - auf schmalen Bildschirmen sprengte das ohne
       Wrapping die Kartenbreite und riss die ganze Seite horizontal auf
       (kein .table-scroll-Container, da hier kein <table>, sondern
       Flex-Spans). Feste Breiten aufheben + umbrechen lassen. */
    .order-summary {
        flex-wrap: wrap;
        row-gap: 8px;
    }

    .order-summary-meta {
        flex-wrap: wrap;
        width: 100%;
        justify-content: flex-start;
    }

    .order-meta-type,
    .order-meta-status,
    .order-meta-date,
    .order-meta-total,
    .order-meta-count {
        width: auto;
    }

    .topbar {
        padding: 0 20px;
    }

    /* Auf schmalen Schirmen bleibt nur das Datum selbst - der Wochentag ist
       dort die erste entbehrliche Angabe. */
    .topbar-context-weekday {
        display: none;
    }

    .content {
        padding: 20px 20px 32px;
    }

    .auth-shell {
        grid-template-columns: 1fr;
        /* align-items:center statt des vererbten stretch - die Karte soll auf
           ihre eigene Inhaltsgroesse schrumpfen und sichtbar von dunklem
           Verlauf umgeben sein (Nutzerwunsch: schwarz/roter Verlauf soll auch
           auf Mobile rund um die Anmelde-Box sichtbar bleiben), statt die
           komplette verfuegbare Hoehe auszufuellen. */
        align-items: center;
        padding: 20px;
        max-width: 440px;
    }

    .auth-brand-panel {
        display: none;
    }

    .auth-card {
        border-radius: var(--radius-lg);
        /* Kompakter als die Desktop-Werte (48px 44px) - schafft zusammen mit
           align-items:center oben echten, sichtbaren Verlauf-Rand oben/unten,
           nicht nur an den Seiten. */
        padding: 32px 26px;
    }

    .auth-logo-mobile {
        display: block;
        max-width: 130px;
        margin: 0 auto 22px;
    }
}

/* ---------- E-Mail-Compose: Adressfelder mit Kontakt-Dropdown + Vorschau-Modal ---------- */

.email-address-row {
    display: flex;
    gap: 8px;
    align-items: center;
}

.email-address-row input {
    flex: 1;
}

.email-contact-picker {
    flex: 0 0 auto;
    width: auto;
    max-width: 180px;
    color: var(--color-muted);
}

.email-preview-overlay {
    position: fixed;
    inset: 0;
    background: rgba(15, 15, 18, 0.5);
    backdrop-filter: blur(5px);
    -webkit-backdrop-filter: blur(5px);
    z-index: 1000;
    align-items: center;
    justify-content: center;
    padding: 24px;
    animation: modal-overlay-in 0.16s ease-out;
}

/* Alle .email-preview-modal-Nutzungen (E-Mail-/Vorlagen-Vorschau, Beleg-
   Upload, Kontakt-Bearbeiten) haben einen FIXEN Header (Titel + Schliessen) -
   nur der Inhalt darunter (.email-preview-modal-body) scrollt. Ohne diese
   Trennung verschwinden Titel/Schliessen-Knopf beim Scrollen nach oben aus
   dem sichtbaren Bereich. Neue Modals sollen dieselbe Struktur verwenden:
   <div class="email-preview-modal"><div class="email-preview-modal-header">
   ...</div><div class="email-preview-modal-body">...</div></div>

   Modernisiert: eigener Rahmen (in Dunkelmodus sichtbarer als ein reiner
   Schatten) + --shadow-elevated (deutlich weicher/tiefer als der vorherige
   feste rgba-Schatten) + kurze Pop-in-Animation beim Oeffnen. Die Animation
   greift zuverlaessig bei jedem Anzeigen, da die Modals per
   style.display = 'none'/'flex' (nicht per Klassen-Toggle) ein-/ausgeblendet
   werden (siehe contact-edit-modal.js) - ein Element, das gerade erst wieder
   Teil des Renderbaums wird, spielt eine CSS-Animation immer neu ab. */
.email-preview-modal {
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);
    width: 100%;
    max-width: 680px;
    max-height: 85vh;
    box-shadow: var(--shadow-elevated);
    display: flex;
    flex-direction: column;
    overflow: hidden;
    animation: modal-pop-in 0.22s cubic-bezier(0.16, 1, 0.3, 1);
}

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

@keyframes modal-pop-in {
    from { opacity: 0; transform: translateY(10px) scale(0.97); }
    to { opacity: 1; transform: translateY(0) scale(1); }
}

@media (prefers-reduced-motion: reduce) {
    .email-preview-overlay,
    .email-preview-modal {
        animation: none;
    }
}

.email-preview-modal-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    padding: 20px 24px;
    background: var(--color-surface-alt);
    border-bottom: 1px solid var(--color-border);
    border-radius: var(--radius-lg) var(--radius-lg) 0 0;
    flex-shrink: 0;
}

.email-preview-modal-header h3 {
    margin: 0;
    font-size: 1.05rem;
    letter-spacing: -0.01em;
}

/* X-Icon-Knopf oben rechts in jedem Modal-Header (ersetzt den frueheren
   Text-Knopf "Schliessen") - immer als letztes Element im Header, siehe
   .email-preview-modal-header (justify-content:space-between). Kreisrund
   statt eckig, mit sanftem Hover-Uebergang - wirkt beim Klicken "griffiger"
   als die vorherige rein statische Flaeche. */
.modal-close-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    padding: 0;
    border: none;
    background: transparent;
    border-radius: 50%;
    color: var(--color-muted);
    cursor: pointer;
    flex-shrink: 0;
    transition: background 0.15s ease, color 0.15s ease, transform 0.1s ease;
}

/* Verwendete frueher die Namen "color-bg-hover" und "color-text" - beide
   existieren in dieser Palette nicht. Der Schliessen-Knopf bekam beim Hover
   daher gar keine Textfarbe (ungueltige Deklaration) und einen
   palettenfremden Ersatz-Grauton statt der Flaechenfarbe der App. */
.modal-close-btn:hover {
    background: var(--color-border);
    color: var(--color-ink);
}

.modal-close-btn:active {
    transform: scale(0.92);
}

.modal-close-btn svg {
    width: 18px;
    height: 18px;
}

.email-preview-modal-body {
    padding: 20px 24px 24px;
    overflow-y: auto;
    flex: 1 1 auto;
}

/* Schlankere, themefolgende Scrollbar innerhalb des Modal-Inhalts (Webkit/
   Blink) - die dicke, unstyled System-Scrollbar wirkte in einem sonst
   durchgestalteten Dialog wie ein Fremdkoerper. Firefox faellt auf seine
   eigene (bereits duenne) Standard-Scrollbar zurueck. */
.email-preview-modal-body::-webkit-scrollbar {
    width: 9px;
}

.email-preview-modal-body::-webkit-scrollbar-track {
    background: transparent;
}

.email-preview-modal-body::-webkit-scrollbar-thumb {
    background: var(--color-border-strong);
    border-radius: 999px;
}

.email-preview-modal-body::-webkit-scrollbar-thumb:hover {
    background: var(--color-muted);
}

/* Das Kontakt-Bearbeiten-Modal (siehe assets/js/contact-edit-modal.js) braucht
   mehr Breite als die uebrigen .email-preview-modal-Nutzungen - Formular +
   Firmen-Zuordnungstabelle nebeneinander statt gequetscht untereinander. */
#contact-edit-modal {
    max-width: 960px;
}

table.email-preview-meta {
    width: 100%;
    border-collapse: collapse;
    margin: 12px 0 16px;
}

table.email-preview-meta td {
    padding: 5px 0;
    vertical-align: top;
    font-size: 0.92rem;
}

table.email-preview-meta td:first-child {
    color: var(--color-muted);
    width: 90px;
    font-weight: 600;
}

/* Quill-Editor (Vorlagen-/E-Mail-Compose-Text) soll unabhaengig vom App-Theme
   immer wie ein Blatt Papier aussehen (weisser Hintergrund, dunkle Schrift) -
   das Vendor-Snow-Theme (assets/vendor/quill/quill.snow.css) geht von einem
   hellen Kontext aus (Toolbar-Icons/-Rahmen fest in Grautoenen, kein eigenes
   color auf .ql-editor) und wird im Dunkelmodus sonst unlesbar: der Editor-
   Inhalt erbte bisher die helle --color-ink-Textfarbe auf dem hart auf #fff
   gesetzten Hintergrund (heller Text auf hellem Grund), und die Toolbar-Icons
   blieben dunkel vor dem dunklen App-Hintergrund. */
.email-editor-wrap .ql-toolbar.ql-snow,
.email-editor-wrap .ql-container.ql-snow {
    background: #fff;
}

.email-editor-wrap .ql-editor {
    color: #1c1d21;
}

/* Geschuetzter Platzhalter-Chip im Quill-Editor (siehe email-placeholder-blot.js) -
   als Embed-Blot fuer Quill ein einziges atomares "Zeichen", optisch als
   kleine, nicht mit dem Fliesstext verwechselbare Pille dargestellt. Farben
   bewusst FEST (keine --color-*-Variablen) statt themefolgend, da der Chip
   ausschliesslich innerhalb der ebenfalls fest auf Weiss/Dunkeltext gesetzten
   Editor-/Vorschau-Flaeche (.email-editor-wrap/.email-preview-body) auftritt -
   Theme-Variablen wuerden dort im Dunkelmodus einen dunklen Fleck auf dem
   erzwungenen weissen Hintergrund ergeben (derselbe Fehler wie bei den
   Editor-Flaechen selbst, siehe .email-editor-wrap weiter oben). */
.ph-chip {
    display: inline-block;
    background: #eef0f4;
    border: 1px solid #ccced6;
    border-radius: 999px;
    padding: 1px 9px;
    margin: 0 1px;
    font-size: 0.85em;
    font-weight: 600;
    color: #c1272d;
    cursor: default;
    user-select: none;
}

.email-preview-body {
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    padding: 14px 16px;
    background: #fff;
    color: #1c1d21;
    max-height: 320px;
    overflow-y: auto;
    margin-bottom: 18px;
}

/* Gleicher Reset wie Quills .ql-editor p (margin: 0) - ohne diesen Reset
   addieren sich Browser-Default-Absatzabstand UND die Zeilenhöhe einer
   bewusst eingefügten Leerzeile, was wie zwei Leerzeilen statt einer aussieht.
   Muss zur Normalisierung in MimeMessageBuilder::normalizeHtmlSpacing()
   passen, damit die Vorschau exakt zeigt, was tatsächlich versendet wird. */
.email-preview-body p,
.email-preview-body ol,
.email-preview-body ul,
.email-preview-body pre,
.email-preview-body blockquote,
.email-preview-body h1,
.email-preview-body h2,
.email-preview-body h3,
.email-preview-body h4,
.email-preview-body h5,
.email-preview-body h6 {
    margin: 0;
}

.email-preview-actions {
    display: flex;
    justify-content: flex-end;
    gap: 10px;
}

/* ==========================================================================
   Farbtoene je Modul
   --------------------------------------------------------------------------
   EIN Satz Farbtoene fuer die ganze App. Vier davon sind exakt die bereits
   vorhandenen Statusfarben (Rot/Blau/Gruen/Bernstein) - nur Violett, Petrol
   und Schiefer kommen hinzu, in derselben Helligkeit und Saettigung gehalten,
   damit alles wie eine Familie wirkt. Rot bleibt die Markenfarbe und ist der
   Standard.

   Gesetzt wird der Ton EINMAL zentral auf <main class="content tone-*"> in
   templates/layout/header.php (abgeleitet aus dem aktuellen Pfad). Auf einer
   Seite ist deshalb immer nur ein einziger Ton sichtbar - es entsteht kein
   Regenbogen, sondern jeder Bereich hat eine eigene, ruhige Farbidentitaet.
   Bauteile lesen nur --tone/--tone-bg/--tone-border und brauchen deshalb
   selbst keine Farbvarianten.
   ========================================================================== */

.tone-brand  { --tone: #c1272d; --tone-bg: #fdecec; --tone-border: #f0c1c3; --tone-on-dark: #ef9296; }
.tone-blue   { --tone: #235a94; --tone-bg: #e8f1fb; --tone-border: #bdd9f2; --tone-on-dark: #8fbbe8; }
.tone-green  { --tone: #1e7a3d; --tone-bg: #e7f5eb; --tone-border: #bfe3c9; --tone-on-dark: #7fc99a; }
.tone-amber  { --tone: #8a6008; --tone-bg: #fdf1dc; --tone-border: #f2d79a; --tone-on-dark: #ddb264; }
.tone-violet { --tone: #57458f; --tone-bg: #eeeaf8; --tone-border: #cec5ea; --tone-on-dark: #a99add; }
.tone-teal   { --tone: #0f6a63; --tone-bg: #e2f2f1; --tone-border: #b4dcd8; --tone-on-dark: #6fc0b8; }
.tone-slate  { --tone: #494b53; --tone-bg: #edeef1; --tone-border: #d1d3d9; --tone-on-dark: #b0b2ba; }

/* ---------- Icon-Plakette: getoentes Quadrat hinter einem Linien-Symbol ----------
   Ersetzt an prominenten Stellen (Seitenkopf, Leerzustand, Karten) das nackte
   graue Strichsymbol. Wird direkt auf ein <svg> ODER auf einen Container mit
   einem <svg> darin angewendet. */

.icon-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    width: 34px;
    height: 34px;
    border-radius: 9px;
    background: var(--tone-bg);
    color: var(--tone);
}

.icon-badge > svg {
    width: 18px;
    height: 18px;
}

.icon-badge-lg {
    width: 44px;
    height: 44px;
    border-radius: 12px;
}

.icon-badge-lg > svg {
    width: 22px;
    height: 22px;
}

.icon-badge-sm {
    width: 27px;
    height: 27px;
    border-radius: 7px;
}

.icon-badge-sm > svg {
    width: 15px;
    height: 15px;
}

/* Auf dunklem Grund (Seitenleiste, Anmeldeseite) traegt die Plakette einen
   milchigen statt eines getoenten Hintergrunds - ein heller Pastellton
   wirkte dort wie ein Fremdkoerper. */
.icon-badge-on-dark {
    background: rgba(255, 255, 255, 0.09);
    color: var(--tone-on-dark);
}

/* ---------- Karte mit Ton-Oberkante ----------
   Bewusst NICHT auf .card allgemein: eine farbige Oberkante an jeder Karte
   waere in einer Liste aus acht Karten wieder eine Wand aus Farbe. Nur dort
   eingesetzt, wo eine Karte fuer sich steht (Dashboard). */
.card-toned {
    border-top: 3px solid var(--tone);
}

/* ---------- Leerzustaende ----------
   Listenseiten ohne Eintraege zeigten bisher nur einen grauen Satz. Jetzt eine
   handgezeichnete Strichzeichnung im gleichen Symbolvokabular wie alle Icons
   (viewBox, currentColor, stroke-width 2) plus Titel, Erklaerung und - wo es
   passt - die Aktion, die den Zustand aufloest. Siehe
   templates/partials/empty-state.php. */

.empty-state {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    padding: 30px 20px 26px;
}

.empty-state-art {
    width: 116px;
    height: 116px;
    margin-bottom: 14px;
    color: var(--tone);
}

/* Weiche getoente Fuellform hinter der Zeichnung (Kreis + Bodenschatten). */
.empty-state-art .es-fill {
    fill: var(--tone-bg);
    stroke: none;
}

/* Deckflaeche, damit sich kreuzende Linien sauber ueberdecken. */
.empty-state-art .es-bg {
    fill: var(--color-surface);
}

/* Nebensaechliche Bildteile treten zurueck, damit die Zeichnung eine
   Hauptform behaelt statt gleichfoermig zu wirken. */
.empty-state-art .es-soft {
    opacity: 0.4;
}

.empty-state-title {
    margin: 0;
    font-size: 1.02rem;
    font-weight: 600;
    color: var(--color-ink);
}

.empty-state-text {
    margin: 6px 0 0;
    max-width: 48ch;
    color: var(--color-muted);
    font-size: 0.9rem;
}

.empty-state-action {
    margin-top: 18px;
}

/* ---------- Dashboard: Entwarnungs-Tafel ----------
   Loest den frueheren einzeiligen gruenen Meldungsbalken ab: derselbe Satz,
   aber als eigenstaendige Tafel mit gezeichnetem Haken. */
.allclear {
    display: flex;
    align-items: center;
    gap: 18px;
    border-color: var(--color-success-border);
    background: linear-gradient(120deg, var(--color-success-bg) 0%, var(--color-surface) 60%);
}

.allclear-art {
    width: 54px;
    height: 54px;
    flex-shrink: 0;
    color: var(--color-success);
}

.allclear h2 {
    margin: 0 0 2px;
    font-size: 1.05rem;
}

.allclear p {
    margin: 0;
    color: var(--color-ink-soft);
    font-size: 0.92rem;
}

/* ==========================================================================
   Mikro-Bewegung
   --------------------------------------------------------------------------
   Bewusst zurueckhaltend: kurze Ein-Blend-Bewegung beim Seitenaufbau, sanftes
   Wachsen der Diagrammbalken, weiche Zustandswechsel. Keine Dauerschleifen,
   kein Federn, nichts, was in einer Buchhaltung stoert. Wer im Betriebssystem
   reduzierte Bewegung eingestellt hat, bekommt am Ende dieses Abschnitts
   alles wieder abgeschaltet.
   ========================================================================== */

@keyframes itsb-rise {
    from { opacity: 0; transform: translateY(8px); }
    to   { opacity: 1; transform: none; }
}

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

@keyframes itsb-drop {
    from { opacity: 0; transform: translateY(-6px); }
    to   { opacity: 1; transform: none; }
}

/* Nur ein Start-Bild: der Endwert ist der per style-Attribut gesetzte
   Balkenwert (impliziter to-Keyframe). Deshalb wachsen die Balken zu ihrer
   echten Hoehe, ohne dass die Vorlage etwas davon wissen muss - und ohne
   scaleY, das die abgerundete Balkenkuppe verzerren wuerde. */
@keyframes itsb-bar-grow {
    from { height: 0; }
}

/* Ein einmaliger, sehr weicher Ring - "hier ist etwas offen", nicht "Alarm".
   Laeuft zweimal und hoert dann auf. */
@keyframes itsb-attention {
    0%, 100% { box-shadow: 0 0 0 0 rgba(146, 101, 10, 0); }
    50%      { box-shadow: 0 0 0 5px rgba(146, 101, 10, 0.12); }
}

@keyframes itsb-draw {
    from { stroke-dashoffset: 60; }
    to   { stroke-dashoffset: 0; }
}

.content > .page-header {
    animation: itsb-fade 0.3s ease both;
}

.content > .card,
.content > .filter-bar,
.content > .alert,
.content > .settings-tabs,
.content > form > .card,
.dashboard-columns > * > .card,
.dashboard-columns > .card {
    animation: itsb-rise 0.34s cubic-bezier(0.22, 0.7, 0.3, 1) both;
}

/* Leichter Versatz, damit der Inhalt von oben nach unten aufbaut statt als
   ein Block zu erscheinen. Ab dem vierten Element gleicher Wert - sonst
   waere auf langen Seiten das letzte Element sekundenlang unsichtbar. */
.content > *:nth-child(2) { animation-delay: 0.05s; }
.content > *:nth-child(3) { animation-delay: 0.1s; }
.content > *:nth-child(n+4) { animation-delay: 0.14s; }

.attention-row > * {
    animation: itsb-rise 0.34s cubic-bezier(0.22, 0.7, 0.3, 1) both;
}

.attention-row > *:nth-child(1) { animation-delay: 0.04s; }
.attention-row > *:nth-child(2) { animation-delay: 0.09s; }
.attention-row > *:nth-child(3) { animation-delay: 0.14s; }
.attention-row > *:nth-child(n+4) { animation-delay: 0.19s; }

.attention-chip.is-warn {
    animation:
        itsb-rise 0.34s cubic-bezier(0.22, 0.7, 0.3, 1) both,
        itsb-attention 2.6s ease-in-out 0.6s 2;
}

.chart-bar {
    animation: itsb-bar-grow 0.62s cubic-bezier(0.2, 0.7, 0.3, 1) both;
    transition: opacity 0.15s ease;
}

.chart-bar-col:nth-child(1) .chart-bar { animation-delay: 0.08s; }
.chart-bar-col:nth-child(2) .chart-bar { animation-delay: 0.14s; }
.chart-bar-col:nth-child(3) .chart-bar { animation-delay: 0.2s; }
.chart-bar-col:nth-child(4) .chart-bar { animation-delay: 0.26s; }
.chart-bar-col:nth-child(5) .chart-bar { animation-delay: 0.32s; }
.chart-bar-col:nth-child(6) .chart-bar { animation-delay: 0.38s; }
.chart-bar-col:nth-child(n+7) .chart-bar { animation-delay: 0.44s; }

.chart-bar-col:hover .chart-bar {
    opacity: 1;
}

.chart-bar-value,
.chart-bar-label {
    transition: color 0.15s ease;
}

.chart-bar-col:hover .chart-bar-value {
    color: var(--color-ink);
}

.chart-stat {
    transition: color 0.15s ease;
}

.chart-stat:hover .chart-stat-value {
    color: var(--color-accent);
}

/* Aufklappen der Untermenues in der Seitenleiste und des Schnellzugriff-
   Menues: nur beim Oeffnen animiert - <details> entfernt seinen Inhalt beim
   Schliessen sofort aus dem Layout, eine Schliess-Animation waere ohne
   JavaScript nicht moeglich und den Aufwand hier nicht wert. */
.sidebar-nav-group[open] > .sidebar-subnav {
    animation: itsb-drop 0.2s ease both;
}

.quickcreate[open] .quickcreate-panel {
    animation: itsb-drop 0.16s ease both;
}

.order-card[open] > .table-scroll {
    animation: itsb-drop 0.18s ease both;
}

/* Der Haken auf der Entwarnungs-Tafel zeichnet sich einmal selbst. */
.allclear-art .allclear-check {
    stroke-dasharray: 60;
    animation: itsb-draw 0.6s cubic-bezier(0.65, 0, 0.35, 1) 0.25s both;
}

.stat-list a,
.doc-list-item,
.badge,
.pill-muted,
.settings-tab,
.quickcreate-panel a {
    transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}

.doc-list-item:hover {
    background: var(--color-surface-alt);
}

a {
    transition: color 0.13s ease;
}

.btn-primary:hover {
    box-shadow: 0 3px 10px rgba(193, 39, 45, 0.24);
}

.empty-state-art {
    animation: itsb-fade 0.5s ease 0.1s both;
}

@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        animation-duration: 0.001ms !important;
        animation-delay: 0ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.001ms !important;
        scroll-behavior: auto !important;
    }
}

/* ==========================================================================
   In-App-Tour (assets/js/tour-engine.js + tour-data.js)
   --------------------------------------------------------------------------
   Spotlight = ein winziges, positioniertes Element GENAU ueber dem echten
   Zielknoten mit box-shadow: 0 0 0 9999px ... - malt die Abdunkelung ueberall
   ausser im eigenen Rechteck. Wichtig: box-shadow nimmt NICHT am Hit-Testing
   teil, darum blockiert die Abdunkelung ausserhalb des Spotlights keine
   Klicks - die Tour ist ein Hinweis-Layer, kein modaler Zwang. Der Callout
   uebernimmt bewusst die Optik von .email-preview-modal (gleicher Radius/
   Schatten, .modal-close-btn), ist aber ein verankertes, kein zentriertes
   Fenster.
   ========================================================================== */

.tour-spotlight {
    position: fixed;
    z-index: 9998;
    pointer-events: none;
    box-shadow: 0 0 0 9999px rgba(20, 20, 24, 0.55);
    border: 2px solid var(--color-accent);
    border-radius: 8px;
    transition: top 0.15s ease, left 0.15s ease, width 0.15s ease, height 0.15s ease;
}

.tour-callout {
    position: fixed;
    z-index: 9999;
    width: 320px;
    max-width: calc(100vw - 32px);
    background: var(--color-surface);
    border-radius: var(--radius-lg);
    border-top: 4px solid var(--color-accent);
    box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
    padding: 18px 20px;
}

.tour-callout-fallback {
    text-align: center;
}

.tour-callout-fallback p {
    margin: 4px 0 0;
    font-size: 0.92rem;
}

.tour-callout-close {
    position: absolute;
    top: 10px;
    right: 10px;
}

.tour-callout-progress {
    font-size: 0.78rem;
    color: var(--color-muted);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    margin-bottom: 6px;
    padding-right: 28px;
}

.tour-callout h4 {
    margin: 0 0 8px;
    font-size: 1.05rem;
    padding-right: 20px;
}

.tour-callout p {
    margin: 0 0 14px;
    font-size: 0.92rem;
    color: var(--color-ink);
    line-height: 1.45;
}

.tour-callout-actions {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 8px;
}

.tour-callout-hint {
    font-size: 0.85rem;
    color: var(--color-muted);
    font-style: italic;
}

.tour-start-btn {
    margin-top: 10px;
}

/* ---------- Swiss Post Frankierung: Logo im Seitenkopf ---------- */

.swisspost-logo {
    width: 32px;
    height: 32px;
    border-radius: 6px;
    vertical-align: middle;
    margin-right: 10px;
}

/* ==========================================================================
   Hilfe-Center (templates/help/*)
   ========================================================================== */

.help-module-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
    gap: 20px;
    margin-top: 20px;
}

.help-module-card {
    display: block;
    background: var(--color-surface);
    border-radius: var(--radius);
    box-shadow: var(--shadow-card);
    padding: 22px 24px;
    border: 1px solid var(--color-border);
    border-top: 3px solid var(--tone);
    text-decoration: none;
    color: inherit;
    transition: transform 0.12s ease, box-shadow 0.12s ease, border-color 0.12s ease;
}

.help-module-card:hover {
    transform: translateY(-2px);
    box-shadow: 0 4px 8px rgba(20, 20, 25, 0.06), 0 8px 24px rgba(20, 20, 25, 0.09);
    border-color: var(--tone);
}

.help-module-card .icon-badge {
    margin-bottom: 12px;
}

.help-module-card h3 {
    margin: 0 0 4px;
    font-size: 1.05rem;
}

.help-module-card p {
    margin: 0;
    color: var(--color-muted);
    font-size: 0.88rem;
}

.help-module-card.is-hidden {
    display: none;
}

.help-search {
    margin: 18px 0 4px;
    max-width: 360px;
}

.help-figure {
    margin: 18px 0;
}

.help-figure img {
    max-width: 100%;
    border-radius: var(--radius-sm);
    border: 1px solid var(--color-border);
    display: block;
}

.help-figure figcaption {
    margin-top: 6px;
    font-size: 0.85rem;
    color: var(--color-muted);
}

.help-tour-card {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 14px 18px;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    margin-bottom: 10px;
}

.help-tour-card:last-child {
    margin-bottom: 0;
}
