/* ==========================================================================
   FinanciaLISM – Admin UI
   Referenziert ausschließlich Tokens aus tokens.css. Keine Farbwerte,
   Radien oder Fonts hier hart verdrahten. Architektur/Großteil der
   Komponenten 1:1 aus SimpLISM CMS übernommen (siehe
   /mnt/Projects/Web/simplism_cms/css/admin.css), blog-/galerie-spezifische
   Abschnitte (Login-Screen, Vollbild-Editor, Bild-Picker, Plan-Vergleich)
   entfernt, dafür Tabellen/Filter/Timer-Widget für die Buchhaltung ergänzt.
   ========================================================================== */

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

html {
  color-scheme: light dark;
}

body {
  margin: 0;
  font-family: var(--font-sans);
  font-size: var(--text-base);
  color: var(--text);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
  transition: background-color var(--duration) var(--ease), color var(--duration) var(--ease);
}

h1, h2, h3, h4 {
  margin: 0;
  font-weight: 650;
  letter-spacing: -0.01em;
  line-height: 1.2;
}

p { margin: 0; }

button, input, select, textarea {
  font: inherit;
  color: inherit;
}

a { color: var(--accent); }

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

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

.hidden { display: none !important; }
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0;
}

/* ==========================================================================
   Form Elements
   ========================================================================== */

.field {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  margin-bottom: var(--space-4);
}

.field label {
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--text);
}

.field .field-hint {
  font-size: var(--text-xs);
  color: var(--text-faint);
}

.field .field-error {
  font-size: var(--text-xs);
  color: var(--danger);
  display: none;
}

.field.has-error .field-error { display: block; }
.field.has-error input,
.field.has-error select,
.field.has-error textarea { border-color: var(--danger); }

.field-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: var(--space-3);
}

input[type="text"],
input[type="email"],
input[type="password"],
input[type="number"],
input[type="date"],
input[type="time"],
input[type="url"],
input[type="color"],
select,
textarea {
  width: 100%;
  padding: 10px 12px;
  background: var(--surface-sunken);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  color: var(--text);
  transition: border-color var(--duration-fast) var(--ease), box-shadow var(--duration-fast) var(--ease);
}

textarea { resize: vertical; min-height: 90px; line-height: 1.5; }

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

input::placeholder, textarea::placeholder { color: var(--text-faint); }
input:disabled, select:disabled, textarea:disabled { opacity: 0.6; cursor: not-allowed; }

.checkbox-row {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}
.checkbox-row input[type="checkbox"] {
  width: 18px; height: 18px; accent-color: var(--accent); cursor: pointer;
}

/* ==========================================================================
   Buttons
   ========================================================================== */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  height: 38px;
  padding: 0 var(--space-4);
  border-radius: var(--radius);
  border: 1px solid transparent;
  font-weight: 600;
  font-size: var(--text-sm);
  white-space: nowrap;
  cursor: pointer;
  transition: transform var(--duration-fast) var(--ease),
    background-color var(--duration-fast) var(--ease),
    border-color var(--duration-fast) var(--ease),
    box-shadow var(--duration-fast) var(--ease);
}
.btn:active { transform: scale(0.98); }
.btn:disabled { opacity: 0.5; cursor: not-allowed; pointer-events: none; }

.btn-primary {
  background: var(--accent);
  color: var(--accent-ink);
}
.btn-primary:hover { background: var(--accent-hover); }

.btn-secondary {
  background: var(--surface);
  border-color: var(--border-strong);
  color: var(--text);
}
.btn-secondary:hover { background: var(--surface-sunken); }

.btn-ghost {
  background: transparent;
  color: var(--text-muted);
}
.btn-ghost:hover { background: var(--surface-sunken); color: var(--text); }

.btn-danger {
  background: transparent;
  color: var(--danger);
  border-color: transparent;
}
.btn-danger:hover { background: var(--danger-soft); }

.btn-danger-solid {
  background: var(--danger-solid);
  color: var(--danger-solid-ink);
}
.btn-danger-solid:hover { filter: brightness(1.08); }

.btn-danger-outline {
  background: transparent;
  color: var(--danger);
  border-color: var(--danger);
}
.btn-danger-outline:hover { background: var(--danger-soft); }

.btn-icon { width: 38px; padding: 0; flex-shrink: 0; }
.btn-block { width: 100%; }
.btn-sm { height: 32px; padding: 0 var(--space-3); font-size: var(--text-xs); }

/* ==========================================================================
   App Shell
   ========================================================================== */

.app-shell {
  display: grid;
  grid-template-columns: var(--sidebar-w) 1fr;
  grid-template-rows: 100dvh;
}

.sidebar {
  background: var(--surface);
  border-right: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  padding: var(--space-4) var(--space-3);
}

