/* ==========================================================================
   Easly - Stylesheet
   Grunddesign nach dem Easly-CI (Brand-Paket 1.0): Easly-Gruen als Akzent,
   Mint fuer Hervorhebungen auf dunklem Grund, Anthrazit fuer Text, helle,
   leicht gruenstichige Flaechen, Inter als Schrift, Radien 8/12/16.
   Der Akzent ist je Instanz einstellbar (Einstellungen > Branding,
   Itsb\Support\AccentPalette) - die dunklen Markenflaechen (Seitenleiste,
   Anmeldung) leiten sich davon ab (--brand-surface), damit ein eigener
   Akzent nicht neben einer gruenen Seitenleiste steht.
   ========================================================================== */

/* Inter (SIL Open Font License, assets/fonts/Inter-OFL.txt), variabel 100-900,
   auf Latein + Satzzeichen reduziert. */
@font-face {
    font-family: "Inter";
    font-style: normal;
    font-weight: 100 900;
    font-display: swap;
    src: url("../fonts/inter-var-latin.woff2") format("woff2");
}

:root {
    /* Markenfarben (Easly; je Instanz per AccentPalette ueberschrieben) */
    --color-accent: #0b4d41;
    --color-accent-rgb: 11, 77, 65;
    --color-accent-dark: #083a31;
    --color-accent-darker: #052a23;
    --color-accent-light: #e8f6f0;
    --color-accent-soft: #bfe6d6;
    --color-mint: #5ed6a6;

    --color-ink: #1f2937;
    --color-ink-2: #2c3644;
    --color-ink-soft: #4b5563;

    /* Dunkle Markenflaeche (Seitenleiste, Anmeldung): Easly-Tinte. Bei eigenem
       Akzent berechnet AccentPalette::toCssOverride() den Ton (34 % bzw. 18 %
       Akzent in fast Schwarz) - bewusst nicht per color-mix() (aeltere Browser). */
    --brand-surface: #06281f;
    --brand-surface-deep: #030f0d;

    /* Flaechen */
    --color-bg: #f4f6f5;
    --color-surface: #ffffff;
    --color-surface-alt: #f9faf8;
    --color-border: #e2e8e5;
    --color-border-strong: #cbd5d1;
    --color-muted: #6b7280;

    /* Status (Easly-Token "semantic") */
    --color-success: #087f5b;
    --color-success-bg: #e6f4ee;
    --color-success-border: #b7e2cf;
    --color-warning: #8a4b08;
    --color-warning-bg: #fdf3e2;
    --color-warning-border: #f1d3a4;
    --color-info: #175cd3;
    --color-info-bg: #eaf1fc;
    --color-info-border: #bcd3f5;
    --color-danger: #b42318;
    --color-danger-bg: #fcebe9;
    --color-danger-border: #f3c2bd;

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

    /* Radien & Schatten */
    --radius-sm: 8px;
    --radius: 12px;
    --radius-lg: 16px;
    --shadow-card: 0 1px 2px rgba(3, 41, 35, 0.04), 0 2px 10px rgba(3, 41, 35, 0.05);
    --shadow-elevated: 0 18px 44px rgba(3, 25, 21, 0.22);
    --shadow-menu: 0 10px 28px rgba(3, 25, 21, 0.14);
    --shadow-focus: 0 0 0 3px rgba(var(--color-accent-rgb), 0.2);

    /* Typografie */
    --font-sans: "Inter", "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: #5ed6a6;

    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: #2f9e7c;
    --color-accent-rgb: 47, 158, 124;
    --color-accent-dark: #4cc097;
    --color-accent-darker: #7fd8b5;
    --color-accent-light: #12302a;
    --color-accent-soft: #1d4a3f;

    --color-ink: #e7ecea;
    --color-ink-2: #cdd5d2;
    --color-ink-soft: #a2adaa;

    --color-bg: #0f1513;
    --color-surface: #171e1c;
    --color-surface-alt: #1e2724;
    --color-border: #2c3733;
    --color-border-strong: #3c4944;
    --color-muted: #8f9a97;

    --color-success: #4cc08f;
    --color-success-bg: #12301f;
    --color-success-border: #24563d;
    --color-warning: #e0a84a;
    --color-warning-bg: #3a2b10;
    --color-warning-border: #5c4620;
    --color-info: #6aa3ec;
    --color-info-bg: #142640;
    --color-info-border: #26466e;
    --color-danger: #f0776c;
    --color-danger-bg: #3a1a17;
    --color-danger-border: #5e2b26;

    --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(var(--color-accent-rgb), 0.32);
}