.sidebar-brand {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2);
  margin-bottom: var(--space-5);
}
.sidebar-brand .brand-mark {
  width: 30px; height: 30px;
  border-radius: var(--radius-sm);
  background: var(--accent);
  color: var(--accent-ink);
  display: grid; place-items: center;
  font-weight: 700;
  font-size: var(--text-sm);
  flex-shrink: 0;
}
.sidebar-brand .brand-name {
  font-weight: 650;
  font-size: var(--text-base);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.sidebar-brand .brand-tagline {
  font-size: 11px;
  color: var(--text-faint);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.sidebar-brand-logo {
  flex-direction: column;
  align-items: center;
  gap: var(--space-1);
}
.brand-logo {
  max-width: 140px;
  max-height: 48px;
  width: auto;
  height: auto;
  object-fit: contain;
}
[data-theme="dark"] .brand-logo { filter: invert(1); }
.brand-name-under-logo {
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--text-faint);
}

.nav-group { margin-bottom: var(--space-5); }

.nav-item {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  width: 100%;
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius);
  color: var(--text-muted);
  background: transparent;
  border: none;
  cursor: pointer;
  font-size: var(--text-sm);
  font-weight: 550;
  text-align: left;
  margin-bottom: 2px;
  transition: background-color var(--duration-fast) var(--ease), color var(--duration-fast) var(--ease);
}
.nav-item:hover { background: var(--surface-sunken); color: var(--text); }
.nav-item.active { background: var(--accent-soft); color: var(--accent); }
.nav-item .icon { width: 18px; height: 18px; flex-shrink: 0; }

.sidebar-footer {
  margin-top: auto;
  padding-top: var(--space-4);
  border-top: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.session-chip {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  width: 100%;
  padding: var(--space-2);
  border: none;
  border-radius: var(--radius);
  background: transparent;
  font: inherit;
  font-size: var(--text-xs);
  color: var(--text-muted);
  text-align: left;
  cursor: pointer;
  transition: background-color var(--duration-fast) var(--ease), color var(--duration-fast) var(--ease);
}
.session-chip:hover { background: var(--surface-sunken); color: var(--text); }
.session-chip.active { background: var(--accent-soft); color: var(--accent); }
.session-chip.active .session-chip-name { color: var(--accent); }
.session-chip .avatar {
  width: 26px; height: 26px;
  border-radius: 50%;
  background: var(--surface-sunken);
  border: 1px solid var(--border);
  display: grid; place-items: center;
  font-weight: 650;
  font-size: 11px;
  flex-shrink: 0;
  color: var(--text);
}
.session-chip-info {
  display: flex;
  flex-direction: column;
  min-width: 0;
  flex: 1;
}
.session-chip-name {
  font-weight: 600;
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.session-chip-role {
  font-size: 11px;
  color: var(--text-faint);
}
.session-chip .icon.session-chip-chevron {
  width: 16px; height: 16px;
  flex-shrink: 0;
  color: var(--text-faint);
}

/* ---- Main area --------------------------------------------------------- */

.main {
  display: flex;
  flex-direction: column;
  min-width: 0;
  height: 100dvh;
  overflow: hidden;
}

.topbar {
  height: var(--topbar-h);
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 var(--space-5);
  border-bottom: 1px solid var(--border);
  background: var(--surface);
}

.topbar-title { font-size: var(--text-lg); font-weight: 650; }
.topbar-actions { display: flex; align-items: center; gap: var(--space-2); }

.theme-toggle {
  width: 38px; height: 38px;
  border-radius: var(--radius);
  border: 1px solid var(--border-strong);
  background: var(--surface);
  display: grid; place-items: center;
  cursor: pointer;
  color: var(--text-muted);
  transition: background-color var(--duration-fast) var(--ease);
}
.theme-toggle:hover { background: var(--surface-sunken); color: var(--text); }
.theme-toggle svg { width: 18px; height: 18px; }

.view {
  flex: 1;
  overflow-y: auto;
  padding: var(--space-6);
}

.view-inner {
  max-width: var(--content-max);
  margin: 0 auto;
}

.view-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-4);
  margin-bottom: var(--space-5);
  flex-wrap: wrap;
}

.view-header h2 { font-size: var(--text-2xl); }
.view-header .view-sub {
  color: var(--text-muted);
  font-size: var(--text-sm);
  margin-top: var(--space-1);
}
.view-header-actions { display: flex; gap: var(--space-2); flex-wrap: wrap; }

/* ==========================================================================
   Dashboard Stat Tiles
   ========================================================================== */

.stat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: var(--space-4);
  margin-bottom: var(--space-6);
}

.stat-tile {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: var(--space-4);
}
.stat-tile .stat-label {
  font-size: var(--text-xs);
  color: var(--text-muted);
  font-weight: 600;
  margin-bottom: var(--space-2);
}
.stat-tile .stat-value {
  font-size: var(--text-2xl);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.stat-tile .stat-value.tone-danger { color: var(--danger); }
.stat-tile .stat-value.tone-success { color: var(--success); }
.stat-tile .stat-meta {
  margin-top: var(--space-1);
  font-size: var(--text-xs);
  color: var(--text-faint);
}

.dashboard-layout {
  display: grid;
  grid-template-columns: 1fr 320px;
  align-items: start;
  gap: var(--space-5);
}
.dashboard-main { min-width: 0; }
.dashboard-side { min-width: 0; }

/* Zwei-Spalten-Kopf der Rechnungsformular-Vollseite (Empfänger / Rechnungs-
   informationen nebeneinander, sevdesk-Anordnung) - siehe js/modules/
   invoices-out.js renderFormPage(). */
.panel-grid-2 {
  display: grid;
  grid-template-columns: 1.3fr 1fr;
  align-items: start;
  gap: var(--space-5);
}

/* ---- Zahlen-Eingabefelder ohne Spinner-Pfeile (Positionstabelle +
   Gesamtrabatt) - Nutzer-Feedback: die Auf/Ab-Buttons in den Zahlenfeldern
   stören dort mehr als sie nützen. */
.no-spinner::-webkit-outer-spin-button,
.no-spinner::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}
.no-spinner {
  -moz-appearance: textfield;
  appearance: textfield;
}