/* 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: var(--color-accent-darker); --tone-bg: var(--color-accent-light); --tone-border: var(--color-accent-soft); }
: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(var(--color-accent-rgb), 0.35), transparent 45%),
        radial-gradient(circle at 85% 80%, rgba(94, 214, 166, 0.12), transparent 50%),
        linear-gradient(160deg, var(--brand-surface-deep) 0%, var(--brand-surface) 60%, var(--brand-surface-deep) 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(--brand-surface) 0%, var(--brand-surface-deep) 100%);
    color: #f4f7f5;
    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(94, 214, 166, 0.28), 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-wordmark {
    display: block;
    width: 168px;
    height: auto;
    position: relative;
    margin-left: -6px;
}

.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: rgba(238, 243, 241, 0.55);
    font-size: 0.8rem;
    position: relative;
    margin-top: 24px;
}

.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;
    max-width: 150px;
    height: auto;
    margin: 0 auto 22px;
}

.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;
}

/* Eingerueckter Unterabschnitt eines Formulars (z.B. "Neues Produkt" im
   Wareneingang, templates/inventory/form.php). */
fieldset.form-fieldset {
    border: 1px solid var(--color-border, rgba(127, 127, 127, 0.3));
    border-radius: 8px;
    padding: 14px 16px 4px;
    margin: 0 0 18px;
    min-width: 0;
}

fieldset.form-fieldset[hidden] {
    display: none;
}

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

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;
}

/* var(--color-muted) statt eines fixen Hex-Werts (Fable-Audit Runde 8,
   MEDIUM): #9b9da3 war erkennbar fuer den DUNKLEN Hintergrund gewaehlt (dort
   ~6:1 Kontrast) und unveraendert auch im hellen Modus verwendet worden, wo
   derselbe Wert nur ~2.7:1 Kontrast liefert (deutlich unter WCAG AA) - jedes
   leere Text-/Textarea-Feld wirkte im hellen Modus auffaellig blass/schwer
   lesbar. --color-muted ist genau fuer diesen Zweck bereits pro Theme
   getrennt definiert (hell #6b6d74 / dunkel #93959d).*/
input::placeholder, textarea::placeholder {
    color: var(--color-muted);
}

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. Explizit dieselbe 38x38px-Groesse wie der
       Dark-Mode-Knopf (.theme-toggle-btn, von dem diese Klasse geerbt wird) -
       auf Nutzerwunsch, damit beide Topbar-Knoepfe optisch gleich gross sind. */
    button.mobile-search-trigger-btn {
        display: inline-flex;
    }
}

.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);
}

/* Auswahlkarten (z.B. Versandweg Microsoft 365 / SMTP) */
.radio-card {
    flex: 1 1 240px;
    display: block;
    padding: 12px 14px;
    border: 1px solid var(--color-border-strong);
    border-radius: var(--radius);
    background: var(--color-surface);
    font-weight: 400;
    cursor: pointer;
    margin-bottom: 12px;
}

.radio-card:has(input:checked) {
    border-color: var(--color-accent);
    box-shadow: var(--shadow-focus);
}

.radio-card input {
    width: auto;
    margin-right: 6px;
    accent-color: var(--color-accent);
}

.checkbox-inline {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    margin-top: 6px;
    font-weight: 400;
}

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