/* ---- Angehängtes Dropdown/Suffix direkt am Textfeld (sevdesk-Vorbild) ---
   Menge+Einheit, Rabatt-Wert+Einheit, Einzelpreis+€ - Input und
   Select/Suffix bilden optisch EIN Steuerelement statt zwei getrennter
   Felder nebeneinander (siehe js/modules/invoices-out.js renderItems()).
   WICHTIG: Rahmen/Radius/Fokus-Ring sitzen NUR am äußeren .input-combo -
   Textfeld/Select/Suffix selbst sind rahmenlos. Vorher hatte jedes
   Teilelement seinen eigenen Rahmen (nur mit border-right:none dazwischen
   "verklebt"), wodurch der native input:focus-visible-Rahmen NUR um das
   Textfeld blau wurde, während der äußere Glow-Ring um die ganze Combo lag
   - zwei sichtbar unterschiedliche Ringe statt einem. Mit dem Rahmen
   ausschließlich am Wrapper gibt es nur noch einen einzigen, exakt
   passenden Ring. */
.input-combo {
  display: flex;
  align-items: stretch;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface-sunken);
  overflow: hidden;
  transition: border-color var(--duration-fast) var(--ease), box-shadow var(--duration-fast) var(--ease);
}
.input-combo input,
.input-combo select {
  border: none;
  border-radius: 0;
  background: transparent;
  min-width: 0;
}
.input-combo input {
  flex: 1 1 auto;
}
.input-combo select {
  flex: 0 0 auto;
  width: auto;
  padding: 10px 8px;
  border-left: 1px solid var(--border);
}
.input-combo input:focus-visible,
.input-combo select:focus-visible {
  box-shadow: none;
  outline: none;
}
.input-combo:focus-within {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-ring);
}

.input-combo-suffix-text {
  display: flex;
  align-items: center;
  padding: 0 10px;
  color: var(--text-muted);
}
/* Einzelpreis: Suffix erscheint erst, sobald ein Betrag eingetragen wurde
   (Nutzer-Wunsch) - siehe refreshPriceSuffix() in invoices-out.js. */
.input-combo-suffix .input-combo-suffix-text {
  opacity: 0;
  transition: opacity var(--duration-fast) var(--ease);
}
.input-combo-suffix.has-value .input-combo-suffix-text { opacity: 1; }
/* Gesamtrabatt-Wert: Suffix (%/€) steht IMMER fest am Feldende, ändert nur
   ihren Text je nach Dropdown-Auswahl (siehe refreshDiscountValueSuffix()) -
   kein Ein-/Ausblenden wie beim Einzelpreis. */
.input-combo-suffix-fixed .input-combo-suffix-text { opacity: 1; }

/* Positionstabelle: Zahlenfelder nur so breit wie ihre realistische
   Ziffernanzahl (Nutzer-Feedback) statt der vollen Zellenbreite - Menge
   bis 5-, Einzelpreis bis 7-, Rabattwert bis 3-stellig. */
.table-editor .qty-input { flex: 0 0 auto; width: calc(5ch + 20px); }
.table-editor .price-input { flex: 0 0 auto; width: calc(7ch + 20px); }
.table-editor .discount-value-input { flex: 0 0 auto; width: calc(3ch + 20px); }

/* Positions-Tabelle (Produkte): Beschreibung nimmt den kompletten
   übrigen Platz, alle anderen Spalten schrumpfen auf ihren tatsächlichen
   Inhalt (Standard-CSS-Trick: width:1% + white-space:nowrap auf den
   schmalen Spalten zwingt den Browser, ihnen nur so viel Platz wie nötig
   zuzuteilen) - ohne das würde die Auto-Tabellenlayout-Berechnung allen
   Spalten unnötig viel Breite geben. */
.items-table th:not(:first-child),
.items-table td:not(:first-child) {
  width: 1%;
  white-space: nowrap;
}

/* Rabatt-Typ-Auswahl (Item-Zeile UND Gesamtrechnung): immer so breit wie
   die längste Option ("Kein Rabatt"), damit sich die Breite beim
   Umschalten nicht ändert. */
.discount-type-select { width: 140px; }

/* ---- Rich-Text-Editor (Freitext vor/nach der Positionstabelle) ---------
   Minimal gehaltene Toolbar (Fett/Kursiv/Unterstrichen) über einer
   contenteditable-Fläche - siehe js/rich-text.js. */
.rte {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--surface-sunken);
}
.rte-toolbar {
  display: flex;
  gap: 2px;
  padding: 6px;
  border-bottom: 1px solid var(--border);
  background: var(--surface);
}
.rte-btn {
  min-width: 30px;
  padding: 4px 8px;
  font-weight: 700;
}
.rte-btn-bold { font-weight: 800; }
.rte-btn-italic { font-style: italic; }
.rte-btn-underline { text-decoration: underline; }
/* Erkennbar hervorgehoben, solange die Formatierung an der aktuellen
   Cursor-Position/Selektion aktiv ist (siehe js/rich-text.js
   refreshToolbarState()). */
.rte-btn.active {
  background: var(--accent-soft);
  color: var(--accent);
  box-shadow: inset 0 0 0 1px var(--accent);
}
/* Trennstrich zwischen Fett/Kursiv/Unterstrichen und den
   Ausrichtungs-Buttons (nur im Block-Modus, siehe showAlign in
   js/rich-text.js - z.B. Vertragsvorlagen). */