/* ---------- 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, var(--brand-surface) 0%, var(--brand-surface-deep) 100%);
    color: #eef3f1;
    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-wordmark {
    display: block;
    height: 44px;
    width: auto;
    margin: -4px 0 -4px -8px;
}

.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(var(--color-accent-rgb), 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(var(--color-accent-rgb), 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;
    /* min-height statt fixer height + zusaetzliches padding-top fuer
       env(safe-area-inset-top): auf Geraeten ohne Notch/Dynamic Island ist
       der Inset 0, also bleibt es exakt bei --topbar-height wie vorher. Als
       Home-Bildschirm-App (apple-mobile-web-app-status-bar-style:
       black-translucent, siehe header.php) erstreckt sich der Seiteninhalt
       unter die Statusleiste - ohne diesen Ausgleich sass die (position:
       sticky; top:0) Topbar samt Hamburger-Knopf dort und war unter der
       Notch/Statusleiste kaum/nicht antippbar. min-height statt height,
       damit der Inset die Box VERGROESSERT statt (bei box-sizing:border-box)
       den eigentlichen Inhalt zusammenzudruecken. */
    min-height: calc(var(--topbar-height) + env(safe-area-inset-top));
    padding-top: env(safe-area-inset-top);
    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;
    /* Explizit dieselbe 38x38px-Groesse wie .theme-toggle-btn/
       .mobile-search-trigger-btn (Nutzerwunsch: alle drei Topbar-Knoepfe auf
       Mobile sollen optisch gleich gross sein). */
    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;
    margin-right: 10px;
}

/* Ohne diese Regel hat das <svg> im Knopf (nur viewBox, kein width/height)
   keine explizite Groesse - der Browser faellt dann auf die generische
   Ersatzgroesse fuer nicht dimensionierte SVGs zurueck (300x150px), die weit
   ueber den 38x38px-Knopf hinausragt und dadurch praktisch unsichtbar/
   falsch abgeschnitten wirkt statt als Hamburger-Icon erkennbar zu sein.
   18px passend zu .theme-toggle-btn svg, das denselben 38px-Knopf nutzt. */
.sidebar-toggle-btn svg {
    width: 18px;
    height: 18px;
}

.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;
    /* Sicherheitsnetz falls trotz min-width:0 unten (z.B. bei einem
       aussergewoehnlich langen Betrag) die Zeile dennoch breiter waere als
       die Karte - Scrollbalken INNERHALB der Karte statt Ueberlauf der
       ganzen Seite nach rechts. */
    overflow-x: auto;
}

.chart-bar-col {
    /* min-width:0 statt des Flexbox-Default (auto) - sonst weigert sich eine
       flex:1-Spalte, unter die minimale Inhaltsbreite ihres NICHT umbrechenden
       .chart-bar-value-Labels zu schrumpfen, und alle 6 Spalten zusammen
       sprengen auf einem schmalen Telefon-Bildschirm die Kartenbreite (gleiche
       Ursache wie beim bereits behobenen .order-summary weiter unten). */
    flex: 1;
    min-width: 0;
    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 {
        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;
    }

    /* inline-block statt block/width:100% - kurze Spalten (z.B. "Kundennr."
       + "Typ", oder "Datum" + "Total CHF") stellen sich dadurch von selbst
       nebeneinander auf dieselbe Zeile, je nachdem, wie viel Platz ihr
       tatsaechlicher Inhalt braucht, statt dass JEDE Spalte zwingend eine
       eigene volle Zeile bekommt und die verfuegbare Breite ungenutzt lässt.
       Eine lange Spalte (z.B. "Firma / Kontakt", E-Mail-Adresse) nimmt dabei
       weiterhin automatisch so viel Platz ein, dass die naechste Spalte auf
       die naechste Zeile faellt - keine Tabellen-spezifische Sonderfall-Klasse
       pro Spalte noetig, das ergibt sich rein aus der tatsaechlichen
       Inhaltsbreite. max-width/overflow-wrap verhindert, dass ein einzelnes
       langes, nicht umbrechbares Wort (z.B. eine lange E-Mail-Adresse) die
       Karte trotzdem horizontal aufreisst.
       :not(:has(input,select,textarea)) klammert EDITIERBARE Zeilen aus
       (z.B. die Positionstabelle #line-items-table) - deren Felder erben ihre
       Breite global ueber "input,select,textarea { width:100% }" (siehe
       weiter oben in dieser Datei), was bei einer auf Inhaltsbreite
       schrumpfenden (width:auto) Zelle zu einem Kreisbezug fuehren wuerde
       (die Zelle richtet sich nach dem Feld, das Feld nach der Zelle) - das
       Feld wuerde auf eine winzige Breite kollabieren statt die Zeile
       auszufuellen. Solche Zellen bleiben ueber die zweite Regel darunter
       weiterhin volle Breite/eigene Zeile.
       KEIN :not([colspan]) hier (bewusst anders als eine frühere Fassung) -
       eine colspan-Zelle in TFOOT (z.B. eine Summen-Beschriftung wie
       reports/vat.php "Total Umsatzsteuer" NEBEN ihrer Betragszelle) soll
       sich weiterhin mit ihrer Geschwister-Zelle eine Zeile teilen koennen;
       nur fuer TBODY gibt es weiter unten eine spezifischere Regel, die
       genau dort (aufklappbare Detail-/Status-Zeilen ohne Geschwister-Zelle)
       stattdessen die volle Breite erzwingt. */
    table.responsive-stack td:not(.table-actions):not(:has(input, select, textarea)) {
        display: inline-block;
        width: auto;
        max-width: 100%;
        vertical-align: top;
        overflow-wrap: break-word;
        word-break: break-word;
        border-bottom: none;
        padding: 6px 0;
        margin: 0 18px 8px 0;
    }

    table.responsive-stack td:has(input, select, textarea) {
        display: block;
        width: 100%;
        border-bottom: none;
        padding: 6px 0;
        margin: 0 0 8px 0;
    }

    /* Eine colspan-Zelle in TBODY (aufklappbare Detail-/Status-Zeilen wie
       "Status verfolgen"-Tracking, Log-Details, Notiz-/Leerzustands-Zeilen)
       hat auf dem einspaltigen Mobile-Layout ohnehin keine Geschwister-Zelle,
       mit der sie sich eine Zeile teilen koennte - ohne diese Regel wuerde
       auch sie unter die obige inline-block-Regel fallen und bei kurzem
       Inhalt (z.B. "Status wird abgerufen ...") auf ein schmales,
       schrumpfendes Kaestchen zusammenfallen statt wie zuvor die volle
       Kartenbreite als eigene Zeile einzunehmen.
       Bewusst NUR tbody, NICHT tfoot: eine Summenzeile wie in reports/vat.php
       ("Total Umsatzsteuer" als td[colspan="2"] NEBEN der CHF-Betragszelle)
       WILL sich gerade mit ihrer Geschwister-Zelle eine Zeile teilen - dort
       wuerde diese Regel die beiden sonst faelschlich auf zwei unbeschriftete
       Zeilen auftrennen. :not(:empty) schliesst zudem rein dekorative
       Abstandshalter-Zellen (leeres td[colspan] nur zum Ausrichten der
       Spaltenanzahl, z.B. expenses/list.php-Fusszeile) aus - ohne sie wuerde
       eine solche leere Zelle als sichtbare, aber inhaltslose volle Zeile
       mit eigenem Padding/Abstand erscheinen. */
    table.responsive-stack tbody td[colspan]:not(.table-actions):not(:empty) {
        display: block;
        width: 100%;
        border-bottom: none;
        padding: 6px 0;
        margin: 0 0 8px 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 {
        /* Die Basis-Regel .table-actions (white-space:nowrap, fuer die
           Desktop-Tabellenzeile gedacht) wirkt sonst UNVERAENDERT auch hier
           weiter - zwei Knoepfe (z.B. "Bearbeiten" + "Aktivieren/
           Deaktivieren") wurden dadurch auf schmalen Bildschirmen auf einer
           Zeile erzwungen und rissen die gestapelte Karte horizontal auf.
           display:flex + flex-wrap laesst sie stattdessen bei Bedarf
           umbrechen, gap ersetzt das margin-right-Muster der Nowrap-Variante. */
        display: flex;
        width: 100%;
        flex-wrap: wrap;
        gap: 8px;
        white-space: normal;
        text-align: left;
        /* margin explizit (nicht nur margin-top) - sonst wuerde das
           rechte/untere margin der allgemeinen td-Regel (fuer das
           Nebeneinander-Stapeln kurzer Spalten) hier durchschlagen und
           die Trennlinie/den Aktionsblock faelschlich einruecken. */
        margin: 8px 0 0 0;
        padding-top: 12px;
        border-top: 1px solid var(--color-border);
    }

    table.responsive-stack td.table-actions > * {
        margin-right: 0;
    }

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

.branding-preview {
    display: flex;
    align-items: center;
    padding: 10px;
    margin-bottom: 8px;
    /* Das helle Schachbrettmuster ist die uebliche, geraeteunabhaengige
       Transparenz-Anzeige (wie in Bildbearbeitungsprogrammen) fuer ein
       hochgeladenes Logo/Favicon mit transparentem Hintergrund - bleibt
       ABSICHTLICH theme-unabhaengig hell, ein dunkles Schachbrett waere
       unueblich und schwerer als "hier ist Transparenz" erkennbar (Fable-Audit
       Runde 8, LOW - vorher ohne Begruendungskommentar). Der Rahmen darum ist
       dagegen nur der Karten-Rand und soll wie jede andere Karte dem Theme
       folgen, war zuvor aber ebenfalls fest auf den hellen Wert von
       --color-border gesetzt - im dunklen Modus wirkte die Vorschau dadurch
       wie ein unstyled/kaputtes Element statt einer themenkonformen Karte. */
    background: repeating-conic-gradient(#f0f0f2 0% 25%, #ffffff 0% 50%) 50% / 16px 16px;
    border: 1px solid var(--color-border);
    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);
}

/* Breite Bildschirme: Reiter umbrechen statt seitlich scrollen (mit Abo &
   Konto/Support-Zugang passen sie nicht mehr in eine Zeile); schmal bleibt es
   bei einer scrollbaren Zeile, der aktive Reiter wird ins Bild gerueckt (_tabs.php). */
@media (min-width: 1100px) {
    .settings-tabs {
        flex-wrap: wrap;
    }
}

/* Begriff/Wert-Liste (z.B. Einstellungen -> Abo & Konto). */
.kv-list {
    display: grid;
    grid-template-columns: minmax(140px, max-content) 1fr;
    gap: 10px 24px;
    margin: 0;
}

.kv-list dt {
    color: var(--color-muted);
    font-size: 0.9rem;
}

.kv-list dd {
    margin: 0;
}

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

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

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

    .card {
        padding: 20px;
    }

    /* Der negative Rand von .sticky-action-bar muss IMMER exakt dem
       aktuellen .card-Padding entsprechen, damit die Leiste bündig mit dem
       Kartenrand abschliesst statt darüber hinauszuragen - hier auf das
       gerade oben auf 20px reduzierte Padding angepasst. */
    .sticky-action-bar {
        margin: 16px -20px -20px;
        padding: 14px 20px;
    }
}

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

    /* .page-header (Titel/Icon-Plakette + "Neu..."-Aktionsknoepfe, auf JEDER
       Listen-/Detailseite im ganzen Projekt verwendet) hatte bisher UEBERHAUPT
       KEINE Mobile-Anpassung - display:flex ohne flex-wrap zwang Titel UND
       Aktionsknoepfe auf schmalen Bildschirmen immer in dieselbe Zeile, auch
       wenn mehrere Knoepfe vorhanden sind (z.B. bis zu 4 "Neue Offerte/AB/
       Lieferschein/Rechnung"-Knoepfe auf der Auftraege-Liste) - beide Bloecke
       teilten sich dadurch die Breite, statt jeweils die volle verfuegbare
       Breite fuer sich zu nutzen. width:100% auf .page-header-actions zwingt
       den Aktionsblock (dank des jetzt erlaubten Umbruchs) in eine eigene,
       volle Zeile UNTER dem Titel - seine eigene flex-wrap-Regel verteilt
       mehrere Knoepfe darin dann optimal ueber diese volle Breite. */
    .page-header {
        flex-wrap: wrap;
    }

    .page-header-actions {
        width: 100%;
    }

    /* Ohne max-width konnte ein <select> mit width:auto (Filterleisten-
       Dropdowns, z.B. "Kunde" auf der Auftraege-/Dokumente-Liste) durch eine
       lange ausgewaehlte Option (Kundenname+Ort) breiter werden als der
       verfuegbare Platz und die ganze Filterleiste/Seite horizontal aufreissen -
       das Feld darf zwar seiner Inhaltsbreite folgen (width:auto bleibt), aber
       nie ueber seinen Container hinauswachsen.
       Native <select>-Elemente kuerzen zu langen Anzeigetext dann selbststaendig
       mit Ellipsis statt zu ueberlaufen. */
    .filter-bar select {
        max-width: 100%;
    }

    /* 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 {
        /* NICHT die "padding"-Kurzform verwenden - die wuerde padding-top
           wieder auf 0 zuruecksetzen und den env(safe-area-inset-top)-Ausgleich
           von oben (siehe Basis-.topbar-Regel) auf genau der Bildschirmbreite
           zunichte machen, auf der das Hamburger-Menu ueberhaupt erst
           sichtbar wird (dieselbe @media-Schwelle). */
        padding-top: env(safe-area-inset-top);
        padding-right: 20px;
        padding-bottom: 0;
        padding-left: 20px;
    }

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

    /* Datum+"HEUTE"-Block auf dieselbe Hoehe wie die 38px-Topbar-Knoepfe
       (.theme-toggle-btn/.sidebar-toggle-btn/.mobile-search-trigger-btn)
       bringen - ohne diese Regel richtet sich seine Hoehe rein nach der
       Schriftgroesse von Datum+Label und faellt dadurch je nach Geraet/
       Schrift-Rendering etwas kleiner oder groesser als die Knoepfe aus,
       auch wenn beide ueber align-items:center auf .topbar vertikal
       zentriert werden - explizite Hoehe garantiert echte Gleichheit. */
    .topbar-context {
        height: 38px;
    }

    .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;
    }
}