.rte-toolbar-sep {
  width: 1px;
  align-self: stretch;
  margin: 2px 4px;
  background: var(--border);
}
/* Schriftgröße-Kombifeld in der Vertragsvorlagen-Toolbar (nur showFontSize,
   siehe js/rich-text.js) - Zahlenfeld + Pfeil-Button, öffnet eine eigene
   gestylte Liste (Portal, wie das "+ Variable"-Menü) statt eines nativen
   <select>/<datalist> (dessen Dropdown wird je nach Browser/OS gar nicht
   oder inkonsistent angezeigt). Bewusst schmal (nur die Zahl, keine
   "px"-Einheit sichtbar). */
.rte-fontsize-combo {
  display: inline-flex;
  align-items: stretch;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
}
.rte-fontsize-combo:hover { background: var(--surface-sunken); }
/* :focus-within statt :focus-visible auf dem Input allein - der Ring soll
   um das GESAMTE Kombifeld laufen (Zahl + Pfeil-Button), nicht nur um den
   Text-Teil (Nutzer-Feedback). Das Input selbst unterdrückt seinen eigenen
   Default-Outline (siehe unten), damit der hier gesetzte Ring nicht doppelt
   erscheint. */
.rte-fontsize-combo:focus-within {
  box-shadow: 0 0 0 2px var(--accent-ring);
}
/* Höhere Spezifität als die globale "input[type=text] { width:100% }"-Regel
   oben in dieser Datei nötig (Attribut-Selektor + Element = spezifischer
   als eine einzelne Klasse) - sonst gewinnt dort die 100%-Breite und das
   Feld reißt die ganze Toolbar-Zeile breit (Nutzer-Feedback). */
.rte-fontsize-combo input.rte-fontsize-input {
  width: 28px;
  min-width: 0;
  font-size: var(--text-xs);
  padding: 4px 0 4px 6px;
  border: none;
  background: transparent;
  color: var(--text);
  text-align: right;
}
/* Überschreibt explizit auch box-shadow/border-color (nicht nur outline) -
   die globale "input:focus-visible"-Regel weiter oben in dieser Datei setzt
   sonst zusätzlich ihren eigenen (kleineren) Ring direkt am Input, was
   zusammen mit dem Ring am ganzen Kombifeld oben zu einem sichtbaren
   doppelten Ring führt (Nutzer-Feedback). */
.rte-fontsize-input:focus-visible {
  outline: none;
  box-shadow: none;
  border-color: transparent;
}
.rte-fontsize-caret {
  display: flex;
  align-items: center;
  padding: 0 4px;
  border: none;
  background: transparent;
  color: var(--text-muted);
  cursor: pointer;
}
/* Kein eigener Browser-Default-Ring auf dem Pfeil-Button - der Ring ums
   ganze Kombifeld (siehe .rte-fontsize-combo:focus-within oben) reicht. */
.rte-fontsize-caret:focus-visible { outline: none; }
.rte-fontsize-list {
  position: fixed;
  z-index: 1000;
  width: 64px;
  max-height: 260px;
  overflow-y: auto;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-lg, 0 8px 24px rgba(0, 0, 0, 0.18));
  padding: 4px;
}
.rte-fontsize-list.hidden { display: none; }
.rte-fontsize-item {
  display: block;
  width: 100%;
  text-align: center;
  padding: 5px 6px;
  border: none;
  background: none;
  border-radius: var(--radius-sm);
  cursor: pointer;
  font-size: var(--text-sm);
  color: var(--text);
}
.rte-fontsize-item:hover, .rte-fontsize-item:focus-visible { background: var(--surface-sunken); }
.rte-fontsize-item.active {
  background: var(--accent-soft);
  color: var(--accent);
  font-weight: 700;
}
/* "Format übertragen"-Button bleibt hervorgehoben, solange er "scharf"
   ist (Format gemerkt, wartet auf die nächste Selektion im Text). */
.rte-btn-paint.active {
  background: var(--accent-soft);
  color: var(--accent);
  box-shadow: inset 0 0 0 1px var(--accent);
}
.rte-editable {
  min-height: 90px;
  padding: 10px 12px;
  line-height: 1.5;
  outline: none;
}
.rte-editable:empty::before {
  content: attr(data-placeholder);
  color: var(--text-faint);
}
/* Vertragsvorlagen (Block-Modus, siehe js/modules/contract-templates.js)
   sind ganze Dokumente statt kurzer Freitexte - deutlich mehr Platz als der
   90px-Standard oben. */
.rte-editable-block {
  min-height: 420px;
}
.rte-editable:focus-visible {
  outline: none;
  box-shadow: inset 0 0 0 3px var(--accent-ring);
}

/* ---- Variablen-Einfügen-Menü (Betreff/Freitexte Ausgangsrechnung,
   siehe js/invoice-variables.js) - kleiner Button + Popover-Liste, keine
   native <select>, damit das Zielfeld beim Öffnen nicht den Fokus/die
   Cursorposition verliert. Der Button steht IMMER unter dem zugehörigen
   Textfeld (nicht daneben) - bei Rich-Text-Editoren sitzt er direkt in der
   Toolbar (siehe js/rich-text.js appendToolbarItem), beim Betreff-Feld als
   eigenes Element direkt nach dem <input>. */
.var-menu-wrap { display: inline-flex; margin-top: 6px; }
.rte-toolbar .var-menu-wrap { margin-top: 0; }
.var-menu-btn { font-size: var(--text-xs); }
/* position:fixed + JS-Positionierung (nicht absolute relativ zu
   .var-menu-wrap) UND als eigenständiges <body>-Kind gerendert (siehe
   buildInsertMenu in js/invoice-variables.js): ein Rich-Text-Editor (.rte)
   hat `overflow:hidden` für die abgerundeten Ecken - ein Kind-Popover würde
   darin unabhängig vom z-index immer abgeschnitten. Als Portal direkt in
   <body> umgeht das zuverlässig, statt nur den z-index zu erhöhen. */
.var-menu {
  position: fixed;
  z-index: 1000;
  min-width: 220px;
  max-height: 320px;
  overflow-y: auto;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-lg, 0 8px 24px rgba(0, 0, 0, 0.18));
  padding: 6px;
}
.var-menu.hidden { display: none; }
.var-menu-group-label {
  font-size: var(--text-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  color: var(--text-muted);
  padding: 6px 8px 2px;
}
.var-menu-item {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 1px;
  width: 100%;
  text-align: left;
  padding: 5px 8px;
  border: none;
  background: none;
  border-radius: var(--radius-sm);
  cursor: pointer;
  font-size: var(--text-sm);
  color: var(--text);
}
.var-menu-item:hover, .var-menu-item:focus-visible { background: var(--surface-sunken); }
/* Zweite Zeile je Menüpunkt mit dem aktuellen Vorschauwert (siehe
   getPreviewValues in js/invoice-variables.js) - nur im Rechnungsformular,
   nicht in den Einstellungen (dort keine konkrete Rechnung vorhanden). */
.var-menu-item-value {
  font-size: var(--text-xs);
  color: var(--text-faint);
}
.var-menu-filter {
  width: 100%;
  box-sizing: border-box;
  margin-bottom: 6px;
  padding: 5px 8px;
  font-size: var(--text-sm);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface-sunken);
}
.var-menu-empty {
  padding: 5px 8px;
  font-size: var(--text-sm);
  color: var(--text-muted);
}

/* ---- Einfacher Balken-Chart (Umsatz nach Monat, Dashboard + EÜR) --------
   Balken haben eine FESTE Pixelbreite statt width:100% - ein Balken sitzt
   in .bar-chart-pair, einem unstyled-width Flex-Wrapper (für zwei Balken
   nebeneinander pro Monat). width:100% eines Flex-Kinds in einem Container
   ohne eigene definite Breite (nur "shrink-to-fit" über align-items:center
   im Elternelement .bar-chart-col) resolved im Browser zu ~0 - genau das
   hat die EÜR-Balken vorher unsichtbar gemacht, obwohl die Höhen korrekt
   berechnet wurden. Feste Breite umgeht dieses Problem zuverlässig.

   Struktur (siehe FinUtils.buildChartAxis + js/modules/dashboard.js|euer.js):
   .chart-row (Flex)
     .chart-axis        <- Y-Achsen-Beschriftung, feste Höhe = Plot-Höhe
     .chart-plot         <- position:relative, enthält Gitterlinien + Balken
       .chart-gridlines   <- absolut positioniert, hinter den Balken
       .bar-chart         <- die eigentlichen Balken/Spalten
   .chart-row (zweite Zeile, Monats-Beschriftungen unter dem Plot-Bereich) */
.chart-row {
  display: flex;
  align-items: flex-start;
  gap: var(--space-2);
}
/* .chart-axis + .chart-gridlines werden BEIDE mit absolut positionierten
   Kindern (top: N% je Linie/Label, siehe FinUtils.buildChartAxis) statt
   flex justify-content:space-between aufgebaut - Gitterlinien haben keine
   eigene Höhe (reine border-top-Linien), Text-Labels aber schon, wodurch
   space-between beide Gruppen unterschiedlich verteilt hätte und Zahlen
   nicht exakt auf ihrer Linie gesessen wären. */
.chart-axis {
  position: relative;
  flex-shrink: 0;
  width: 56px;
  padding-right: var(--space-2);
  font-size: 11px;
  color: var(--text-faint);
  font-variant-numeric: tabular-nums;
}
.chart-axis-label {
  position: absolute;
  right: 0;
  transform: translateY(-50%);
  white-space: nowrap;
}
.chart-axis-spacer { flex-shrink: 0; width: 56px; }
.chart-plot { position: relative; flex: 1; min-width: 0; }
.chart-gridlines {
  position: absolute;
  left: 0; right: 0; top: 0;
  height: 100%;
  pointer-events: none;
}
.chart-gridline {
  position: absolute;
  left: 0; right: 0;
  border-top: 1px dashed var(--border);
}
.chart-gridline:last-child { border-top: 1px solid var(--border-strong); }

.bar-chart {
  display: flex;
  align-items: flex-end;
  gap: var(--space-2);
  height: 120px;
  position: relative;
}
.bar-chart-col {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  height: 100%;
  justify-content: flex-end;
}
.bar-chart-pair {
  display: flex;
  align-items: flex-end;
  justify-content: center;
  gap: 4px;
  height: 100%;
}
.bar-chart-bar {
  width: 16px;
  flex-shrink: 0;
  border-radius: var(--radius-sm) var(--radius-sm) 0 0;
  background: var(--accent);
  min-height: 2px;
  transition: height var(--duration) var(--ease);
}
.bar-chart-bar.negative { background: var(--danger-solid); }
/* Einnahmen-Balken im EÜR-Chart - dasselbe Grün wie der "Bezahlt"-Anteil
   im Dashboard-Chart (.bar-chart-seg-paid), damit beide Diagramme optisch
   dieselbe Farbsprache für "Geld eingegangen" verwenden. */
.bar-chart-bar.positive { background: var(--success); }