/* Ersatz fuer die nativen Browser-Dialoge window.confirm()/alert() (siehe
   assets/js/confirm-modal.js) - haesslich, je nach Browser/Betriebssystem
   unterschiedlich gestaltet und in manchen eingebetteten Kontexten (z.B.
   manche PDF-/Webview-Umgebungen) unterdrueckt oder gar nicht verfuegbar.
   Nutzt bewusst .email-preview-overlay fuer den Hintergrund (identisches
   Verhalten/Aussehen, keine Duplikation), .itsb-confirm-dialog ist bewusst
   schmaler als .email-preview-modal - ein Bestaetigungstext braucht keine
   680px-Karte mit festem Header/scrollendem Body. */
.itsb-confirm-dialog {
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);
    width: 100%;
    max-width: 420px;
    box-shadow: var(--shadow-elevated);
    padding: 24px;
    animation: modal-pop-in 0.22s cubic-bezier(0.16, 1, 0.3, 1);
}

.itsb-confirm-message {
    margin: 0 0 20px 0;
    color: var(--color-ink);
    line-height: 1.5;
    white-space: pre-line;
}

.itsb-confirm-actions {
    display: flex;
    justify-content: flex-end;
    gap: 10px;
}

@media (prefers-reduced-motion: reduce) {
    .itsb-confirm-dialog {
        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: #1f2937;
}

/* 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). */
/* Kontextuelle Hilfe-Seitenleiste (templates/layout/footer.php, Logik in
   assets/js/help-panel.js) - bewusst ein rechtes Dock statt eines Modals:
   kein abdunkelnder Hintergrund, keine Fokus-Falle, die Seite dahinter
   bleibt waehrend geoeffneter Leiste bedienbar. z-index unter den Modals
   (1000, siehe .email-preview-overlay) UND unter den Touren (9998/9999),
   damit beide bei Bedarf ueber der Hilfe-Leiste erscheinen. */
.help-panel-toggle {
    position: fixed;
    /* env(safe-area-inset-right): auf dem Home Screen installiert (iOS
       "Zum Home-Bildschirm hinzufuegen", apple-mobile-web-app-capable) laeuft
       die Seite randlos ohne Safari-Chrome - im Querformat rueckt der Knopf
       sonst unter die abgerundete Geraeteecke bzw. (bei Geraeten mit
       seitlicher Aussparung) unter die Sensor-Notch. Auf Geraeten ohne
       Aussparung ist der Wert 0, also keine Verhaltensaenderung. */
    right: env(safe-area-inset-right);
    top: 50%;
    transform: translateY(-50%);
    z-index: 899;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    padding: 22px 5px;
    background: var(--color-accent);
    border: none;
    border-radius: var(--radius-sm) 0 0 var(--radius-sm);
    box-shadow: var(--shadow-elevated);
    color: #fff;
    cursor: pointer;
    transition: padding-right 0.15s ease, transform 0.15s ease;
}

.help-panel-toggle:hover {
    padding-right: 8px;
    transform: translateY(-50%) scale(1.04);
}

.help-panel-toggle svg {
    width: 16px;
    height: 16px;
    flex-shrink: 0;
    transform: rotate(90deg);
}

/* "Hilfe" als fertig vorgerendertes SVG (assets/img/help-label.svg) statt
   per CSS writing-mode:vertical-rl gedrehtem Live-Text - bei so kleiner
   Schriftgroesse machte die 90-Grad-Drehung "i"/"l"/"f" praktisch zu
   ununterscheidbaren Strichen (Feedback des Nutzers). Das SVG zeichnet das
   Wort dagegen normal orientiert und dreht erst den fertigen Textblock als
   Ganzes - jeder Buchstabe behaelt seine volle, unrotierte Form. */
.help-panel-toggle-label {
    width: 14px;
    height: 61px;
    display: block;
}

.help-panel {
    position: fixed;
    top: 0;
    /* siehe Kommentar bei .help-panel-toggle - selber Grund (randloses
       Standalone-Layout auf dem iOS-Home-Bildschirm). */
    right: env(safe-area-inset-right);
    height: 100dvh;
    width: min(480px, 100vw);
    background: var(--color-surface);
    border-left: 1px solid var(--color-border);
    box-shadow: var(--shadow-elevated);
    z-index: 900;
    display: flex;
    flex-direction: column;
    transform: translateX(100%);
    transition: transform 0.22s cubic-bezier(0.16, 1, 0.3, 1);
}

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

@media (prefers-reduced-motion: reduce) {
    .help-panel {
        transition: none;
    }
}

.help-panel-header {
    display: flex;
    align-items: center;
    gap: 10px;
    /* max(16px, env(safe-area-inset-top)): auf dem iOS-Home-Bildschirm
       (Standalone, black-translucent Status-Bar, siehe .sidebar-brand
       weiter oben fuer dasselbe Muster) reicht die Leiste bis ganz nach
       oben unter die Status-Bar - ohne den Ausgleich waeren Titel/
       Zuklapp-Knopf teils dahinter verdeckt. */
    padding: max(16px, env(safe-area-inset-top)) 16px 16px;
    border-bottom: 1px solid var(--color-border);
    flex-shrink: 0;
}

.help-panel-header h2 {
    flex: 1;
    margin: 0;
    font-size: 1.05rem;
}

.help-panel-body {
    flex: 1;
    overflow-y: auto;
    /* Unten zusaetzlich env(safe-area-inset-bottom): das Frageformular
       (.help-panel-chat-form) steht am Ende dieses scrollbaren Bereichs -
       auf dem iOS-Home-Bildschirm sonst teils unter dem Wischbalken/der
       Home-Indicator-Zone versteckt bzw. nur schwer erreichbar. */
    padding: 16px 16px max(16px, env(safe-area-inset-bottom));
}

/* Der nachgeladene Inhalt ist das komplette help/article.php-Template
   (Seitenkopf + Touren-Karte + Artikel-Karte, siehe help-panel.js) - der
   Seitenkopf (Titel/Icon/"Zur Uebersicht") ist hier redundant, da der
   Leisten-Header oben bereits Titel+Icon zeigt, und in den knapp 400px
   Breite zu viel Platz braucht. Karten verlieren Rahmen/Schatten, da die
   Leiste selbst schon der umschliessende Rahmen ist ("Karte in der Karte"
   wirkt sonst beengt). */
.help-panel-article .page-header {
    display: none;
}

.help-panel-article .card {
    border: none;
    box-shadow: none;
    padding: 0;
    margin-bottom: 16px;
}

.help-panel-article h1 {
    font-size: 1.05rem;
}

.help-panel-article h2 {
    font-size: 0.95rem;
}

/* Touren-Karten in der Leiste: bei knapper Breite zwingt ein langes Label
   (z.B. "Ausgabe erfassen (Beleg-Upload + KI)") den Knopf sonst zum Umbruch
   ("Tour\nstarten"), waehrend ein kurzes Label ihn einzeilig laesst - dadurch
   wurden die Knoepfe je nach Tour unterschiedlich gross. Hier stattdessen
   Label und Knopf untereinander, Knopf ueber die volle Breite - so bleibt
   die Groesse immer gleich, unabhaengig von der Label-Laenge. */
.help-panel-article .help-tour-card {
    flex-direction: column;
    align-items: stretch;
    gap: 8px;
    padding: 12px 14px;
}

.help-panel-article .help-tour-card span {
    font-size: 0.85rem;
}

.help-panel-article .help-tour-card .tour-start-btn {
    align-self: stretch;
    justify-content: center;
    margin-top: 0;
    font-size: 0.8rem;
    padding: 6px 10px;
}

.help-panel-chat {
    margin-top: 20px;
    padding-top: 16px;
    border-top: 1px solid var(--color-border);
}

.help-panel-chat-thread {
    display: flex;
    flex-direction: column;
    gap: 12px;
    margin-bottom: 10px;
}

.help-panel-chat-entry {
    background: var(--color-surface-alt);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    padding: 10px 12px;
}

.help-panel-chat-question {
    margin: 0 0 6px;
    font-weight: 600;
    font-size: 0.88rem;
}

.help-panel-chat-answer {
    margin: 0;
    font-size: 0.88rem;
    white-space: pre-wrap;
}

.help-panel-chat-form {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.help-panel-chat-form textarea {
    resize: vertical;
    min-height: 44px;
    font-family: inherit;
    font-size: 0.9rem;
    padding: 8px 10px;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    background: var(--color-surface);
    color: var(--color-ink);
}

.help-panel-chat-form button {
    align-self: flex-end;
}

@media (max-width: 480px) {
    .help-panel {
        width: calc(100vw - env(safe-area-inset-right));
        border-left: none;
    }
}

.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: var(--color-accent);
    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: #1f2937;
    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;
    flex-wrap: wrap;
    justify-content: flex-end;
    row-gap: 8px;
    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: var(--color-accent); --tone-bg: var(--color-accent-light); --tone-border: var(--color-accent-soft); --tone-on-dark: #5ed6a6; }
.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(var(--color-accent-rgb), 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;
}

/* Struktur fuer Hilfe-Artikel-Inhalt: statt einer flachen Aufzaehlung
   (frueher <ul class="serial-list"> mit fett gesetztem Lead-in pro Punkt,
   optisch kaum von den Nachbarpunkten getrennt) ein eigener Titel je Thema
   + Trennlinie dazwischen - liest sich sowohl auf der vollen /help/{modul}-
   Seite als auch in der schmalen Hilfe-Seitenleiste klarer gegliedert. */
.help-topics {
    display: flex;
    flex-direction: column;
    gap: 16px;
}

.help-topic {
    padding-bottom: 16px;
    border-bottom: 1px solid var(--color-border);
}

.help-topic:last-child {
    padding-bottom: 0;
    border-bottom: none;
}

.help-topic h3 {
    margin: 0 0 6px;
    font-size: 0.95rem;
}

.help-topic p {
    margin: 0;
    font-size: 0.88rem;
    color: var(--color-ink);
    line-height: 1.5;
}

.help-panel-article .help-topic h3 {
    font-size: 0.88rem;
}

.help-panel-article .help-topic p {
    font-size: 0.83rem;
}

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

.help-figure img {
    max-width: 100%;
    border-radius: var(--radius-sm);
    border: 1px solid var(--color-border);
    display: block;
    cursor: zoom-in;
    transition: opacity 0.12s ease;
}

.help-figure img:hover {
    opacity: 0.88;
}

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

/* Vergroesserte Ansicht per Klick auf einen Hilfe-Screenshot, siehe
   assets/js/image-lightbox.js. Nutzt .email-preview-overlay fuer den
   identischen Hintergrund/Blur wie alle anderen Modals im Projekt. */
.image-lightbox-overlay {
    padding: 40px;
}

.image-lightbox-img {
    max-width: 100%;
    max-height: 100%;
    border-radius: var(--radius-sm);
    box-shadow: var(--shadow-elevated);
    animation: modal-pop-in 0.22s cubic-bezier(0.16, 1, 0.3, 1);
}

@media (prefers-reduced-motion: reduce) {
    .image-lightbox-img {
        animation: none;
    }
}

.image-lightbox-close {
    position: fixed;
    top: 20px;
    right: 24px;
    width: 40px;
    height: 40px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: 50%;
    color: var(--color-ink);
    cursor: pointer;
    box-shadow: var(--shadow-elevated);
}

.image-lightbox-close svg {
    width: 18px;
    height: 18px;
}

.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;
}