/* Gestapelter Balken (bezahlter + noch offener Anteil einer Rechnung im
   selben Monat, siehe js/modules/dashboard.js) - Segmente werden in
   Dokumentreihenfolge unten -> oben gestapelt (normale column-Richtung,
   erstes Kind unten). */
.bar-chart-stack {
  width: 16px;
  flex-shrink: 0;
  display: flex;
  flex-direction: column-reverse;
  border-radius: var(--radius-sm) var(--radius-sm) 0 0;
  overflow: hidden;
}
.bar-chart-seg-paid { background: var(--success); min-height: 0; }
.bar-chart-seg-unpaid { background: var(--border-strong); min-height: 0; }

.bar-chart-labels {
  display: flex;
  flex: 1;
  min-width: 0;
  gap: var(--space-2);
  margin-top: var(--space-2);
}
.bar-chart-label {
  flex: 1;
  text-align: center;
  font-size: 11px;
  color: var(--text-faint);
  white-space: nowrap;
}
.bar-chart-legend {
  display: flex;
  justify-content: center;
  gap: var(--space-4);
  padding-top: var(--space-3);
  font-size: var(--text-xs);
  color: var(--text-muted);
}
.bar-chart-legend-dot {
  display: inline-block;
  width: 8px; height: 8px;
  border-radius: 2px;
  margin-right: 4px;
}

/* ==========================================================================
   Cards / Lists / Tables
   ========================================================================== */

.panel {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  overflow: hidden;
}

.panel-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-4);
  border-bottom: 1px solid var(--border);
  flex-wrap: wrap;
}
.panel-header h3 { font-size: var(--text-base); }

.row-list { display: flex; flex-direction: column; }

.row-item {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  padding: var(--space-4);
  border-bottom: 1px solid var(--border);
  transition: background-color var(--duration-fast) var(--ease);
}
.row-item:last-child { border-bottom: none; }
.row-item:hover { background: var(--surface-sunken); }

.row-main { flex: 1; min-width: 0; }
.row-title {
  font-weight: 600;
  font-size: var(--text-sm);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.row-meta {
  font-size: var(--text-xs);
  color: var(--text-faint);
  margin-top: 2px;
}

.row-actions { display: flex; align-items: center; gap: var(--space-2); flex-shrink: 0; }

.badge {
  display: inline-flex;
  align-items: center;
  height: 22px;
  padding: 0 var(--space-2);
  border-radius: var(--radius-pill);
  font-size: 11px;
  font-weight: 650;
  letter-spacing: 0.02em;
  white-space: nowrap;
}
.badge-success { background: var(--success-soft); color: var(--success); }
.badge-muted { background: var(--surface-sunken); color: var(--text-muted); border: 1px solid var(--border); }
.badge-warning { background: var(--warning-soft); color: var(--warning); }
.badge-danger { background: var(--danger-soft); color: var(--danger); }
.badge-accent { background: var(--accent-soft); color: var(--accent); }

/* ---- Generische Datentabelle (Kunden, Rechnungen, Projekte, Zeiteinträge) */
.data-table-wrap { overflow-x: auto; }
.data-table { width: 100%; border-collapse: collapse; font-size: var(--text-sm); }
.data-table th {
  text-align: left;
  font-size: var(--text-xs);
  font-weight: 650;
  color: var(--text-muted);
  padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
}
.data-table td {
  padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--border);
  vertical-align: middle;
}
.data-table tbody tr { transition: background-color var(--duration-fast) var(--ease); }
.data-table tbody tr:hover { background: var(--surface-sunken); }
.data-table tbody tr:last-child td { border-bottom: none; }
.data-table td.num, .data-table th.num { text-align: right; font-variant-numeric: tabular-nums; }
.data-table td.actions { text-align: right; white-space: nowrap; }

/* ---- Positions-Editor (Rechnungspositionen) ----------------------------- */
.table-editor { width: 100%; border-collapse: collapse; }
.table-editor th {
  text-align: left;
  font-size: var(--text-xs);
  color: var(--text-muted);
  font-weight: 600;
  padding: var(--space-2);
  border-bottom: 1px solid var(--border);
}
.table-editor td { padding: var(--space-2); border-bottom: 1px solid var(--border); vertical-align: top; }
.table-editor input { padding: 8px 10px; }
.table-editor tr:last-child td { border-bottom: none; }
.table-editor td.num { text-align: right; }

/* ---- Filter-Leiste (Zeiterfassung, Rechnungen) --------------------------- */
.filter-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--space-3);
  margin-bottom: var(--space-4);
  padding: var(--space-4);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
}
.filter-bar .field { margin-bottom: 0; min-width: 150px; }
.filter-bar .field-inline { flex: 0 0 auto; }

/* ---- Zeiterfassung: Start/Stop-Timer-Widget ------------------------------ */
.timer-widget {
  display: flex;
  align-items: center;
  gap: var(--space-5);
  padding: var(--space-5);
  flex-wrap: wrap;
}
.timer-widget.running {
  background: linear-gradient(135deg, var(--accent-soft), transparent 70%);
}
.timer-display {
  font-family: var(--font-mono);
  font-size: 2.4rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  min-width: 9ch;
  color: var(--text);
}
.timer-widget.running .timer-display { color: var(--accent); }
.timer-controls { display: flex; align-items: center; gap: var(--space-3); flex: 1; flex-wrap: wrap; min-width: 220px; }
.timer-controls .field { margin-bottom: 0; flex: 1; min-width: 180px; }
.timer-status-dot {
  width: 10px; height: 10px; border-radius: 50%;
  background: var(--text-faint);
  flex-shrink: 0;
}
.timer-widget.running .timer-status-dot {
  background: var(--success);
  animation: timer-pulse 1.6s ease-in-out infinite;
}
@keyframes timer-pulse {
  0%, 100% { box-shadow: 0 0 0 0 var(--success-soft); }
  50% { box-shadow: 0 0 0 6px transparent; }
}
@media (prefers-reduced-motion: reduce) {
  .timer-widget.running .timer-status-dot { animation: none; }
}

/* ==========================================================================
   Modal
   ========================================================================== */

.modal-backdrop {
  position: fixed; inset: 0;
  background: var(--scrim);
  display: grid;
  place-items: center;
  padding: var(--space-5);
  z-index: 160;
  opacity: 0;
  transition: opacity var(--duration) var(--ease);
  overflow-y: auto;
}
.modal-backdrop.open { opacity: 1; }

.modal {
  width: 100%;
  max-width: 560px;
  max-height: min(760px, 90dvh);
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  transform: translateY(8px) scale(0.98);
  opacity: 0;
  transition: transform var(--duration) var(--ease), opacity var(--duration) var(--ease);
  margin: auto;
}
.modal-backdrop.open .modal { transform: translateY(0) scale(1); opacity: 1; }

.modal-header {
  display: flex; align-items: center; justify-content: space-between;
  padding: var(--space-4) var(--space-5);
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}
.modal-header h3 { font-size: var(--text-lg); }
.modal-body { padding: var(--space-5); overflow-y: auto; }
.modal-footer {
  display: flex; justify-content: flex-end; flex-wrap: wrap; gap: var(--space-2);
  padding: var(--space-4) var(--space-5);
  border-top: 1px solid var(--border);
  flex-shrink: 0;
}
.modal-footer .footer-hint {
  flex: 1;
  font-size: var(--text-xs);
  color: var(--text-faint);
  align-self: center;
}

/* ---- Tabs (z.B. Konto-Einstellungen) ------------------------------------ */
.tab-row {
  display: flex;
  gap: var(--space-1);
  margin-bottom: var(--space-5);
  border-bottom: 1px solid var(--border);
}
.tab-btn {
  padding: var(--space-2) var(--space-3);
  margin-bottom: -1px;
  border: none;
  border-bottom: 2px solid transparent;
  border-radius: var(--radius-sm) var(--radius-sm) 0 0;
  background: transparent;
  color: var(--text-muted);
  font-size: var(--text-sm);
  font-weight: 600;
  cursor: pointer;
  transition: background-color var(--duration-fast) var(--ease), color var(--duration-fast) var(--ease);
}
.tab-btn:hover { background: var(--surface-sunken); color: var(--text); }
.tab-btn.active { color: var(--accent); border-bottom-color: var(--accent); }

.avatar-md {
  width: 36px; height: 36px;
  border-radius: 50%;
  background: var(--surface-sunken);
  border: 1px solid var(--border);
  display: grid; place-items: center;
  font-weight: 650;
  font-size: 13px;
  color: var(--text);
  flex-shrink: 0;
}

/* ==========================================================================
   Empty / Loading States
   ========================================================================== */

.empty-state {
  text-align: center;
  padding: var(--space-7) var(--space-4);
  color: var(--text-muted);
}
.empty-state .icon {
  width: 44px; height: 44px;
  margin: 0 auto var(--space-3);
  border-radius: var(--radius);
  background: var(--surface-sunken);
  display: grid; place-items: center;
  color: var(--text-faint);
}
.empty-state h4 { font-size: var(--text-base); color: var(--text); margin-bottom: var(--space-1); }
.empty-state p { font-size: var(--text-sm); max-width: 320px; margin: 0 auto var(--space-4); line-height: 1.5; }

.skeleton {
  background: linear-gradient(90deg, var(--surface-sunken) 25%, var(--border) 50%, var(--surface-sunken) 75%);
  background-size: 200% 100%;
  border-radius: var(--radius-sm);
  animation: skeleton-shimmer 1.4s ease-in-out infinite;
}
@media (prefers-reduced-motion: reduce) {
  .skeleton { animation: none; }
}
@keyframes skeleton-shimmer {
  0% { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}
.skeleton-row { height: 56px; margin-bottom: 1px; border-radius: 0; }

/* ==========================================================================
   Toasts
   ========================================================================== */

.toast-stack {
  position: fixed;
  bottom: var(--space-5);
  right: var(--space-5);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  z-index: 200;
  max-width: 340px;
}

.toast {
  display: flex;
  align-items: flex-start;
  gap: var(--space-2);
  background: var(--surface-raised);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-md);
  border-radius: var(--radius);
  padding: var(--space-3) var(--space-4);
  font-size: var(--text-sm);
  animation: toast-in var(--duration) var(--ease);
}
.toast.toast-success { border-color: hsl(140 50% 45% / 0.35); }
.toast.toast-error { border-color: hsl(0 60% 55% / 0.35); }

@keyframes toast-in {
  from { opacity: 0; transform: translateY(8px); }
  to { opacity: 1; transform: translateY(0); }
}
@media (prefers-reduced-motion: reduce) {
  .toast { animation: none; }
}

/* ==========================================================================
   Settings / Branding preview
   ========================================================================== */

.color-swatch-row { display: flex; align-items: center; gap: var(--space-3); }
.color-swatch-row input[type="color"] {
  width: 44px; height: 38px; padding: 2px; cursor: pointer;
}

.info-row {
  display: flex; justify-content: space-between; gap: var(--space-3);
  font-size: var(--text-sm); padding: 6px 0;
}
.info-row .info-label { color: var(--text-muted); }
.info-row .info-value { font-weight: 600; }

/* ==========================================================================
   Einstellungen / Rechnungsdesign (Farbe + Layout fürs PDF)
   ========================================================================== */

.design-color-grid { display: flex; flex-wrap: wrap; gap: var(--space-2); }

.design-color-swatch {
  width: 32px; height: 32px; border-radius: 50%;
  border: none; padding: 0; cursor: pointer; position: relative;
  box-shadow: 0 0 0 1px var(--border) inset;
}
.design-color-swatch.is-active::after {
  content: "";
  position: absolute; inset: -4px;
  border-radius: 50%;
  border: 2px solid var(--accent);
}
.design-color-swatch-custom {
  display: block;
  background: conic-gradient(red, yellow, lime, cyan, blue, magenta, red);
  overflow: hidden;
}
.design-color-swatch-custom input[type="color"] {
  width: 100%; height: 100%; padding: 0; border: none; cursor: pointer;
  opacity: 0;
}

.design-layout-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: var(--space-3);
}
.design-layout-card {
  display: flex; flex-direction: column; gap: var(--space-2);
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
  padding: var(--space-2); cursor: pointer; text-align: center;
  transition: border-color var(--duration-fast) var(--ease);
}
.design-layout-card:hover { border-color: var(--border-strong); }
.design-layout-card.is-active { border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent-ring); }
.design-layout-card .design-layout-label { font-size: var(--text-xs); font-weight: 600; }

.design-layout-thumb {
  height: 74px; border-radius: var(--radius-sm); overflow: hidden;
  background: #fff; box-shadow: 0 0 0 1px var(--border) inset;
  display: flex; flex-direction: column;
}
.design-thumb-header { flex-shrink: 0; }
.design-thumb-rows { flex: 1; padding: 5px 8px; display: flex; flex-direction: column; gap: 4px; }
.design-thumb-row { height: 5px; border-radius: 2px; background: #e5e5e0; }
.design-thumb-row.is-shaded { background: #efefe8; }

.design-preview {
  border-radius: var(--radius); overflow: hidden;
  box-shadow: 0 0 0 1px var(--border);
  background: #fff; color: #1c1c20; font-size: 10px;
}
.design-preview-body { padding: 14px 16px; }
.design-preview-brand { font-weight: 700; font-size: 11px; }
.design-preview-title { font-weight: 700; font-size: 13px; letter-spacing: 0.02em; }
.design-preview-table-header {
  display: flex; justify-content: space-between;
  font-size: 8px; font-weight: 700; color: #8a8a90;
  padding: 5px 8px; text-transform: uppercase; letter-spacing: 0.03em;
}
.design-preview-row {
  display: flex; justify-content: space-between;
  font-size: 9px; padding: 5px 8px;
}
.design-preview-row.is-shaded { background: #f7f7f2; }

/* ==========================================================================
   Responsive
   ========================================================================== */

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

@media (max-width: 860px) {
  .panel-grid-2 { grid-template-columns: 1fr; }
  .app-shell { grid-template-columns: 1fr; }
  .sidebar {
    position: fixed;
    inset: 0 auto 0 0;
    width: min(80vw, var(--sidebar-w));
    z-index: 90;
    transform: translateX(-100%);
    transition: transform var(--duration) var(--ease);
    box-shadow: var(--shadow-lg);
  }
  .sidebar.open { transform: translateX(0); }
  .view { padding: var(--space-4); }
  .stat-grid { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }
  .timer-widget { flex-direction: column; align-items: stretch; }
  .timer-display { text-align: center; }
}

/* ---- Vertrags-Flow: fehlende Variablen-Hinweis im Projektformular -------
   Fest im Modal angezeigt (nicht als Toast), solange nicht alle im
   Vertragstext genutzten {{variablen}} befüllbar sind - siehe
   js/modules/projects.js renderContractSection()/computeMissing(). */
.contract-missing-banner {
  margin-top: var(--space-3);
  padding: var(--space-3);
  border-radius: var(--radius);
  background: var(--warning-soft);
  color: var(--warning);
  font-size: var(--text-sm);
}
.contract-missing-banner strong { display: block; margin-bottom: 4px; }
.contract-missing-banner ul { margin: 0; padding-left: 18px; }

/* ---- Login-Screen (js/auth-gate.js) - nur aktiv wenn config.adapter ===
   "supabase" (siehe config.js), im Demo-Modus nie sichtbar. */
.auth-gate {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--bg);
  padding: var(--space-4);
}
.auth-card {
  width: 100%;
  max-width: 360px;
  padding: var(--space-6) var(--space-5);
}
.auth-mark {
  width: 44px;
  height: 44px;
  border-radius: var(--radius-sm);
  background: var(--accent);
  color: var(--accent-ink);
  display: grid;
  place-items: center;
  font-weight: 700;
  font-size: var(--text-base);
  margin: 0 auto var(--space-3);
}
.auth-title {
  text-align: center;
  font-weight: 650;
  font-size: var(--text-lg);
  margin-bottom: var(--space-1);
}
.auth-tagline {
  text-align: center;
  font-size: var(--text-sm);
  color: var(--text-faint);
  margin-bottom: var(--space-5);
}
.auth-form .btn { width: 100%; }
.auth-form .field:last-of-type { margin-bottom: var(--space-4); }
