/* ═══════════════════════════════════════════════════════════════════════════
   os.felixme.de — Design System (FLX-DESIGN)
   Reihenfolge: Tokens → Reset → Typo → Layout → Komponenten → Responsive
   Abschnitte 19+ sind projektspezifische Erweiterungen (Life-OS).
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── 0. Schriften — selbst gehostet, keine externen Requests ───────────── */
@font-face { font-family: 'Geist'; font-style: normal; font-weight: 400; font-display: swap; src: url('/assets/fonts/geist-400.woff2') format('woff2'); }
@font-face { font-family: 'Geist'; font-style: normal; font-weight: 500; font-display: swap; src: url('/assets/fonts/geist-500.woff2') format('woff2'); }
@font-face { font-family: 'Geist'; font-style: normal; font-weight: 600; font-display: swap; src: url('/assets/fonts/geist-600.woff2') format('woff2'); }
@font-face { font-family: 'Geist'; font-style: normal; font-weight: 700; font-display: swap; src: url('/assets/fonts/geist-700.woff2') format('woff2'); }
@font-face { font-family: 'Geist Mono'; font-style: normal; font-weight: 400; font-display: swap; src: url('/assets/fonts/geist-mono-400.woff2') format('woff2'); }

/* ── 1. Tokens ─────────────────────────────────────────────────────────── */
:root {
  /* Farben */
  /* Bereichsfarben — die einzige Stelle, an der sie stehen.
     Arbeit ist hellblau, Privat indigo (so gewünscht, 2026-07-31). Vorher war
     Arbeit indigo und Privat lieh sich den Erfolgs-Ton; damit sahen „Akzent"
     und „geschafft" im Privatbereich gleich aus. Grün bedeutet jetzt wieder
     nur Erfolg.
     Je Bereich zwei Werte: der helle für Text und Aktiv-Zustände auf dunklem
     Grund, der kräftige als Knopfhintergrund mit weißer Schrift. */
  --area-work:         #6FC8F7;
  --area-work-cta:     #0B72C9;
  --area-private:      #8B93FF;
  --area-private-cta:  #3E43F0;

  --accent:            var(--area-work);
  --accent-cta:        var(--area-work-cta);
  --accent-secondary:  #7A00DF;
  --accent-tertiary:   #007CBA;

  --text-primary:      #FAFAFA;
  --text-secondary:    #D4D4D8;
  --text-tertiary:     #A1A1AA;
  --text-muted:        #71717A;

  --surface-1:         #17171A;  /* Karten, Container       */
  --surface-2:         #111113;  /* Seitenhintergrund       */
  --surface-3:         #27272A;  /* Navigation, Hervorhebung */
  --border:            #27272A;
  --border-strong:     #3F3F46;

  --success:           #22C55E;
  --error:             #CF2E2E;
  --warning:           #FCB900;

  --overlay-accent:    color-mix(in srgb, var(--area-work-cta) 22%, transparent);
  --border-soft:       rgba(255, 255, 255, 0.22);
  --btn-overlay:       rgba(255, 255, 255, 0.08);

  /* Elevation */
  --shadow-1: rgba(0, 0, 0, 0.3) 0 1px 2px 0;
  --shadow-2: rgba(0, 0, 0, 0.4) 0 1px 3px 0, rgba(0, 0, 0, 0.3) 0 1px 2px -1px;
  --shadow-3: rgba(0, 0, 0, 0.5) 0 4px 8px 0, rgba(0, 0, 0, 0.3) 0 2px 4px -1px;

  /* Radius */
  --r-sm: 4px;
  --r-md: 6px;
  --r-lg: 8px;
  --r-xl: 10px;

  /* Spacing (4px-Basis) */
  --s-1: 4px;  --s-2: 8px;  --s-3: 12px; --s-4: 16px;
  --s-6: 24px; --s-8: 32px; --s-12: 48px; --s-16: 64px;

  --sidebar-w: 248px;
  --max-w: 1440px;

  --font: 'Geist', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --font-mono: 'Geist Mono', 'Courier New', monospace;
}

/* ── 2. Reset ──────────────────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--surface-2);
  color: var(--text-secondary);
  font-family: var(--font);
  font-size: 13px;
  line-height: 19.5px;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

img, svg { display: block; max-width: 100%; }
button, input, select, textarea { font: inherit; color: inherit; }

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

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

/* ── 3. Typografie ─────────────────────────────────────────────────────── */
h1, h2, h3, h4 { color: var(--text-primary); margin: 0; font-weight: 600; }
h1 { font-size: 48px; line-height: 57.6px; }
h2 { font-size: 32px; line-height: 38.4px; }
h3 { font-size: 20px; line-height: 24px; }
h4 { font-size: 14px; line-height: 20px; }
p  { margin: 0 0 var(--s-3); }

/* Links erben grundsätzlich die Textfarbe — kein Browser-Blau, keine
   Unterstreichung. Farbe bekommt nur, was ohne sie nicht auffindbar wäre
   (siehe .prose weiter unten). */
a { color: inherit; text-decoration: none; transition: color .15s ease; }

/* Dezenter Navigationslink: "Alle Termine", "Alle", Zurück-Pfeile.
   Ruhig im Normalzustand, Akzent erst bei Interaktion. */
.link,
.back-link,
.section-head a,
.card-head a {
  display: inline-flex; align-items: center; gap: 4px;
  color: var(--text-tertiary);
  font-size: 13px; font-weight: 500;
  white-space: nowrap;
}
.link:hover,
.back-link:hover,
.section-head a:hover,
.card-head a:hover { color: var(--accent); }

/* Zurück-Pfeil bewegt sich leicht — reicht als Affordanz ohne Unterstreichung */
.back-link { gap: 6px; }
.back-link::before { content: '←'; transition: transform .15s ease; }
.back-link:hover::before { transform: translateX(-2px); }

/* Überschriften und Textlinks: neutral, Akzent nur im Hover */
.event-title a:hover,
.card-title a:hover,
h3 a:hover,
a.strong:hover,
.table a:hover { color: var(--accent); }

/* Ganze Zeile als Ziel: Hintergrund statt Unterstreichung. */
.list-row {
  min-height: 36px;
  color: var(--text-secondary);
  border-radius: var(--r-md);
  padding-left: var(--s-2); padding-right: var(--s-2);
  margin-left: calc(var(--s-2) * -1); margin-right: calc(var(--s-2) * -1);
  transition: background .15s ease, color .15s ease;
}
.list-row:hover { background: var(--surface-3); color: var(--text-primary); }

/* Fließtext: hier MÜSSEN Links erkennbar sein, sonst findet sie niemand. */
.prose a { color: var(--accent); font-weight: 500; overflow-wrap: anywhere; }
.prose a:hover { color: var(--accent-cta); text-decoration: underline; }

code, pre, .mono { font-family: var(--font-mono); font-size: 13px; }

.text-lg    { font-size: 16px; line-height: 24px; }
.text-sm    { font-size: 12px; line-height: 18px; }
.muted      { color: var(--text-tertiary); }
.dim        { color: var(--text-muted); }
.strong     { color: var(--text-primary); font-weight: 600; }
.nowrap     { white-space: nowrap; }
.truncate   { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.text-success { color: var(--success); }
.text-error   { color: var(--error); }
.text-warning { color: var(--warning); }

/* ── 4. Layout ─────────────────────────────────────────────────────────── */
.app { display: flex; min-height: 100vh; }

.sidebar {
  width: var(--sidebar-w);
  flex-shrink: 0;
  background: var(--surface-1);
  border-right: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  position: sticky;
  top: 0;
  height: 100vh;
  overflow-y: auto;
}

.sidebar-brand {
  display: flex; align-items: center; gap: var(--s-3);
  padding: var(--s-6) var(--s-4);
  border-bottom: 1px solid var(--border);
}
/* Die Marke ist ein Link, soll aber nicht wie einer aussehen. */
.sidebar-brand .mark { transition: background .15s ease; }
.sidebar-brand:hover .mark { background: rgba(139, 147, 255, .28); }
.sidebar-brand .mark {
  width: 36px; height: 36px; flex-shrink: 0;
  border-radius: var(--r-lg);
  background: var(--overlay-accent);
  color: var(--accent);
  display: grid; place-items: center;
}
.sidebar-brand strong { display: block; color: var(--text-primary); font-size: 14px; line-height: 20px; }
.sidebar-brand span   { display: block; color: var(--text-muted); font-size: 12px; line-height: 16px; }

.nav { padding: var(--s-4) var(--s-2); flex: 1; }
.nav-section { margin-bottom: var(--s-6); }
.nav-label {
  font-size: 11px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase;
  color: var(--text-muted); padding: 0 var(--s-3) var(--s-2);
}
.nav-item {
  display: flex; align-items: center; gap: var(--s-3);
  min-height: 36px; padding: var(--s-2) var(--s-3);
  border-radius: var(--r-lg);
  color: var(--text-secondary);
  font-size: 13px; font-weight: 500;
  transition: background .15s ease, color .15s ease;
}
.nav-item:hover { background: var(--surface-3); color: var(--text-primary); text-decoration: none; }
.nav-item.is-active { background: var(--overlay-accent); color: var(--accent); }
.nav-item svg { width: 18px; height: 18px; flex-shrink: 0; }
.nav-item .count {
  margin-left: auto; font-size: 11px; font-weight: 600;
  background: var(--surface-3); color: var(--text-tertiary);
  padding: 1px 7px; border-radius: 999px;
}
.nav-item.is-active .count { background: rgba(139,147,255,.18); color: var(--accent); }

.sidebar-user {
  border-top: 1px solid var(--border);
  padding: var(--s-3);
  display: flex; align-items: center; gap: var(--s-3);
}
.sidebar-user img { width: 36px; height: 36px; border-radius: 50%; }
.sidebar-user a:hover { text-decoration: none; }
.sidebar-user a:hover .meta b { color: var(--accent); }
.sidebar-user .meta { min-width: 0; flex: 1; }
.sidebar-user .meta b { display: block; color: var(--text-primary); font-size: 13px; font-weight: 600; }
.sidebar-user .meta span { display: block; color: var(--text-muted); font-size: 11px; }

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

.topbar {
  display: none;
  align-items: center; gap: var(--s-3);
  padding: var(--s-3) var(--s-4);
  background: var(--surface-1);
  border-bottom: 1px solid var(--border);
  position: sticky; top: 0; z-index: 50;
}

.content {
  flex: 1;
  width: 100%;
  max-width: var(--max-w);
  margin: 0 auto;
  padding: var(--s-8) var(--s-8) var(--s-16);
}

.page-head {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: var(--s-4); flex-wrap: wrap;
  margin-bottom: var(--s-6);
}
.page-head h2 { letter-spacing: -0.02em; }
.page-head .sub { color: var(--text-tertiary); font-size: 14px; margin-top: var(--s-1); }
.page-actions { display: flex; gap: var(--s-2); flex-wrap: wrap; }

.section { margin-bottom: var(--s-12); }
.section-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--s-4); margin-bottom: var(--s-4);
}
.section-head h3 { letter-spacing: -0.01em; }
/* "Alle Termine ›" darf nie zwischen Text und Chevron umbrechen. */
.section-head a { display: inline-flex; align-items: center; gap: 4px; white-space: nowrap; }

.grid { display: grid; gap: var(--s-4); }
.grid-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.grid-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.grid-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.grid-sidebar { grid-template-columns: minmax(0, 1fr) 320px; gap: var(--s-6); }

.stack   { display: flex; flex-direction: column; gap: var(--s-4); }
.stack-2 { display: flex; flex-direction: column; gap: var(--s-2); }
.row     { display: flex; align-items: center; gap: var(--s-3); flex-wrap: wrap; }
.row-tight { display: flex; align-items: center; gap: var(--s-2); }
.spacer  { flex: 1; }

/* ── 5. Karten ─────────────────────────────────────────────────────────── */
.card {
  background: var(--surface-1);
  border: 1px solid var(--border);
  border-radius: var(--r-xl);
  box-shadow: var(--shadow-1);
  padding: var(--s-6);
  transition: border-color .15s ease, box-shadow .15s ease;
}
.card.is-interactive:hover {
  border-color: var(--border-strong);
  box-shadow: rgba(0, 0, 0, 0.4) 0 2px 4px 0;
}
.card-wide { padding: var(--s-6) var(--s-8); }
.card-compact { padding: var(--s-4); }
.card-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--s-3); margin-bottom: var(--s-4);
}
.card-title { font-size: 20px; font-weight: 600; color: var(--text-primary); line-height: 24px; }
.card-divider { height: 1px; background: var(--border); margin: var(--s-4) calc(var(--s-6) * -1); }

.icon-box {
  width: 40px; height: 40px; flex-shrink: 0;
  border-radius: var(--r-lg);
  background: var(--overlay-accent);
  color: var(--accent);
  display: grid; place-items: center;
}
.icon-box.success { background: rgba(34,197,94,.15);  color: var(--success); }
.icon-box.error   { background: rgba(207,46,46,.15);  color: var(--error); }
.icon-box.warning { background: rgba(252,185,0,.15);  color: var(--warning); }

/* Kennzahl-Kachel */
.stat { display: flex; align-items: center; gap: var(--s-4); }
.stat .value { font-size: 32px; line-height: 38.4px; font-weight: 600; color: var(--text-primary); }
.stat .label { font-size: 12px; color: var(--text-tertiary); }

/* ── 6. Buttons ────────────────────────────────────────────────────────── */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--s-2);
  min-height: 36px; padding: 0 14px;
  border-radius: var(--r-lg);
  border: 1px solid transparent;
  background: #FAFAFA; color: #0A0A0A;
  font-size: 13px; font-weight: 500; line-height: 20px;
  box-shadow: var(--shadow-2);
  cursor: pointer;
  transition: background .15s ease, color .15s ease, border-color .15s ease;
  text-decoration: none;
  white-space: nowrap;
}
.btn:hover  { background: #D4D4D8; color: #0A0A0A; text-decoration: none; }
.btn:active { background: #A1A1AA; }
.btn svg { width: 16px; height: 16px; }

.btn-primary { background: var(--accent-cta); color: #FAFAFA; }
.btn-primary:hover  { background: #5257F3; color: #FFFFFF; }
.btn-primary:active { background: #2E33D8; }

.btn-secondary {
  background: transparent; color: var(--text-primary);
  font-weight: 700; border-radius: var(--r-md); padding: 0 10px;
  box-shadow: none;
}
.btn-secondary:hover  { background: rgba(139,147,255,.1); color: var(--accent); border-color: var(--accent); }
.btn-secondary:active { background: rgba(139,147,255,.2); color: var(--accent-cta); border-color: var(--accent-cta); }

.btn-ghost {
  background: var(--btn-overlay); color: var(--text-primary);
  border: 1px solid var(--border-soft); box-shadow: none;
}
.btn-ghost:hover { background: rgba(139,147,255,.15); border-color: var(--accent); color: var(--text-primary); }

.btn-danger { background: var(--error); color: #FFFFFF; }
.btn-danger:hover { background: #E04141; color: #FFFFFF; }

.btn-icon { width: 36px; height: 36px; padding: 0; }

.btn[disabled], .btn.is-disabled {
  opacity: .5; cursor: not-allowed; pointer-events: none; box-shadow: none;
}

.btn-block { width: 100%; }

/* ── 7. Badges & Pills ─────────────────────────────────────────────────── */
.badge {
  display: inline-flex; align-items: center; gap: var(--s-1);
  padding: 4px 10px; border-radius: var(--r-md);
  font-size: 12px; font-weight: 600; line-height: 16px;
  background: rgba(139,147,255,.15); color: var(--accent);
  border: 1px solid var(--accent);
}
.badge-success { background: rgba(34,197,94,.15);  color: var(--success); border-color: var(--success); }
.badge-error   { background: rgba(207,46,46,.15);  color: var(--error);   border-color: var(--error); }
.badge-warning { background: rgba(252,185,0,.15);  color: var(--warning); border-color: var(--warning); }
.badge-muted   { background: var(--surface-3);     color: var(--text-tertiary); border-color: var(--border-strong); }
.badge-dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; }

.chip {
  display: inline-flex; align-items: center; gap: var(--s-2);
  padding: var(--s-1) var(--s-3); border-radius: 999px;
  background: var(--surface-3); border: 1px solid var(--border);
  color: var(--text-secondary); font-size: 12px; font-weight: 500;
}
.chip .swatch { width: 8px; height: 8px; border-radius: 50%; }

/* ── 8. Formulare ──────────────────────────────────────────────────────── */
.field { margin-bottom: var(--s-4); }
.label {
  display: block; margin-bottom: var(--s-2);
  font-size: 14px; font-weight: 600; line-height: 20px; color: var(--text-primary);
}
.hint { margin-top: var(--s-2); font-size: 12px; color: var(--text-muted); }

.input, .select, .textarea {
  width: 100%;
  min-height: 36px;
  padding: 8px 12px;
  background: var(--surface-1);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  color: var(--text-primary);
  font-size: 13px; line-height: 19.5px;
  transition: border-color .15s ease, box-shadow .15s ease;
}
.textarea { min-height: 120px; resize: vertical; line-height: 1.55; }
.input::placeholder, .textarea::placeholder { color: var(--text-muted); }
.input:focus, .select:focus, .textarea:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(139,147,255,.1);
}
.select {
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23A1A1AA' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 10px center;
  padding-right: 34px;
}
.input-error { border-color: var(--error); }

.checkbox, .radio {
  display: flex; align-items: flex-start; gap: var(--s-3);
  min-height: 36px; padding: var(--s-2) 0;
  cursor: pointer;
}
.checkbox input, .radio input { width: 18px; height: 18px; margin: 1px 0 0; accent-color: var(--accent-cta); flex-shrink: 0; }
.checkbox .txt b, .radio .txt b { display: block; color: var(--text-primary); font-weight: 500; font-size: 13px; }
.checkbox .txt span, .radio .txt span { display: block; color: var(--text-muted); font-size: 12px; }

.form-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 var(--s-4); }
.form-grid .span-2 { grid-column: 1 / -1; }

.form-actions {
  display: flex; justify-content: flex-end; gap: var(--s-2);
  padding-top: var(--s-4); margin-top: var(--s-4);
  border-top: 1px solid var(--border);
}

/* ── 9. Event-Karten & RSVP ────────────────────────────────────────────── */
.event-card {
  display: flex; gap: var(--s-4); align-items: stretch;
  background: var(--surface-1);
  border: 1px solid var(--border);
  border-left: 3px solid var(--accent);
  border-radius: var(--r-xl);
  box-shadow: var(--shadow-1);
  padding: var(--s-4);
  transition: border-color .15s ease, box-shadow .15s ease, transform .15s ease;
}
.event-card:hover { border-color: var(--border-strong); box-shadow: rgba(0,0,0,.4) 0 2px 4px 0; }
.event-card.is-cancelled { opacity: .6; border-left-color: var(--error); }
.event-card.is-cancelled .event-title { text-decoration: line-through; }

.event-date {
  width: 56px; flex-shrink: 0; text-align: center;
  background: var(--surface-3); border-radius: var(--r-lg);
  padding: var(--s-2) 0;
  align-self: flex-start;
}
.event-date .dow  { font-size: 11px; font-weight: 600; color: var(--accent); text-transform: uppercase; }
.event-date .day  { font-size: 20px; font-weight: 600; color: var(--text-primary); line-height: 24px; }
.event-date .mon  { font-size: 11px; color: var(--text-muted); text-transform: uppercase; }

.event-body { flex: 1; min-width: 0; }
.event-title { font-size: 16px; font-weight: 600; color: var(--text-primary); line-height: 24px; }
.event-title a { color: inherit; }
.event-title a:hover { color: var(--accent); text-decoration: none; }
.event-meta { display: flex; flex-wrap: wrap; gap: var(--s-1) var(--s-4); margin-top: var(--s-1); font-size: 12px; color: var(--text-tertiary); }
.event-meta span { display: inline-flex; align-items: center; gap: 5px; }
.event-meta svg { width: 14px; height: 14px; opacity: .8; }

/* ── 10. Zeilen-Listen ─────────────────────────────────────────────────── */
.member-row {
  display: flex; align-items: center; gap: var(--s-3);
  padding: var(--s-2) 0;
  min-height: 44px;
}
.member-row + .member-row { border-top: 1px solid var(--border); }
.member-row img { width: 32px; height: 32px; border-radius: 50%; flex-shrink: 0; }
.member-row .name { color: var(--text-primary); font-size: 13px; font-weight: 500; }
.member-row .sub  { color: var(--text-muted); font-size: 11px; }

/* ── 11. Tabellen ──────────────────────────────────────────────────────── */
.table-wrap { overflow-x: auto; border: 1px solid var(--border); border-radius: var(--r-xl); background: var(--surface-1); }
.table { width: 100%; border-collapse: collapse; font-size: 13px; }
.table th {
  text-align: left; padding: var(--s-3) var(--s-4);
  font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: .06em;
  color: var(--text-muted); background: var(--surface-3);
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
}
.table td { padding: var(--s-3) var(--s-4); border-bottom: 1px solid var(--border); vertical-align: middle; }
.table tr:last-child td { border-bottom: none; }
.table tbody tr:hover { background: rgba(255,255,255,.02); }
.table .num { text-align: right; font-variant-numeric: tabular-nums; }

/* Fortschrittsbalken in Statistiken */
.meter { height: 6px; border-radius: 999px; background: var(--surface-3); overflow: hidden; min-width: 80px; }
.meter i { display: block; height: 100%; background: var(--accent); }
.meter.good i { background: var(--success); }
.meter.mid  i { background: var(--warning); }
.meter.bad  i { background: var(--error); }

/* ── 11a. Einklappbare Karte (<details>) ───────────────────────────────── */
.collapsible { padding: 0; }
.collapsible > summary {
  display: flex; align-items: center; gap: var(--s-3);
  padding: var(--s-4) var(--s-6);
  cursor: pointer;
  list-style: none;          /* Standard-Dreieck weg */
  min-height: 44px;
  border-radius: var(--r-xl);
  transition: background .15s ease;
}
.collapsible > summary::-webkit-details-marker { display: none; }
.collapsible > summary:hover { background: rgba(255, 255, 255, .02); }
.collapsible > summary:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

.collapsible-chevron {
  display: inline-flex; flex-shrink: 0;
  color: var(--text-muted);
  transform: rotate(90deg);   /* zeigt nach unten = "aufklappen" */
  transition: transform .18s ease, color .15s ease;
}
.collapsible[open] > summary .collapsible-chevron { transform: rotate(-90deg); }
.collapsible > summary:hover .collapsible-chevron { color: var(--text-primary); }

/* Inhalt bekommt die Kartenpolsterung; die Trennlinie sitzt direkt
   unter dem Kopf, nicht mit Abstand darunter. */
.collapsible > *:not(summary) {
  padding: var(--s-2) var(--s-6) var(--s-6);
  border-top: 1px solid var(--border);
  margin-top: 0;
}

/* ── 11b. Einrichtungs-Checkliste ──────────────────────────────────────── */
.setup-list { display: flex; flex-direction: column; }
.setup-step {
  display: flex; align-items: center; gap: var(--s-3);
  padding: var(--s-3) 0; min-height: 44px;
}
.setup-step + .setup-step { border-top: 1px solid var(--border); }
.setup-step.is-done { opacity: .55; }
.setup-step.is-done .strong { text-decoration: line-through; }
.setup-marker {
  width: 24px; height: 24px; flex-shrink: 0;
  border-radius: 50%; display: grid; place-items: center;
  background: var(--surface-3); color: var(--text-tertiary);
  font-size: 11px; font-weight: 600;
}
.setup-step.is-done .setup-marker { background: rgba(34,197,94,.15); color: var(--success); }

/* ── 12. Tabs ──────────────────────────────────────────────────────────── */
.tabs { display: flex; gap: var(--s-1); border-bottom: 1px solid var(--border); margin-bottom: var(--s-6); overflow-x: auto; }
.tab {
  min-height: 36px; padding: var(--s-2) var(--s-4);
  color: var(--text-tertiary); font-size: 13px; font-weight: 500;
  border-bottom: 2px solid transparent; margin-bottom: -1px;
  white-space: nowrap; background: none; border-top: 0; border-left: 0; border-right: 0; cursor: pointer;
}
.tab:hover { color: var(--text-primary); text-decoration: none; }
.tab.is-active { color: var(--accent); border-bottom-color: var(--accent); }

/* ── 14. Leerzustände ──────────────────────────────────────────────────── */
.empty {
  text-align: center; padding: var(--s-16) var(--s-6);
  border: 1px dashed var(--border-strong); border-radius: var(--r-xl);
  color: var(--text-tertiary);
}
.empty .icon-box { margin: 0 auto var(--s-4); }
.empty h4 { font-size: 16px; margin-bottom: var(--s-2); }
.empty p { max-width: 420px; margin: 0 auto var(--s-4); }

/* ── 15. Flash & Toast ─────────────────────────────────────────────────── */

/* Benachrichtigungen ploppen oben rechts auf und räumen sich selbst weg. */
.toasts {
  position: fixed; top: var(--s-4); right: var(--s-4); z-index: 500;
  display: flex; flex-direction: column; gap: var(--s-2);
  width: 360px; max-width: calc(100vw - var(--s-8));
  pointer-events: none;
}
.toast {
  position: relative;
  display: flex; align-items: flex-start; gap: var(--s-3);
  padding: var(--s-3) var(--s-4);
  background: var(--surface-1);
  color: var(--text-secondary);
  border: 1px solid var(--border-strong);
  border-radius: var(--r-xl);
  box-shadow: var(--shadow-3);
  font-size: 13px; line-height: 19.5px;
  overflow: hidden;
  pointer-events: auto;
  opacity: 0;
  transform: translateX(16px) scale(.98);
  transition: opacity .22s cubic-bezier(.16,1,.3,1),
              transform .22s cubic-bezier(.16,1,.3,1),
              margin .22s ease;
}
.toast.is-in  { opacity: 1; transform: none; }
.toast.is-out { opacity: 0; transform: translateX(16px) scale(.96); margin-bottom: -52px; }

.toast-icon {
  flex-shrink: 0;
  width: 28px; height: 28px;
  display: grid; place-items: center;
  border-radius: var(--r-md);
}
.toast-body { flex: 1; min-width: 0; padding-top: 3px; }
.toast-title { display: block; color: var(--text-primary); font-weight: 600; margin-bottom: 2px; }
.toast-text  { display: block; overflow-wrap: anywhere; }

.toast-close {
  flex-shrink: 0;
  width: 24px; height: 24px;
  display: grid; place-items: center;
  border: 0; background: transparent; padding: 0;
  color: var(--text-muted); border-radius: var(--r-md);
  cursor: pointer; transition: background .15s ease, color .15s ease;
}
.toast-close:hover { background: var(--surface-3); color: var(--text-primary); }

/* Laufzeitanzeige — macht sichtbar, wie lange die Meldung noch steht. */
.toast-progress {
  position: absolute; left: 0; bottom: 0; height: 2px;
  background: currentColor; opacity: .5;
  transform-origin: left center;
  animation: toastCountdown linear forwards;
}
@keyframes toastCountdown { from { transform: scaleX(1); } to { transform: scaleX(0); } }
.toast:hover .toast-progress { animation-play-state: paused; }

.toast-success .toast-icon { background: rgba(34,197,94,.15);  color: var(--success); }
.toast-success .toast-progress { color: var(--success); }
.toast-error   .toast-icon { background: rgba(207,46,46,.15);  color: var(--error); }
.toast-error   .toast-progress { color: var(--error); }
.toast-warning .toast-icon { background: rgba(252,185,0,.15);  color: var(--warning); }
.toast-warning .toast-progress { color: var(--warning); }
.toast-info    .toast-icon { background: var(--overlay-accent); color: var(--accent); }
.toast-info    .toast-progress { color: var(--accent); }

@media (max-width: 639px) {
  .toasts { top: var(--s-3); left: var(--s-3); right: var(--s-3); width: auto; max-width: none; }
  .toast.is-out { margin-bottom: -60px; }
}

@media (prefers-reduced-motion: reduce) {
  .toast { transition: opacity .15s ease; transform: none; }
  .toast.is-in, .toast.is-out { transform: none; }
  .toast-progress { animation: none; }
}

/* ── 16. Modal ─────────────────────────────────────────────────────────── */
.modal { position: fixed; inset: 0; z-index: 300; display: none; align-items: center; justify-content: center; padding: var(--s-4); }
.modal.is-open { display: flex; }
.modal-backdrop { position: absolute; inset: 0; background: rgba(0,0,0,.7); }
.modal-panel {
  position: relative;
  background: var(--surface-1); border: 1px solid var(--border);
  border-radius: var(--r-xl); box-shadow: var(--shadow-3);
  width: 100%; max-width: 520px; max-height: calc(100vh - 32px); overflow: auto;
  animation: modalPop .2s cubic-bezier(.16,1,.3,1);
}
@keyframes modalPop { from { opacity: 0; transform: scale(.97) translateY(8px); } to { opacity: 1; transform: none; } }
.modal-head { padding: var(--s-6) var(--s-6) var(--s-3); display: flex; justify-content: space-between; gap: var(--s-3); }
.modal-body { padding: 0 var(--s-6) var(--s-4); }
.modal-foot { padding: var(--s-4) var(--s-6) var(--s-6); display: flex; justify-content: flex-end; gap: var(--s-2); border-top: 1px solid var(--border); }

/* ── 17. Login-Seite ───────────────────────────────────────────────────── */
.auth-screen {
  min-height: 100vh; display: grid; place-items: center;
  padding: var(--s-6);
  background:
    radial-gradient(900px 500px at 50% -10%, rgba(62,67,240,.18), transparent 70%),
    var(--surface-2);
}
.auth-card { width: 100%; max-width: 420px; text-align: center; }
.auth-card .mark {
  width: 56px; height: 56px; margin: 0 auto var(--s-6);
  border-radius: var(--r-xl); background: var(--overlay-accent);
  color: var(--accent); display: grid; place-items: center;
}
.auth-card h1 { font-size: 32px; line-height: 38.4px; margin-bottom: var(--s-2); }
.auth-card p  { color: var(--text-tertiary); font-size: 14px; margin-bottom: var(--s-6); }

/* ── 18. Responsive ────────────────────────────────────────────────────── */
@media (max-width: 1023px) {
  .grid-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .grid-3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .grid-sidebar { grid-template-columns: minmax(0, 1fr); }
  .content { padding: var(--s-6) var(--s-6) var(--s-16); }
}

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

  .sidebar {
    position: fixed; inset: 0 auto 0 0; z-index: 100;
    transform: translateX(-100%);
    transition: transform .2s ease;
    box-shadow: var(--shadow-3);
  }
  .sidebar.is-open { transform: none; }
  .sidebar-scrim {
    position: fixed; inset: 0; z-index: 90;
    background: rgba(0,0,0,.7); display: none;
  }
  .sidebar-scrim.is-open { display: block; }

  .topbar { display: flex; }
  .content { padding: var(--s-4) var(--s-4) var(--s-16); }

  h1 { font-size: 28px; line-height: 34px; }
  h2 { font-size: 20px; line-height: 26px; }

  .grid-2, .grid-3, .grid-4 { grid-template-columns: minmax(0, 1fr); }
  .form-grid { grid-template-columns: minmax(0, 1fr); }

  .page-head { flex-direction: column; align-items: stretch; }
  .page-actions .btn { flex: 1; min-height: 44px; }


  .form-actions { flex-direction: column-reverse; }
  .form-actions .btn { width: 100%; min-height: 44px; }

  .setup-step { flex-wrap: wrap; }
  .setup-step .btn { width: 100%; }

  .collapsible > summary { padding: var(--s-3) var(--s-4); }
  .collapsible > summary .meter { display: none; }
  .collapsible > *:not(summary) { padding: var(--s-2) var(--s-4) var(--s-4); }

  .toasts { left: var(--s-4); right: var(--s-4); bottom: var(--s-4); max-width: none; }
}

@media print {
  .sidebar, .topbar, .page-actions, .btn { display: none !important; }
  body { background: #FFFFFF; color: #0A0A0A; }
  .card, .table-wrap { border-color: #DDDDDD; box-shadow: none; background: #FFFFFF; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   Projektspezifische Erweiterungen — Life-OS
   Ausschließlich aus den Tokens oben gebaut: keine neuen Farben, Abstände aus
   der 4px-Skala, Radien aus der Skala, Interaktives >= 36px (44px mobil).
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── 19. Bereichsumschaltung (Arbeit / Privat) ─────────────────────────────
   Der Privat-Bereich muss funktional unterscheidbar sein. Statt einer neuen
   Farbe wird der vorhandene Erfolgs-Ton zum Akzent umgehängt — Navigation,
   Badges, Buttons, Fokus und Icon-Boxen ziehen automatisch nach. */
body[data-area="private"] {
  --accent:         var(--area-private);
  --accent-cta:     var(--area-private-cta);
  --overlay-accent: color-mix(in srgb, var(--area-private-cta) 18%, transparent);
}
@supports not (color: color-mix(in srgb, red 50%, blue)) {
  body[data-area="private"] { --accent-cta: var(--area-private-cta); }
}

/* ── 20. Bottom-Navigation und Aktionsknöpfe (nur mobil) ───────────────────
   Die App ist Mobile-First; die Schublade allein trägt die Hauptwege nicht.
   Erscheint nur unter 768px, wo die Sidebar ohnehin zur Schublade wird. */
.bottom-nav { display: none; }
.fab { display: none; }

@media (max-width: 767px) {
  .bottom-nav {
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 80;
    display: none;
    grid-template-columns: repeat(5, 1fr);
    background: var(--surface-1);
    border-top: 1px solid var(--border);
    padding-bottom: env(safe-area-inset-bottom);
  }
  body[data-area="work"]    .bottom-nav-work,
  body[data-area="private"] .bottom-nav-private { display: grid; }

  .bn-item {
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: var(--s-1);
    min-height: 56px; padding: var(--s-2) var(--s-1);
    color: var(--text-muted);
    font-size: 10px; font-weight: 600; letter-spacing: .04em; text-transform: uppercase;
    transition: color .15s ease;
  }
  .bn-item svg { width: 20px; height: 20px; }
  .bn-item.is-active { color: var(--accent); }
  .bn-item-private { color: var(--area-private); }
  .bn-item-work    { color: var(--area-work); }

  .fab {
    position: fixed; right: var(--s-4); z-index: 90;
    bottom: calc(56px + var(--s-4) + env(safe-area-inset-bottom));
    display: grid; place-items: center;
    width: 56px; height: 56px;
    border: 1px solid transparent; border-radius: 50%;
    background: var(--accent-cta); color: #FAFAFA;
    box-shadow: var(--shadow-3);
    cursor: pointer;
    transition: background .15s ease;
  }
  .fab:hover { background: var(--accent); }
  .fab svg { width: 24px; height: 24px; }

  /* Zweiter, ruhigerer Knopf darüber: Suche */
  .fab-search {
    bottom: calc(56px + var(--s-4) + 56px + var(--s-3) + env(safe-area-inset-bottom));
    width: 44px; height: 44px;
    background: var(--surface-3); color: var(--text-secondary);
    border-color: var(--border-strong);
    box-shadow: var(--shadow-2);
  }
  .fab-search:hover { background: var(--surface-1); color: var(--accent); }
  .fab-search svg { width: 20px; height: 20px; }

  /* Platz, damit die Leiste nichts verdeckt */
  .content { padding-bottom: calc(56px + var(--s-16)); }
}

/* ── 21. Befehlspalette (Strg+K) ───────────────────────────────────────────
   Overlay auf Basis des Modal-Bausteins, Trefferzeilen im .list-row-Muster. */
.palette-input { margin-bottom: var(--s-3); }
.palette-results { max-height: 50vh; overflow-y: auto; }
.palette-hint { color: var(--text-muted); font-size: 12px; padding: var(--s-2) var(--s-1); }
.palette-group {
  font-size: 11px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase;
  color: var(--text-muted);
  margin: var(--s-4) var(--s-1) var(--s-2);
}
.palette-group:first-child { margin-top: 0; }
.palette-item {
  display: flex; align-items: center; gap: var(--s-3);
  min-height: 36px; padding: var(--s-2) var(--s-3);
  border-radius: var(--r-md);
  color: var(--text-secondary);
  cursor: pointer;
  transition: background .15s ease, color .15s ease;
}
.palette-item:hover,
.palette-item.is-active { background: var(--surface-3); color: var(--text-primary); }
.palette-item svg { width: 16px; height: 16px; flex-shrink: 0; color: var(--text-muted); }
.palette-item-title { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.palette-item-done .palette-item-title { text-decoration: line-through; color: var(--text-muted); }

/* ── 22. Aufgaben-, Notiz- und Inbox-Zeilen ────────────────────────────────
   Zeile als eigenständige Karte (Schwester von .event-card), damit Abhaken,
   Titel und Kennzeichen nebeneinander Platz haben. */
.row-card {
  display: flex; align-items: flex-start; gap: var(--s-3);
  background: var(--surface-1);
  border: 1px solid var(--border);
  border-radius: var(--r-xl);
  box-shadow: var(--shadow-1);
  padding: var(--s-3) var(--s-4);
  min-height: 44px;
  transition: border-color .15s ease, box-shadow .15s ease;
}
.row-card:hover { border-color: var(--border-strong); box-shadow: rgba(0, 0, 0, .4) 0 2px 4px 0; }
.row-card.is-done { opacity: .6; }
.row-card.is-done .row-card-title { text-decoration: line-through; color: var(--text-muted); }
.row-card-main { flex: 1; min-width: 0; }
.row-card-title { color: var(--text-primary); font-size: 13px; font-weight: 500; overflow-wrap: anywhere; }
.row-card-meta { display: flex; flex-wrap: wrap; gap: var(--s-2); margin-top: var(--s-2); }
/* Zurückgenommen statt unsichtbar — aus demselben Grund wie beim Ziehgriff:
   Der Platz war immer reserviert, die Zeile sah ohne Zeiger unfertig aus.
   Beim Drüberfahren gehen die Knöpfe auf volle Deckkraft. */
.row-card-actions { display: flex; gap: var(--s-1); flex-shrink: 0; opacity: .5; transition: opacity .15s ease; }
.row-card:hover .row-card-actions,
.row-card:focus-within .row-card-actions { opacity: 1; }
@media (hover: none) { .row-card-actions { opacity: 1; } }

/* Freistehendes Kontrollkästchen (ohne Beschriftung) in Zeilen */
.check {
  width: 18px; height: 18px; margin: 1px 0 0;
  accent-color: var(--accent-cta);
  flex-shrink: 0; cursor: pointer;
}

/* Prioritätspunkt */
.prio-dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; background: var(--text-muted); margin-top: 6px; }
.prio-dot.high   { background: var(--error); box-shadow: 0 0 0 3px rgba(207, 46, 46, .15); }
.prio-dot.medium { background: var(--warning); }
.prio-dot.low    { background: var(--text-muted); }

/* ── 23. Unteraufgaben ─────────────────────────────────────────────────────
   Baut auf dem Muster der Einrichtungs-Checkliste auf. */
.subtask-list { display: flex; flex-direction: column; }
.subtask-item {
  display: flex; align-items: center; gap: var(--s-3);
  min-height: 44px; padding: var(--s-2) 0;
}
.subtask-item + .subtask-item { border-top: 1px solid var(--border); }
.subtask-item.is-done .subtask-title { text-decoration: line-through; color: var(--text-muted); }
.subtask-title { flex: 1; min-width: 0; font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ── 24. Segmentleiste (Schnellerfassung, Ansichtswechsel) ───────────────── */
.segment {
  display: flex; gap: var(--s-1);
  padding: var(--s-1);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
}
.segment button {
  flex: 1;
  display: inline-flex; align-items: center; justify-content: center; gap: var(--s-2);
  min-height: 36px; padding: 0 var(--s-3);
  border: 0; border-radius: var(--r-md);
  background: transparent; color: var(--text-tertiary);
  font-size: 13px; font-weight: 500;
  cursor: pointer;
  transition: background .15s ease, color .15s ease;
}
.segment button:hover { color: var(--text-primary); }
.segment button.is-active { background: var(--overlay-accent); color: var(--accent); }
.segment button svg { width: 16px; height: 16px; }
.segment button[data-area="work"].is-active {
  background: color-mix(in srgb, var(--area-work) 15%, transparent);
  color: var(--area-work);
}
.segment button[data-area="private"].is-active {
  background: color-mix(in srgb, var(--area-private) 15%, transparent);
  color: var(--area-private);
}

/* ── 25. Notiz-Editor ──────────────────────────────────────────────────────
   Zweispaltig ab 900px: links Eingabe, rechts Vorschau (.prose). */
.note-edit { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s-4); }
@media (min-width: 900px) { .note-edit.is-split { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); } }
.note-edit .textarea { min-height: 60vh; font-family: var(--font-mono); }
.note-preview {
  padding: var(--s-4);
  background: var(--surface-1);
  border: 1px solid var(--border);
  border-radius: var(--r-xl);
  overflow-y: auto;
  max-height: 70vh;
}
.note-title-input {
  width: 100%;
  background: transparent; border: 0; padding: 0;
  color: var(--text-primary);
  font-family: var(--font); font-size: 32px; line-height: 38.4px; font-weight: 600;
  letter-spacing: -0.02em;
}
.note-title-input:focus { outline: none; }

/* Auszeichnungen im Fließtext (Markdown-Vorschau) */
.prose h1, .prose h2, .prose h3 { color: var(--text-primary); margin: var(--s-6) 0 var(--s-3); }
.prose h1 { font-size: 24px; line-height: 30px; }
.prose h2 { font-size: 20px; line-height: 24px; }
.prose h3 { font-size: 16px; line-height: 22px; }
.prose > :first-child { margin-top: 0; }
.prose p { margin: 0 0 var(--s-3); line-height: 1.6; }
.prose ul, .prose ol { margin: 0 0 var(--s-3); padding-left: var(--s-6); }
.prose li { margin-bottom: var(--s-1); }
.prose code { background: var(--surface-2); border-radius: var(--r-sm); padding: 1px 6px; font-size: 12px; }
.prose pre {
  background: var(--surface-2); border: 1px solid var(--border);
  border-radius: var(--r-lg); padding: var(--s-3); overflow-x: auto;
}
.prose pre code { background: transparent; padding: 0; }
.prose strong { color: var(--text-primary); font-weight: 600; }
.prose blockquote {
  border-left: 3px solid var(--border-strong);
  margin: 0 0 var(--s-3); padding-left: var(--s-3);
  color: var(--text-tertiary);
}
.prose hr { border: 0; border-top: 1px solid var(--border); margin: var(--s-6) 0; }

/* ── 26. Farbwahl (Projekte, Kalenderquellen) ─────────────────────────────- */
.swatch-grid { display: flex; flex-wrap: wrap; gap: var(--s-2); }
.swatch-btn {
  width: 28px; height: 28px; padding: 0;
  border: 2px solid transparent; border-radius: 50%;
  cursor: pointer;
  transition: transform .15s ease, border-color .15s ease;
}
.swatch-btn:hover { transform: scale(1.08); }
.swatch-btn.is-active { border-color: var(--text-primary); }

/* ── 27. Kalender ──────────────────────────────────────────────────────────
   Monat (mit Mehrtagesbalken), Woche und Tag. Die Struktur stammt aus der
   bestehenden Kalender-Engine; hier ausschließlich auf Tokens gesetzt. */

.cal-toolbar { display: flex; align-items: center; gap: var(--s-2); flex-wrap: wrap; margin-bottom: var(--s-4); }
.cal-label { font-size: 20px; line-height: 24px; font-weight: 600; color: var(--text-primary); letter-spacing: -0.01em; margin-right: auto; text-transform: capitalize; }

/* Der Kalender darf die Inhaltsbreite ausreizen */
.view-calendar { max-width: none; }

/* ---------- Monat ---------- */
.cal-month {
  border: 1px solid var(--border);
  border-radius: var(--r-xl);
  overflow: hidden;
  background: var(--surface-1);
  box-shadow: var(--shadow-1);
}
.cal-month-head {
  display: grid; grid-template-columns: repeat(7, minmax(0, 1fr));
  background: var(--surface-3);
  border-bottom: 1px solid var(--border);
}
.cal-head {
  padding: var(--s-2) var(--s-3);
  font-size: 11px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase;
  color: var(--text-muted);
  border-right: 1px solid var(--border);
}
.cal-head:nth-child(7n) { border-right: none; }

.cal-month-week { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); position: relative; }

.cal-day {
  min-height: 116px;
  padding: var(--s-2);
  border-right: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
  display: flex; flex-direction: column; gap: 3px;
  position: relative; min-width: 0;
  cursor: pointer;
}
.cal-day:nth-child(7n) { border-right: none; }
.cal-month-week:last-child .cal-day { border-bottom: none; }
.cal-day.other { background: var(--surface-2); }
.cal-day.other .cal-day-num,
.cal-day.other .cal-evt { opacity: .5; }
.cal-day.today { background: var(--overlay-accent); box-shadow: inset 0 0 0 1px var(--accent); }
.cal-day.today .cal-day-num { color: var(--accent); }

.cal-day-num {
  position: absolute; top: var(--s-2); left: var(--s-2);
  font-size: 12px; font-weight: 600; color: var(--text-secondary);
  z-index: 1;
}
.cal-day-events { display: flex; flex-direction: column; gap: 3px; min-width: 0; margin-top: var(--s-4); }
.cal-day-more {
  font-size: 11px; font-weight: 600;
  color: var(--text-muted);
  cursor: pointer; user-select: none;
  padding: 2px var(--s-1);
}
.cal-day-more:hover { color: var(--accent); }

/* Termin-Chip */
.cal-evt { cursor: pointer; min-width: 0; }
.cal-evt-chip {
  display: flex; align-items: center; gap: 5px;
  padding: 3px 6px;
  border-radius: var(--r-sm);
  background: color-mix(in srgb, var(--evt, #8B93FF) 14%, transparent);
  border-left: 2px solid var(--evt, #8B93FF);
  color: var(--text-secondary);
  font-size: 11px; line-height: 15px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  min-width: 0;
  transition: background .15s ease, color .15s ease;
}
.cal-evt-chip:hover { background: color-mix(in srgb, var(--evt, #8B93FF) 26%, transparent); color: var(--text-primary); }
.cal-evt-time { color: var(--text-muted); font-variant-numeric: tabular-nums; flex-shrink: 0; }

@supports not (background: color-mix(in srgb, red 10%, transparent)) {
  .cal-evt-chip { background: var(--surface-3); }
  .cal-evt-chip:hover { background: var(--border-strong); }
}

/* Mehrtagesbalken: eigenes Raster über der Wochenzeile */
.cal-month-week-bars {
  position: absolute; top: 0; left: 0; width: 100%;
  display: grid; grid-template-columns: repeat(7, minmax(0, 1fr));
  pointer-events: none;
  z-index: 2;
}
.cal-span-bar {
  pointer-events: auto;
  background: var(--surface-3);
  border: 1px solid var(--border);
  border-left: 3px solid var(--evt, #8B93FF);
  border-radius: var(--r-sm);
  padding: 2px 6px;
  margin: 0 var(--s-2);
  font-size: 11px; font-weight: 500; line-height: 15px;
  color: var(--text-secondary);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  cursor: pointer; min-width: 0;
  transition: background .15s ease, color .15s ease;
}
.cal-span-bar:hover { background: var(--border-strong); color: var(--text-primary); }
.cal-span-bar.cs-left  { border-left: 1px solid var(--border); border-top-left-radius: 0; border-bottom-left-radius: 0; margin-left: 0; }
.cal-span-bar.cs-right { border-top-right-radius: 0; border-bottom-right-radius: 0; margin-right: 0; }

/* ---------- Woche ---------- */
.cal-week {
  border: 1px solid var(--border);
  border-radius: var(--r-xl);
  background: var(--surface-1);
  box-shadow: var(--shadow-1);
  overflow: hidden;
}
.cal-week-title {
  padding: var(--s-3) var(--s-4);
  font-weight: 600; color: var(--text-primary); text-align: center;
  background: var(--surface-3);
  border-bottom: 1px solid var(--border);
}
.cal-week-grid { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); min-height: 480px; }
.cal-week-col { border-right: 1px solid var(--border); display: flex; flex-direction: column; cursor: pointer; }
.cal-week-col:last-child { border-right: none; }
.cal-week-col.today { background: var(--overlay-accent); }
.cal-week-col-head {
  padding: var(--s-3);
  border-bottom: 1px solid var(--border);
  background: var(--surface-3);
  position: relative;
}
.cal-week-col.today .cal-week-col-head { background: var(--overlay-accent); }
.cal-week-col-name {
  font-size: 11px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase;
  color: var(--text-muted);
}
.cal-week-col-date { font-size: 20px; line-height: 24px; font-weight: 600; color: var(--text-primary); margin-top: 2px; }
.cal-week-col.today .cal-week-col-date { color: var(--accent); }
.cal-week-col-badge {
  position: absolute; right: var(--s-2); top: var(--s-3);
  font-size: 10px; font-weight: 600; letter-spacing: .06em;
  color: var(--accent); background: var(--overlay-accent);
  padding: 2px 6px; border-radius: var(--r-sm);
}
.cal-week-col-body { padding: var(--s-2); display: flex; flex-direction: column; gap: var(--s-2); flex: 1; }
.cal-week-col-empty { color: var(--text-muted); font-size: 12px; text-align: center; padding: var(--s-2) 0; font-family: var(--font-mono); }

.cal-evt-card {
  background: var(--surface-3);
  border: 1px solid var(--border);
  border-left: 3px solid var(--evt, #8B93FF);
  border-radius: var(--r-md);
  padding: var(--s-2);
  font-size: 12px; line-height: 16px;
  cursor: pointer;
  transition: background .15s ease;
}
.cal-evt-card:hover { background: var(--border-strong); }
.cal-evt-meta {
  font-family: var(--font-mono); font-size: 10px;
  color: var(--text-muted); text-transform: uppercase; letter-spacing: .06em;
  margin-bottom: var(--s-1);
}
.cal-evt-title {
  color: var(--text-primary); font-weight: 500;
  overflow: hidden; text-overflow: ellipsis;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
}

/* ---------- Tag ---------- */
.cal-day-view {
  --cal-gutter: 56px;
  border: 1px solid var(--border);
  border-radius: var(--r-xl);
  background: var(--surface-1);
  box-shadow: var(--shadow-1);
  overflow: hidden;
  display: flex; flex-direction: column;
  /* Startwert für den ersten Bildaufbau; fitDay() misst danach genau nach. */
  height: clamp(420px, calc(100vh - 300px), 1200px);
}
.cal-day-head {
  flex: none;
  display: flex; align-items: baseline; gap: var(--s-3);
  padding: var(--s-3) var(--s-4);
  font-size: 16px; font-weight: 600; color: var(--text-primary);
  background: var(--surface-3);
  border-bottom: 1px solid var(--border);
}
.cal-day-head-count {
  margin-left: auto;
  font-size: 12px; font-weight: 400; color: var(--text-muted);
  font-variant-numeric: tabular-nums;
}
.cal-day-allday {
  flex: none;
  display: flex; gap: var(--s-4);
  padding: var(--s-2) var(--s-4);
  background: var(--surface-3);
  border-bottom: 1px solid var(--border);
}
.cal-day-allday-label {
  font-size: 11px; font-weight: 600;
  color: var(--text-muted);
  min-width: 56px; padding-top: var(--s-1);
}
.cal-day-allday-events { flex: 1; display: flex; flex-wrap: wrap; gap: var(--s-2); }

/* Raster: gleich hohe Stunden, Höhe kommt vom Container (fitDay). */
.cal-day-grid { position: relative; cursor: pointer; flex: 1; min-height: 0; }
.cal-day-hours {
  height: 100%;
  display: grid;
  grid-template-rows: repeat(var(--cal-rows, 15), minmax(0, 1fr));
}
.cal-day-hour { position: relative; border-top: 1px solid var(--border); min-height: 0; }
.cal-day-hour:first-child { border-top: none; }
.cal-day-hour.is-off { background: rgba(255, 255, 255, .015); }
/* halbe Stunde — hilft beim genauen Ablesen, ohne das Raster zu überladen */
.cal-day-hour::after {
  content: ''; position: absolute; left: var(--cal-gutter); right: 0; top: 50%;
  border-top: 1px solid color-mix(in srgb, var(--border) 55%, transparent);
}
/* Beschriftung hängt unter ihrer Linie — gleich in jeder Zeile, auch der
   ersten. Zentriert auf der Linie ginge oben über den Kartenrand hinaus. */
.cal-day-hour-label {
  position: absolute; left: 0; top: 0; width: var(--cal-gutter);
  padding: 2px var(--s-2) 0 0; text-align: right;
  font-family: var(--font-mono); font-size: 11px; line-height: 13px;
  color: var(--text-muted);
}

.cal-day-events-layer {
  position: absolute; top: 0; left: var(--cal-gutter); right: var(--s-2); bottom: 0;
  pointer-events: none;
}
.cal-day-evt {
  position: absolute;
  container-type: size;
  background: var(--surface-3);
  border: 1px solid var(--border);
  border-left: 3px solid var(--evt, #8B93FF);
  border-radius: var(--r-md);
  padding: 1px var(--s-2);
  cursor: pointer; pointer-events: auto; overflow: hidden;
  /* Muss die Zeile ganz fassen (15px Zeilenhöhe + Innenabstand), sonst
     schneidet `overflow: hidden` die Schrift an und es sieht aus wie ein
     Strich mit Textresten. */
  min-height: 19px;
  /* Der Block darf keinen Rand mit dem nächsten teilen — sonst verschmelzen
     aufeinanderfolgende Termine optisch zu einem Kasten. Die Lücke kommt aus
     der Höhenrechnung im Renderer (−2px). */
  transition: background .15s ease;
}
.cal-day-evt:hover { background: var(--border-strong); z-index: 5; }
/* Grundzustand ist die enge Zeile — nur wenn Platz da ist, wird aufgeklappt. */
.cal-day-evt-in {
  display: flex; align-items: center; gap: var(--s-2);
  min-width: 0; height: 100%; overflow: hidden;
}
.cal-day-evt-time {
  flex: none;
  font-family: var(--font-mono); font-size: 10px; line-height: 15px;
  color: var(--text-muted); font-variant-numeric: tabular-nums;
}
.cal-day-evt-till { display: none; }
.cal-day-evt-title {
  color: var(--text-primary); font-size: 12px; font-weight: 500; line-height: 15px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.cal-day-evt-loc { display: none; color: var(--text-tertiary); font-size: 11px; }

/* Die Schwellen sind nachgerechnet, nicht geschätzt: Was der Block zeigt,
   muss in seine Höhe passen — sonst schneidet `overflow: hidden` mitten in
   eine Zeile, und genau das sah nach einem Fehler aus.

     zweizeilig  15 (Zeit) + 34 (2 Zeilen) + 1 + 2 (Polster) = 52  → ab 62px
     einzeilig   15        + 17            + 1 + 2           = 35  → ab 40px
     mit Ort     15 + 51 (3 Zeilen) + 1 + 17 (Ort) + 2       = 86  → ab 96px

   Vorher klappte schon ab 40px auf zwei Zeilen auf und ab 76px kam der Ort
   dazu — beides mehr Inhalt, als in den Block passte. Auf dem Handy trat das
   bei jedem Stundentermin auf (52px Blockhöhe gegen 55px Inhalt). */
@container (min-height: 40px) {
  .cal-day-evt-in { display: block; }
  .cal-day-evt-till { display: inline; }
  .cal-day-evt-title {
    display: -webkit-box; -webkit-line-clamp: 1; -webkit-box-orient: vertical;
    white-space: normal; font-size: 13px; line-height: 17px; margin-top: 1px;
  }
}
@container (min-height: 62px) {
  .cal-day-evt-title { -webkit-line-clamp: 2; }
}
@container (min-height: 96px) {
  .cal-day-evt-loc { display: block; margin-top: 2px; }
  .cal-day-evt-title { -webkit-line-clamp: 3; }
}
@container (max-width: 110px) {
  .cal-day-evt-till { display: none; }
}
/* Der Ziehgriff eigener Termine darf den Inhalt nicht nach unten schieben —
   in flachen Blöcken wäre der Titel sonst weg. */
.cal-day-evt .dnd-handle-inline { position: absolute; top: 1px; right: 2px; z-index: 1; }

/* Jetzt-Linie */
.cal-day-now { position: absolute; left: 0; right: 0; height: 2px; background: var(--error); z-index: 3; pointer-events: none; }
.cal-day-now::before {
  content: ''; position: absolute; left: -6px; top: -4px;
  width: 10px; height: 10px; border-radius: 50%; background: var(--error);
}
.cal-day-now-label {
  position: absolute; right: var(--s-1); top: -8px;
  background: var(--error); color: #FAFAFA;
  font-family: var(--font-mono); font-size: 10px; font-weight: 600;
  padding: 1px 6px; border-radius: var(--r-sm); letter-spacing: .04em;
}

/* Schmalere Schirme: feste Stundenhöhe, dafür scrollt die Seite wie gehabt.
   Gleicher Umbruchpunkt wie `.cal-layout` — darunter steht die Seitenspalte
   unter dem Kalender und die Seite scrollt sowieso. */
@media (max-width: 1099px) {
  .cal-day-view { height: auto; }
  .cal-day-hours { height: auto; grid-template-rows: none; grid-auto-rows: 56px; }
  .cal-day-evt-title { white-space: normal; }
}

/* ---------- Tages-Popover ("+N weitere") ---------- */
.cal-popover {
  position: fixed; z-index: 200;
  width: 320px; max-height: min(70vh, 520px);
  background: var(--surface-1);
  border: 1px solid var(--border-strong);
  border-radius: var(--r-xl);
  box-shadow: var(--shadow-3);
  display: flex; flex-direction: column;
  overflow: hidden;
}
.cal-popover-head {
  display: flex; align-items: flex-start; justify-content: space-between; gap: var(--s-3);
  padding: var(--s-4) var(--s-4) var(--s-2);
}
.cal-popover-eyebrow {
  font-size: 11px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase;
  color: var(--text-muted); margin-bottom: 2px;
}
.cal-popover-date { font-size: 16px; font-weight: 600; color: var(--text-primary); }
.cal-popover-count {
  padding: 0 var(--s-4) var(--s-3);
  font-family: var(--font-mono); font-size: 11px; color: var(--text-muted); letter-spacing: .04em;
  border-bottom: 1px solid var(--border);
}
.cal-popover-body { padding: var(--s-2); overflow-y: auto; display: flex; flex-direction: column; gap: var(--s-1); }
.cal-popover-empty { padding: var(--s-6); text-align: center; color: var(--text-muted); font-size: 13px; }
.cal-popover-evt {
  display: flex; gap: var(--s-3);
  padding: var(--s-2) var(--s-3);
  border-left: 3px solid var(--evt, #8B93FF);
  background: var(--surface-3);
  border-radius: var(--r-md);
  cursor: pointer;
  transition: background .15s ease;
}
.cal-popover-evt:hover { background: var(--border-strong); }
.cal-popover-evt-time {
  font-family: var(--font-mono); font-size: 11px; color: var(--text-tertiary);
  flex-shrink: 0; min-width: 68px; padding-top: 1px;
}
.cal-popover-evt-body { flex: 1; min-width: 0; }
.cal-popover-evt-title { font-size: 13px; font-weight: 500; color: var(--text-primary); line-height: 17px; overflow-wrap: anywhere; }
.cal-popover-evt-source {
  display: flex; align-items: center; gap: var(--s-2);
  margin-top: var(--s-1);
  font-size: 10px; color: var(--text-muted); text-transform: uppercase; letter-spacing: .06em;
}
.cal-popover-dot { width: 6px; height: 6px; border-radius: 50%; flex-shrink: 0; }

@media (max-width: 767px) {
  .cal-day { min-height: 84px; padding: var(--s-1); }
  .cal-day-num { top: var(--s-1); left: var(--s-1); }
  .cal-day-events { margin-top: var(--s-3); }
  .cal-head { padding: var(--s-2) var(--s-1); text-align: center; }
  .cal-evt-time { display: none; }
  .cal-day-more-word { display: none; }
  .cal-week-grid { grid-template-columns: minmax(0, 1fr); min-height: 0; }
  .cal-week-col { border-right: none; border-bottom: 1px solid var(--border); }
  .cal-popover { width: auto; left: var(--s-3) !important; right: var(--s-3); }
}

/* Bereichsakzent auch in Modals (der Umschalter dort kann vom Body abweichen) */
.modal[data-area="private"] {
  --accent:         var(--area-private);
  --accent-cta:     var(--area-private-cta);
  --overlay-accent: color-mix(in srgb, var(--area-private-cta) 18%, transparent);
}

/* Initialen-Kachel in der Seitenleiste */
.sidebar-user .mark {
  width: 36px; height: 36px; flex-shrink: 0;
  border-radius: var(--r-lg);
  background: var(--overlay-accent);
  color: var(--accent);
  display: grid; place-items: center;
  font-size: 13px; font-weight: 600;
}

/* ── 28. Kartenbeschreibung ────────────────────────────────────────────── */
.card-desc { color: var(--text-tertiary); font-size: 13px; margin: 0 0 var(--s-4); }
.card-head:has(+ .card-desc) { margin-bottom: var(--s-2); }

/* ── 29. Einstellungen: Reiterinhalte ──────────────────────────────────── */
.settings-pane { display: flex; flex-direction: column; gap: var(--s-4); }
.settings-pane[hidden] { display: none; }
.settings-pane .section { margin-bottom: 0; }

/* ── 30. Benutzermenü (Seitenleiste) ───────────────────────────────────── */
.user-menu {
  position: fixed; z-index: 400;
  min-width: 220px;
  padding: var(--s-1);
  background: var(--surface-1);
  border: 1px solid var(--border-strong);
  border-radius: var(--r-xl);
  box-shadow: var(--shadow-3);
  display: flex; flex-direction: column; gap: 2px;
}
.user-menu-item {
  display: flex; align-items: center; gap: var(--s-3);
  min-height: 36px; padding: var(--s-2) var(--s-3);
  border: 0; border-radius: var(--r-md);
  background: transparent; color: var(--text-secondary);
  font-size: 13px; font-weight: 500; text-align: left;
  cursor: pointer;
  transition: background .15s ease, color .15s ease;
}
.user-menu-item:hover { background: var(--surface-3); color: var(--text-primary); }
.user-menu-item svg { width: 16px; height: 16px; flex-shrink: 0; color: var(--text-muted); }
.user-menu-item.danger { color: var(--error); }
.user-menu-item.danger:hover { background: rgba(207, 46, 46, .12); color: var(--error); }
.user-menu-item.danger svg { color: currentColor; }
.user-menu-sep { height: 1px; background: var(--border); margin: var(--s-1) 0; }

/* ── 31. Nachträge Redesign ────────────────────────────────────────────────
   Komponenten, die im Markup vorkommen und beim Umbau ohne Regel geblieben
   sind. Ausschließlich aus den Tokens gebaut. */

/* Schließen-Knopf im Kalender-Popover (Markup liefert ein "×"-Zeichen) */
.cal-popover-close {
  flex-shrink: 0;
  width: 24px; height: 24px;
  display: grid; place-items: center;
  border: 0; background: transparent; padding: 0;
  color: var(--text-muted);
  font-size: 18px; line-height: 1;
  border-radius: var(--r-md);
  cursor: pointer;
  transition: background .15s ease, color .15s ease;
}
.cal-popover-close:hover { background: var(--surface-3); color: var(--text-primary); }

/* Wochenenden im Kalender dezent absetzen (Monat, Wochenkopf, Wochenspalte) */
.cal-head.weekend { color: var(--text-tertiary); }
.cal-day.weekend:not(.today):not(.other) { background: rgba(255, 255, 255, .015); }
.cal-week-col.weekend:not(.today) { background: rgba(255, 255, 255, .015); }

/* Angaben-Raster in der „Über"-Karte (Einstellungen → Daten) */
.about-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--s-4) var(--s-6);
  font-size: 13px;
}
.about-grid > div { display: flex; flex-direction: column; gap: var(--s-1); }
.about-grid .label { font-size: 11px; margin-bottom: 0; color: var(--text-muted); }
@media (max-width: 639px) { .about-grid { grid-template-columns: minmax(0, 1fr); } }

/* ── 32. Korrekturen aus der Sichtprüfung ──────────────────────────────── */

/* Symbole in Kartentiteln: der Reset setzt svg { display: block } — ohne Flex
   bricht das Symbol auf eine eigene Zeile über die Überschrift. */
.card-title { display: flex; align-items: center; gap: var(--s-2); }
.card-title svg { width: 18px; height: 18px; flex-shrink: 0; color: var(--text-muted); }

/* overflow-x: auto setzt overflow-y implizit auf auto. Der -1px-Rand der
   Reiter erzeugt dadurch 1px vertikalen Überlauf und einen Geister-Scrollbalken. */
.tabs { scrollbar-width: none; }
.tabs::-webkit-scrollbar { display: none; }

/* Scrollbalken im Systemton statt in der hellen Betriebssystem-Variante */
* { scrollbar-width: thin; scrollbar-color: var(--border-strong) transparent; }
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
  background: var(--border-strong);
  border-radius: 999px;
  border: 3px solid transparent;
  background-clip: padding-box;
}
::-webkit-scrollbar-thumb:hover { background: var(--text-muted); background-clip: padding-box; }

/* Seitenleiste: drei Abschnitte (Arbeit, Privat, System) brauchen mehr Höhe,
   als die Vorlage vorsah — etwas enger, damit der Nutzerblock unten sichtbar
   bleibt, statt hinter den Rand zu rutschen. */
.sidebar-brand { padding: var(--s-4); }
.nav { padding: var(--s-3) var(--s-2); }
.nav-section { margin-bottom: var(--s-4); }
.nav-section:last-child { margin-bottom: 0; }

/* ── 33. Reiter mit Symbol ─────────────────────────────────────────────────
   Gleiche Ursache wie bei .card-title: der Reset setzt svg { display: block },
   ohne Flex rutscht das Symbol über die Beschriftung (Einstellungen-Reiter). */
.tab { display: inline-flex; align-items: center; justify-content: center; gap: var(--s-2); }
.tab svg { width: 16px; height: 16px; flex-shrink: 0; }

/* ── 34. Trefferfläche der Abhak-Box ───────────────────────────────────────
   Das freistehende Kontrollkästchen in Zeilen ist optisch 18px groß. Ohne
   umgebendes Label wäre auch die Trefferfläche nur 18px — die Systemregel
   verlangt 44px auf Touch. Ein unsichtbares Pseudo-Element vergrößert die
   Fläche, ohne die Darstellung zu verändern. */
.check { position: relative; }
.check::after {
  content: '';
  position: absolute;
  inset: -13px;      /* 18px + 2×13px = 44px */
  border-radius: var(--r-sm);
}
@media (hover: hover) {
  .check::after { inset: -9px; }   /* 36px mit Maus */
}
/* Das Auswahlkästchen ist mit 15px kleiner als das Abhak-Kästchen (siehe
   .check-select) — seine Fläche muss entsprechend weiter greifen. */
.check-select::after { inset: -14.5px; }              /* 15 + 2×14,5 = 44 */
@media (hover: hover) {
  .check-select::after { inset: -10.5px; }            /* 15 + 2×10,5 = 36 */
}

/* ── 35. Kennzahlen auf kleinen Schirmen ───────────────────────────────────
   Untereinander würden vier Kacheln zwei Drittel des Handy-Bildschirms
   belegen, bevor der eigentliche Inhalt beginnt. Deshalb 2×2 und kompakter. */
@media (max-width: 767px) {
  .grid-4:has(> .stat) { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s-3); }
  .grid-4 > .stat { padding: var(--s-4); gap: var(--s-3); }
  .grid-4 > .stat .icon-box { width: 32px; height: 32px; }
  .grid-4 > .stat .icon-box svg { width: 16px; height: 16px; }
  .grid-4 > .stat .value { font-size: 24px; line-height: 30px; }
}

/* ── 36. Sprunglink ────────────────────────────────────────────────────────
   Erstes fokussierbares Element der Seite: überspringt die Navigation und
   führt direkt zum Inhalt. Nur sichtbar, solange er den Fokus hat. */
.skip-link {
  position: fixed;
  top: var(--s-2);
  left: var(--s-2);
  z-index: 600;
  padding: var(--s-2) var(--s-4);
  min-height: 36px;
  display: inline-flex;
  align-items: center;
  background: var(--accent-cta);
  color: #FAFAFA;
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-3);
  font-size: 13px;
  font-weight: 500;
  transform: translateY(calc(-100% - var(--s-4)));
  transition: transform .15s ease;
}
.skip-link:focus { transform: none; color: #FAFAFA; }

/* Der Inhaltsbereich ist per Sprunglink fokussierbar, soll aber keinen
   Fokusrahmen zeigen, wenn er nur programmatisch angesprungen wird. */
.content:focus { outline: none; }

/* ── 37. Schlagwörter ──────────────────────────────────────────────────────
   Chip mit angehängter Häufigkeit; Grundlage ist der System-Chip. */
.tag-chip {
  min-height: 36px;
  padding-right: var(--s-1);
  cursor: pointer;
  transition: border-color .15s ease, color .15s ease;
}
.tag-chip:hover { border-color: var(--accent); color: var(--text-primary); }
.tag-chip-name { color: inherit; }
.tag-chip-count {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 22px; height: 22px; padding: 0 6px;
  border-radius: 999px;
  background: var(--surface-1);
  color: var(--text-muted);
  font-size: 11px; font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.tag-chip:hover .tag-chip-count { color: var(--accent); }

/* Schlagwort-Badges in Zeilen sind Links — sie sollen sich als solche
   verraten, ohne die Ruhe der Zeile zu stören. */
a.badge:hover { border-color: var(--accent); color: var(--accent); }

/* Verteilungszeile der Schlagwörter */
.tag-row { cursor: pointer; }
.tag-row-name  { min-width: 140px; }
.tag-row-meter { flex: 1; }
.tag-row-stat  { min-width: 120px; text-align: right; }

@media (max-width: 767px) {
  /* Auf schmalen Schirmen passen Name, Balken und Zahlen nicht nebeneinander.
     Die Zahlen stehen ohnehin schon auf dem Chip darüber. */
  .tag-row-name { min-width: 0; flex: 1; }
  .tag-row-stat { display: none; }
  .tag-row-meter { flex: none; width: 96px; }
}

/* ── 38. Arbeitsbereich-Umschalter ─────────────────────────────────────────
   Arbeit und Privat sind gleichwertige Arbeitsbereiche, nicht zwei Kategorien
   untereinander. Die Seitenleiste zeigt immer nur den aktiven Bereich; die
   Segmentleiste unter der Marke wechselt ihn. Beide Navigationen stehen im
   Markup (wie bei der Bottom-Navigation), die inaktive wird ausgeblendet —
   das spart einen Render-Durchlauf und hält die Zähler beider Bereiche aktuell. */
.sidebar-switch { padding: var(--s-3) var(--s-3) 0; }
.sidebar-switch .segment { width: 100%; }

body[data-area="work"]    .nav-area-private,
body[data-area="private"] .nav-area-work { display: none; }

@media (max-width: 767px) {
  /* Ab hier ist die Seitenleiste eine Schublade — der Umschalter wird mit dem
     Daumen bedient und braucht die 44px Trefferhöhe. */
  .sidebar-switch .segment button { min-height: 44px; }
}

/* ── 39. Ziehen und Ablegen ────────────────────────────────────────────────
   Der Griff ist der einzige Startpunkt der Geste. Auf Touch muss er
   `touch-action: none` tragen, sonst gewinnt das Scrollen der Seite — und
   genau deshalb liegt die Geste nicht auf der ganzen Zeile. */
.dnd-handle {
  display: inline-flex; align-items: center; justify-content: center;
  width: 24px; min-height: 36px; flex-shrink: 0;
  color: var(--text-muted);
  cursor: grab;
  touch-action: none;
  /* Dauerhaft sichtbar, nur zurückgenommen.
     Vorher stand der Griff auf `opacity: 0` und tauchte erst beim Hovern auf.
     Sein Platz wurde aber immer reserviert — die Zeilen begannen damit hinter
     einer leeren Lücke, was wie ein Layoutfehler aussah. Dasselbe galt für
     das Auswahlkästchen daneben. */
  opacity: .45;
  transition: opacity .15s ease, color .15s ease;
}
.row-card:hover .dnd-handle,
.card:hover .dnd-handle,
.subtask-item:hover .dnd-handle,
.dnd-handle:focus-visible { opacity: 1; }
.dnd-handle:hover { color: var(--text-secondary); }
.dnd-handle:active { cursor: grabbing; }

/* Ohne Hover (Touch) gibt es kein „beim Drüberfahren" — dort etwas kräftiger,
   Trefferhöhe 44px. */
@media (hover: none) {
  .dnd-handle { opacity: .6; min-height: 44px; width: 32px; }
}

/* Das Original bleibt als Lücke stehen, während der Klon am Zeiger hängt. */
.is-dragging { opacity: .35; }
.dnd-ghost {
  box-shadow: var(--shadow-3);
  border-radius: var(--r-xl);
  opacity: .95;
  transform: rotate(.5deg);
}
body.dnd-active { user-select: none; cursor: grabbing; }

/* Ablageziel unter dem Zeiger */
.is-dropping {
  outline: 2px dashed var(--accent);
  outline-offset: 2px;
  background: var(--overlay-accent);
}

/* Angeheftete Notizen */
.card.is-pinned { border-color: color-mix(in srgb, var(--accent) 45%, var(--border)); }
.note-pin { opacity: .5; transition: opacity .15s ease, color .15s ease; }
/* Auch in Zeilenkarten (Lesezeichen) — dort ist die Zeile eine `.row-card`.
   Ohne diese Zeile blieb der Anheft-Knopf dauerhaft unsichtbar, weil die
   eigene Deckkraft die der `.row-card-actions` überstimmt. */
.card:hover .note-pin,
.row-card:hover .note-pin,
.row-card:focus-within .note-pin,
.note-pin[data-pinned="1"] { opacity: 1; }
.note-pin[data-pinned="1"] { color: var(--accent); }
@media (hover: none) { .note-pin { opacity: .7; } }

/* Ablageflächen des Eingangs — nur während einer Ziehbewegung sichtbar,
   damit sie im Ruhezustand keine Fläche verbrauchen. */
.drop-targets { display: none; gap: var(--s-3); margin-top: var(--s-3); }
body.dnd-active .drop-targets { display: flex; }
.drop-target {
  flex: 1;
  display: flex; align-items: center; justify-content: center; gap: var(--s-2);
  min-height: 56px; padding: var(--s-3);
  border: 1px dashed var(--border-strong);
  border-radius: var(--r-xl);
  color: var(--text-tertiary);
  font-size: 13px; font-weight: 500;
}
.drop-target svg { width: 16px; height: 16px; }

/* ── 40. Board, Mehrfachauswahl, Wiederholungs-Chips ──────────────────────── */

/* Board: drei Spalten, waagerecht scrollbar auf schmalen Schirmen. */
.board { display: grid; grid-template-columns: repeat(3, minmax(240px, 1fr)); gap: var(--s-4); }
@media (max-width: 767px) {
  .board { grid-auto-flow: column; grid-template-columns: none; grid-auto-columns: 82%;
           overflow-x: auto; scroll-snap-type: x mandatory; padding-bottom: var(--s-2); }
  .board-col { scroll-snap-align: start; }
}
.board-col {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--r-xl);
  padding: var(--s-3);
  min-height: 120px;
}
.board-col-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: var(--s-3); }
.board-col-body { display: flex; flex-direction: column; gap: var(--s-2); min-height: 60px; }
.board-card {
  display: flex; align-items: flex-start; gap: var(--s-2);
  padding: var(--s-3);
  background: var(--surface-1);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-1);
}
.board-card-title { color: var(--text-primary); font-size: 13px; font-weight: 500; cursor: pointer; }
.board-card-title:hover { color: var(--accent); }
.board-card .dnd-handle { min-height: 20px; }

/* Mehrfachauswahl */
/* Ebenfalls dauerhaft sichtbar (siehe .dnd-handle): Der Platz war ohnehin
   reserviert, und ein Bedienelement, das man erst findet, wenn man zufällig
   darüberfährt, ist keins.

   Kleiner als das Abhak-Kästchen daneben. In einer Aufgabenzeile stehen beide
   nebeneinander; gleich groß und gleich gefärbt wäre nicht zu erkennen,
   welches erledigt und welches auswählt. Die Trefferfläche bleibt über das
   unsichtbare ::after bei 36px (Maus) bzw. 44px (Touch). */
.check-select { width: 15px; height: 15px; opacity: .45; transition: opacity .15s ease; }
.row-card:hover .check-select,
.card:hover .check-select,
.check-select:checked,
.check-select:focus-visible,
.row-card.is-selected .check-select,
.card.is-selected .check-select { opacity: 1; }
@media (hover: none) { .check-select { opacity: .6; } }
.row-card.is-selected { border-color: var(--accent); background: var(--overlay-accent); }

.bulk-bar {
  position: fixed; left: 50%; transform: translateX(-50%);
  bottom: var(--s-4); z-index: 200;
  display: flex; align-items: center; gap: var(--s-2);
  max-width: calc(100vw - var(--s-8));
  padding: var(--s-2) var(--s-3);
  background: var(--surface-3);
  border: 1px solid var(--border-strong);
  border-radius: var(--r-xl);
  box-shadow: var(--shadow-3);
  overflow-x: auto;
}
.bulk-bar .strong { white-space: nowrap; color: var(--text-primary); font-size: 13px; }
@media (max-width: 767px) {
  /* Über der Bottom-Navigation bleiben, sonst verdeckt sie die Leiste. */
  .bulk-bar {
    left: var(--s-3); right: var(--s-3);
    transform: none;
    max-width: none;
    bottom: calc(56px + var(--s-3) + env(safe-area-inset-bottom));
    /* Umbrechen statt waagerecht scrollen: Bei sechs Knöpfen lagen auf einem
       390px-Schirm vier davon außerhalb des Bildes — sichtbar war nur, was
       zufällig zuerst kam, und gescrollt hat dort niemand. */
    flex-wrap: wrap;
    overflow-x: visible;
  }
  /* Die Zahl bekommt eine eigene Zeile, die Knöpfe teilen sich die darunter. */
  .bulk-bar .strong  { flex: 1 0 100%; }
  .bulk-bar .spacer  { display: none; }
  /* Nicht wachsen lassen: In der letzten Zeile stehen oft nur zwei Knöpfe,
     und der eine, der sich den freien Platz nahm, war „Löschen" — die
     zerstörende Aktion als größte Fläche im Bild. Natürliche Breite, linksbündig. */
  .bulk-bar .btn     { flex: 0 1 auto; min-height: 44px; }
  .bulk-bar .btn-icon { flex: 0 0 auto; margin-left: auto; }

  /* Die runden Aktionsknöpfe säßen genau auf der Leiste — gleiche Höhe über
     der Navigation, gleiche rechte Kante. Solange etwas ausgewählt ist,
     treten sie zurück; die Auswahl ist ohnehin das, was gerade zählt. */
  body:has(#bulk-bar) .fab { display: none; }
}

/* Umschaltbare Chips (Wochentage der Wiederholung) */
.chip-row { display: flex; flex-wrap: wrap; gap: var(--s-2); margin-top: var(--s-2); }
.chip.is-toggle { cursor: pointer; min-height: 36px; }
.chip.is-toggle.is-active {
  border-color: var(--accent);
  background: var(--overlay-accent);
  color: var(--accent);
}

/* ── 41. Anhänge ──────────────────────────────────────────────────────────── */
.attach-list { display: flex; flex-direction: column; gap: var(--s-2); }
.attach-list:not(:empty) { margin-bottom: var(--s-3); }
.attach-item {
  display: flex; align-items: center; gap: var(--s-3);
  padding: var(--s-2) var(--s-3);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  min-height: 44px;
}
.attach-thumb {
  width: 32px; height: 32px; flex-shrink: 0;
  border-radius: var(--r-md);
  object-fit: cover;
  background: var(--surface-3);
}
.attach-thumb-icon { display: grid; place-items: center; color: var(--text-muted); }
.attach-name { flex: 1; min-width: 0; color: var(--text-secondary); font-size: 13px; }
.attach-name:hover { color: var(--accent); }

.dropfile {
  display: flex; align-items: center; justify-content: center; gap: var(--s-2);
  flex-wrap: wrap;
  min-height: 56px; padding: var(--s-3);
  border: 1px dashed var(--border-strong);
  border-radius: var(--r-xl);
  color: var(--text-tertiary);
  font-size: 13px;
  transition: border-color .15s ease, background .15s ease;
}
.dropfile.is-over { border-color: var(--accent); background: var(--overlay-accent); color: var(--accent); }
.dropfile svg { width: 16px; height: 16px; }
.textarea.is-over { border-color: var(--accent); box-shadow: 0 0 0 3px var(--overlay-accent); }

/* Bilder im gerenderten Markdown */
.prose img { max-width: 100%; height: auto; border-radius: var(--r-lg); border: 1px solid var(--border); }

/* ── 42. Kalender: Seitenspalte und Aufgaben-Termine ─────────────────────── */
.cal-layout { display: grid; grid-template-columns: minmax(0, 1fr) 260px; gap: var(--s-4); align-items: start; }
@media (max-width: 1100px) {
  /* Auf schmalen Schirmen wandert die Spalte unter den Kalender. */
  .cal-layout { grid-template-columns: minmax(0, 1fr); }
}
.cal-side {
  background: var(--surface-1);
  border: 1px solid var(--border);
  border-radius: var(--r-xl);
  padding: var(--s-4);
}
.unplanned-item {
  display: flex; align-items: center; gap: var(--s-2);
  min-height: 40px; padding: var(--s-2) var(--s-3);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  font-size: 13px; color: var(--text-secondary);
}
.unplanned-item:hover { border-color: var(--border-strong); }
.unplanned-item .dnd-handle { min-height: 24px; width: 18px; }

/* Griff innerhalb eines Termin-Chips */
.dnd-handle-inline { width: 14px; min-height: 14px; opacity: 0; }
.cal-evt:hover .dnd-handle-inline { opacity: .7; }

/* Kalendertag als Ablageziel */
.cal-day.is-dropping { outline-offset: -2px; }

/* ── 43. Zeit, Beziehungen, Vorschläge ───────────────────────────────────── */
.time-list { display: flex; flex-direction: column; gap: var(--s-1); margin-top: var(--s-2); }
.time-item {
  display: flex; align-items: center; gap: var(--s-2);
  padding: var(--s-1) var(--s-2);
  border-bottom: 1px solid var(--border);
  color: var(--text-tertiary);
}
.time-item:last-child { border-bottom: 0; }

/* Kleines X in Chips (Abhängigkeiten, Verknüpfungen, Ansichten) */
.chip-x {
  display: inline-flex; align-items: center; justify-content: center;
  width: 18px; height: 18px; margin-left: var(--s-1);
  padding: 0; border: 0; border-radius: 999px;
  background: transparent; color: inherit; cursor: pointer;
  opacity: .6;
}
.chip-x:hover { opacity: 1; background: var(--surface-3); }

/* Vorschlagsliste unter Suchfeldern */
.suggest { display: flex; flex-direction: column; gap: 2px; margin-top: var(--s-1); }
.suggest:not(:empty) {
  padding: var(--s-1);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
}
.suggest-item {
  display: flex; align-items: center; gap: var(--s-2);
  min-height: 36px; padding: var(--s-1) var(--s-2);
  border: 0; border-radius: var(--r-md);
  background: transparent; color: var(--text-secondary);
  font-size: 13px; text-align: left; cursor: pointer;
}
.suggest-item:hover { background: var(--surface-3); color: var(--text-primary); }
.suggest-item svg { width: 12px; height: 12px; flex-shrink: 0; }

/* ── 44. Notizen: Gliederung, Verweise, Code ─────────────────────────────── */
.outline { display: flex; flex-direction: column; gap: 2px; }
.outline-item {
  min-height: 36px; padding: var(--s-2) var(--s-3);
  border: 0; border-radius: var(--r-md);
  background: transparent; color: var(--text-secondary);
  font-size: 13px; text-align: left; cursor: pointer;
}
.outline-item:hover { background: var(--surface-3); color: var(--text-primary); }

/* Verweise zwischen Notizen sollen sich vom Fließtext abheben — hier ist
   die Ausnahme von "Links sehen nicht wie Links aus" gerechtfertigt, weil
   sie in .prose stehen. */
.prose .wikilink {
  color: var(--accent);
  border-bottom: 1px dashed color-mix(in srgb, var(--accent) 50%, transparent);
  text-decoration: none;
}
.prose .wikilink:hover { border-bottom-style: solid; }

/* Syntaxhervorhebung — nur Abstufungen vorhandener Tokens, keine neuen Farben */
.prose pre code .tok-key { color: var(--accent); }
.prose pre code .tok-str { color: var(--success); }
.prose pre code .tok-com { color: var(--text-muted); font-style: italic; }
.prose pre code .tok-num { color: var(--warning); }
.prose pre code .tok-var { color: var(--text-primary); }

/* ── 45. Erfassung: Stapel und Diktat ─────────────────────────────────────── */
.batch-count { color: var(--text-muted); font-size: 12px; margin-bottom: var(--s-2); }
.batch-content {
  padding: var(--s-4);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--r-xl);
  color: var(--text-primary);
  font-size: 15px; line-height: 1.5;
  white-space: pre-wrap; word-break: break-word;
  max-height: 40vh; overflow-y: auto;
}
.batch-meta { display: flex; flex-wrap: wrap; gap: var(--s-2); margin-top: var(--s-3); }

/* Laufendes Diktat — nur Deckkraft, keine neue Farbe. */
#qc-dictate.is-recording { color: var(--error); }
#qc-dictate.is-recording svg { animation: puls 1.4s ease-in-out infinite; }
@keyframes puls { 0%, 100% { opacity: 1; } 50% { opacity: .35; } }
@media (prefers-reduced-motion: reduce) {
  #qc-dictate.is-recording svg { animation: none; }
}

/* ── 46. Tastaturbedienung, Auswertung, Rückgängig ───────────────────────── */

/* Hervorgehobene Zeile bei Tastaturbedienung (J/K) */
.row-card.is-cursor {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--overlay-accent);
}

/* Tastenkürzel-Übersicht */
.keys { display: flex; flex-direction: column; gap: var(--s-1); }
.keys-row { display: flex; align-items: center; gap: var(--s-3); min-height: 32px; }
.keys-row span { color: var(--text-tertiary); font-size: 13px; }
kbd {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 28px; min-height: 24px; padding: 0 var(--s-2);
  background: var(--surface-3);
  border: 1px solid var(--border-strong);
  border-bottom-width: 2px;
  border-radius: var(--r-sm);
  color: var(--text-primary);
  font-family: var(--font-mono); font-size: 11px;
  white-space: nowrap;
}

/* Verlaufsbalken der Auswertung */
.spark { display: flex; align-items: flex-end; gap: 2px; height: 120px; }
.spark-bar { flex: 1; min-width: 2px; height: 100%; display: flex; align-items: flex-end; }
.spark-bar i {
  display: block; width: 100%; min-height: 2px;
  background: var(--accent);
  border-radius: var(--r-sm) var(--r-sm) 0 0;
  opacity: .8;
}
.spark-bar:hover i { opacity: 1; }

/* Rückgängig-Knopf im Toast */
.toast-undo { min-height: 28px; padding: 0 var(--s-2); font-size: 12px; margin-left: var(--s-2); }

.grid-4 { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--s-4); }
@media (max-width: 900px) { .grid-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

/* ── 47. Offline-Streifen ─────────────────────────────────────────────────── */
.offline-bar {
  position: fixed; top: 0; left: 0; right: 0; z-index: 300;
  display: flex; align-items: center; justify-content: center; gap: var(--s-2);
  min-height: 32px; padding: var(--s-1) var(--s-4);
  background: var(--surface-3);
  border-bottom: 1px solid var(--border-strong);
  color: var(--text-secondary);
  font-size: 12px; font-weight: 500;
}
.offline-bar svg { width: 14px; height: 14px; color: var(--warning); }
body:has(.offline-bar) .app { padding-top: 32px; }

/* ── 48. Sync-Zustand und freie Zeit ─────────────────────────────────────── */
.sync-state {
  display: flex; align-items: center; gap: var(--s-2);
  padding: var(--s-2) var(--s-3); margin-bottom: var(--s-3);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  color: var(--text-tertiary);
  font-size: 12px;
}
/* `display: flex` schlägt das hidden-Attribut (beide zählen gleich viel, die
   Komponentenregel steht später). Ohne diese Zeile stand auf jeder
   Kalenderseite ein leerer Kasten mit Rahmen — 30px Höhe für nichts, immer
   dann, wenn der Abgleich in Ordnung war und es gar nichts zu melden gab. */
.sync-state[hidden] { display: none; }
.sync-state svg { width: 14px; height: 14px; flex-shrink: 0; }
.sync-state.is-warn { border-color: var(--warning); color: var(--text-secondary); }
.sync-state.is-warn svg { color: var(--warning); }

.freetime { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-2); margin-bottom: var(--s-3); }

/* ── 49. Hierarchie: Unteraufgaben und Teilprojekte ──────────────────────── */

/* Aufklapp-Pfeil in der Aufgabenzeile. Die leere Variante hält die Spalte
   frei, damit Zeilen mit und ohne Unteraufgaben bündig stehen. */
.row-expand {
  display: inline-flex; align-items: center; justify-content: center;
  width: 20px; min-height: 20px; flex-shrink: 0;
  padding: 0; border: 0; border-radius: var(--r-sm);
  background: transparent; color: var(--text-muted); cursor: pointer;
  transition: transform .15s ease, color .15s ease;
}
.row-expand:hover { color: var(--text-primary); background: var(--surface-3); }
.row-expand.is-open { transform: rotate(90deg); color: var(--accent); }
.row-expand.is-empty { cursor: default; pointer-events: none; }

/* Aufgeklappte Unteraufgaben — eingerückt und mit Führungslinie, damit die
   Zugehörigkeit auch ohne den Pfeil erkennbar bleibt. */
.subrows {
  display: flex; flex-direction: column; gap: var(--s-2);
  margin: var(--s-2) 0 var(--s-2) var(--s-6);
  padding-left: var(--s-4);
  border-left: 2px solid var(--border);
}
.subrows .row-card { background: var(--surface-2); }

/* Herkunftszeile im Dialog einer Unteraufgabe */
.parent-hint {
  display: flex; align-items: center; gap: var(--s-2); flex-wrap: wrap;
  padding: var(--s-2) var(--s-3); margin-bottom: var(--s-4);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  color: var(--text-tertiary); font-size: 13px;
}
.parent-hint svg { width: 14px; height: 14px; color: var(--text-muted); flex-shrink: 0; }

/* Unteraufgaben im Dialog sind anklickbar */
.subtask-title {
  flex: 1; min-width: 0; text-align: left;
  padding: 0; border: 0; background: none;
  color: var(--text-secondary); font-size: 13px; cursor: pointer;
}
.subtask-title:hover { color: var(--accent); }
.subtask-item.is-done .subtask-title { text-decoration: line-through; color: var(--text-muted); }

/* Teilprojekt-Karte: eingerückt und schmaler abgesetzt */
.card.is-subproject {
  border-left: 3px solid color-mix(in srgb, var(--accent) 40%, var(--border));
}

/* ── 50. Nachlese: Trefferflächen und Reiterleiste ───────────────────────── */

/* Der Aufklapp-Pfeil war optisch 20px groß — und damit auf Touch auch als
   Trefferfläche. Gleiche Lösung wie bei der Abhak-Box: ein unsichtbares
   Pseudo-Element vergrößert die Fläche, ohne die Darstellung zu ändern. */
.row-expand { position: relative; }
.row-expand::after {
  content: '';
  position: absolute;
  inset: -8px;            /* 20px + 2×8px = 36px, Maus */
}
@media (hover: none) {
  .row-expand::after { inset: -12px; }   /* 20px + 2×12px = 44px, Touch */
}

/* Mit dem vierten Reiter passt die Leiste am Handy nicht mehr in eine Zeile.
   Sie scrollt zwar, aber ohne Hinweis sieht man den letzten Eintrag nicht.
   Etwas enger gesetzt passen alle vier hinein. */
@media (max-width: 480px) {
  .tabs .tab { padding-left: var(--s-2); padding-right: var(--s-2); font-size: 12px; }
  .tabs .tab svg { width: 14px; height: 14px; }
}

/* ── 31. Auswahldialog ─────────────────────────────────────────────────────
   Eine Zeilenkarte, die selbst der Knopf ist. Ersetzt die nativen
   prompt()-Kästen, mit denen Priorität und Projekt bei Sammelaktionen über
   eine nummerierte Textliste abgefragt wurden. */
.row-card-choice {
  width: 100%;
  text-align: left;
  align-items: center;
  cursor: pointer;
}
.row-card-choice:hover,
.row-card-choice:focus-visible {
  border-color: var(--accent);
  background: var(--overlay-accent);
}
.row-card-choice > svg { color: var(--text-muted); flex-shrink: 0; }
/* Im Knopf stehen nur Inline-Elemente (Knöpfe dürfen keine Blöcke enthalten),
   der Textblock braucht die Blockdarstellung deshalb ausdrücklich. */
.row-card-choice .row-card-main { display: block; }

/* ── 32. Farbpunkt in Zeilenkarten ─────────────────────────────────────────
   Kalenderfarbe, Projektfarbe, Prioritätsstufe — dieselbe Form, bisher an
   drei Stellen getrennt gebaut (einmal als Klasse, zweimal inline über eine
   umgewidmete `.badge-dot`). Die 6px sind kein Abstand aus der Skala, sondern
   ein optischer Versatz: Er setzt den 8px-Punkt auf die Mitte der ersten
   Textzeile (17px hoch). */
.row-dot {
  width: 8px; height: 8px; border-radius: 50%;
  flex-shrink: 0; background: var(--text-muted);
}
.row-card > .row-dot { margin-top: 6px; }
/* Der Auswahldialog richtet mittig aus — dort ist kein Versatz nötig. */
.row-card-choice > .row-dot { margin-top: 0; }

/* ── 33. Trefferfläche der Abschnittslinks ─────────────────────────────────
   „Alle ›" und „Kalender ›" in `.section-head` sind 20px hoch und lagen damit
   unter der Mindestgröße für Interaktives (36px Maus, 44px Touch) — am Handy
   kaum zu treffen. Die Fläche wächst unsichtbar über ein ::after, die Optik
   bleibt unverändert. Gleiches Vorgehen wie bei `.check` und `.row-expand`. */
.section-head a,
.back-link { position: relative; }
.section-head a::after,
.back-link::after {
  content: ""; position: absolute; inset: -8px -4px;
}
@media (hover: none) {
  .section-head a::after,
  .back-link::after { inset: -12px -8px; }   /* 20 + 2×12 = 44px */
}

/* ── 33b. Lange Zeichenketten in Zeilenkarten ──────────────────────────────
   Kennungen, Token und Adressen haben keine Trennstellen. In einem
   Flex-Element verhindert `min-width: auto`, dass es unter seine
   Inhaltsbreite schrumpft — die ganze Seite scrollt dann waagerecht.
   Gemessen auf 500px: Die Google-Kalender-Kennung in den Einstellungen ragte
   216px über den rechten Rand hinaus und schob die Seite mit. */
.row-card-meta .mono {
  min-width: 0;
  overflow-wrap: anywhere;
}

/* ── 34. Auswahl in Kartenlisten ───────────────────────────────────────────
   Notizen und Projekte stehen als `.card` in einem Raster, nicht als
   `.row-card` in einer Liste — die Auswahlregeln aus Abschnitt 22 greifen
   dort nicht. Verhalten bleibt gleich: erscheint beim Hovern, bleibt sichtbar
   solange ausgewählt. */
.card:hover .check-select,
.card.is-selected .check-select { opacity: 1; }
.card.is-selected {
  border-color: var(--accent);
  background: var(--overlay-accent);
}

/* ── 35. Anklickbare Schlagwort-Abzeichen ──────────────────────────────────
   Schlagwörter in Aufgaben- und Lesezeichenzeilen führen zur Schlagwort-
   Ansicht. Als Abzeichen sind sie nur 26px hoch und lagen damit unter der
   Mindestgröße für Interaktives (36px Maus, 44px Touch). Die Fläche wächst
   unsichtbar — gleiches Vorgehen wie bei .section-head a und .back-link. */
a.badge { position: relative; }
a.badge::after { content: ""; position: absolute; inset: -5px -4px; }
@media (hover: none) {
  a.badge::after { inset: -9px -8px; }   /* 26 + 2×9 = 44px */
}

/* ── 51. Geteilte Akquise-Liste (akquise.php) ──────────────────────────────
   (Nummer 51, nicht 36: Die Abschnitte 31–35 gibt es in dieser Datei zweimal —
   der zweite Block wurde beim Nachlese-Durchgang neu gezählt. 51 schließt
   eindeutig an die höchste vergebene Nummer an.)
   Die öffentliche Nur-Lese-Seite hat keine Seitenleiste und keine Topbar —
   sie besteht aus einer Karte auf leerem Grund. Bewusst dieselben Tokens wie
   die App: Wer den Link bekommt, soll sehen, dass beides zusammengehört.
   Der Tabellenrahmen kommt aus .table-wrap (Abschnitt 12), hier steht nur
   das Drumherum. */
body.share-page { background: var(--surface-2); }
.share-wrap {
  max-width: 900px;
  margin: 0 auto;
  padding: var(--s-8) var(--s-5) var(--s-16);
}
.share-legend { display: flex; flex-wrap: wrap; gap: var(--s-2); }
.share-name { color: var(--text-primary); font-weight: 500; }

@media (max-width: 767px) {
  .share-wrap { padding: var(--s-6) var(--s-4) var(--s-12); }
}

/* ── 52. iPhone: Sicherheitsabstände oben und an den Seiten ────────────────
   Die App läuft auf dem iPhone vom Home-Bildschirm als eigenständige Web-App.
   Zusammen mit `viewport-fit=cover` und `apple-mobile-web-app-status-bar-style:
   black-translucent` beginnt der Inhalt dann bei y=0 — also **unter** der
   Statusleiste und der Dynamic Island.

   Bisher standen im ganzen Projekt nur die unteren Abstände (Home-Indikator).
   Topbar, Schublade und hohe Dialoge lagen dadurch teilweise hinter der Insel.
   Die Seitenabstände zählen im Querformat: dort liegt die Insel links.

   Auf allem außer iOS sind die env()-Werte 0, die Regeln ändern dort also
   nichts. Sie stehen bewusst hier hinten statt in der übernommenen
   Systemdatei. */
.topbar { padding-top: calc(var(--s-3) + env(safe-area-inset-top)); }

/* Der Dialog ist mittig, stößt aber bei viel Inhalt oben an. Beide Werte
   müssen mitwandern: der Abstand des Rahmens und die Höhengrenze darin. */
.modal {
  padding-top: calc(var(--s-4) + env(safe-area-inset-top));
  padding-bottom: calc(var(--s-4) + env(safe-area-inset-bottom));
}
.modal-panel {
  max-height: calc(100vh - 32px - env(safe-area-inset-top) - env(safe-area-inset-bottom));
}

@media (max-width: 767px) {
  /* Die Schublade läuft über die volle Höhe — ihr Markenblock stünde sonst
     hinter der Insel. */
  .sidebar { padding-top: env(safe-area-inset-top); }

  .content {
    padding-left:  calc(var(--s-4) + env(safe-area-inset-left));
    padding-right: calc(var(--s-4) + env(safe-area-inset-right));
  }
  .bottom-nav {
    padding-left:  env(safe-area-inset-left);
    padding-right: env(safe-area-inset-right);
  }
  .fab, .fab-search { right: calc(var(--s-4) + env(safe-area-inset-right)); }
  .toasts { bottom: calc(var(--s-4) + env(safe-area-inset-bottom)); }
}

/* ── 53. Kalender auf schmalen Schirmen ────────────────────────────────────
   Sieben Spalten lassen auf einem Handy rund 45 Pixel je Tag. Ein
   Termintitel passt da nicht hinein — heraus kamen bunte Schnipsel mit drei
   Buchstaben, aus denen sich nichts ablesen ließ, und ein Tipp auf einen Tag
   öffnete auch noch den Anlegen-Dialog statt den Tag zu zeigen.

   Deshalb gibt es hier andere Darstellungen, nicht kleinere:
   die Agenda als Liste, den Monat als Auswahlraster mit Punkten und
   darunter die Tagesliste. Alles aus den vorhandenen Tokens. */

/* ---------- Werkzeugleiste ---------- */
.cal-nav { display: flex; align-items: center; gap: var(--s-2); margin-right: auto; min-width: 0; }
.cal-nav .cal-label { margin-right: 0; }
.cal-views { flex: none; }

/* ---------- Agenda: die Liste nach Tagen ---------- */
.cal-agenda { display: flex; flex-direction: column; gap: var(--s-6); }
.cal-agenda-tag { display: flex; flex-direction: column; gap: var(--s-2); }
.cal-agenda-kopf {
  display: flex; align-items: baseline; gap: var(--s-2);
  padding-bottom: var(--s-2);
  border-bottom: 1px solid var(--border);
}
.cal-agenda-dow {
  font-size: 11px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase;
  color: var(--text-muted);
}
.cal-agenda-zahl { font-size: 16px; font-weight: 600; color: var(--text-primary); font-variant-numeric: tabular-nums; }
.cal-agenda-monat { font-size: 13px; color: var(--text-tertiary); }
.cal-agenda-anzahl { margin-left: auto; font-size: 12px; color: var(--text-muted); font-variant-numeric: tabular-nums; }
.cal-agenda-tag.is-today .cal-agenda-zahl,
.cal-agenda-tag.is-today .cal-agenda-dow { color: var(--accent); }

.cal-agenda-liste { display: flex; flex-direction: column; gap: var(--s-2); }
.cal-agenda-evt {
  display: flex; align-items: flex-start; gap: var(--s-3);
  min-height: 44px; padding: var(--s-2) var(--s-3);
  background: var(--surface-1);
  border: 1px solid var(--border);
  border-left: 3px solid var(--evt, var(--accent));
  border-radius: var(--r-lg);
  cursor: pointer;
  transition: background .15s ease;
}
.cal-agenda-evt:hover { background: var(--surface-3); }
.cal-agenda-zeit {
  flex: none; width: 46px; padding-top: 1px;
  display: flex; flex-direction: column;
  font-family: var(--font-mono); font-size: 12px; line-height: 16px;
  color: var(--text-secondary); font-variant-numeric: tabular-nums;
}
.cal-agenda-bis { color: var(--text-muted); }
/* Ganztägige tragen ein Schildchen statt einer Uhrzeit. In eine Spalte, die
   auf „09:00" ausgelegt ist, passt das Wort nicht — es brach dort mitten
   durch. Sie stehen ohnehin zuoberst im Tag. */
.cal-agenda-ganz {
  flex: none; align-self: flex-start;
  padding: 2px var(--s-2);
  border-radius: var(--r-sm);
  background: var(--surface-3);
  color: var(--text-tertiary);
  font-size: 11px; line-height: 15px; white-space: nowrap;
}
.cal-agenda-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.cal-agenda-titel { font-size: 13px; line-height: 18px; font-weight: 500; color: var(--text-primary); overflow-wrap: anywhere; }
.cal-agenda-meta  { font-size: 12px; line-height: 16px; color: var(--text-muted); overflow-wrap: anywhere; }

.cal-agenda-leer {
  padding: var(--s-8) var(--s-4); text-align: center;
  border: 1px dashed var(--border); border-radius: var(--r-xl);
}
.cal-agenda-leer-titel { font-size: 14px; font-weight: 600; color: var(--text-secondary); }
.cal-agenda-leer-text  { font-size: 13px; color: var(--text-muted); margin-top: var(--s-1); }

/* ---------- Monat als Auswahlraster ---------- */
.cal-mini {
  border: 1px solid var(--border); border-radius: var(--r-xl);
  background: var(--surface-1); overflow: hidden;
}
.cal-mini-week { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); border-bottom: 1px solid var(--border); }
.cal-mini-head {
  padding: var(--s-2) 0; text-align: center;
  font-size: 11px; font-weight: 600; letter-spacing: .04em;
  color: var(--text-muted);
}
.cal-mini-head.weekend { color: var(--text-tertiary); }
.cal-mini-grid { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); }
.cal-mini-day {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--s-1);
  min-height: 48px; padding: var(--s-2) 0;
  background: transparent; border: 0; border-radius: 0;
  color: var(--text-secondary); font: inherit; cursor: pointer;
  transition: background .15s ease;
}
.cal-mini-day.weekend:not(.is-selected) { background: rgba(255, 255, 255, .015); }
.cal-mini-day.other .cal-mini-num { color: var(--text-muted); opacity: .55; }
.cal-mini-day.today .cal-mini-num { color: var(--accent); font-weight: 600; }
.cal-mini-day.is-selected { background: var(--overlay-accent); box-shadow: inset 0 0 0 1px var(--accent); }
.cal-mini-num { font-size: 14px; line-height: 18px; font-variant-numeric: tabular-nums; }
/* Die Punktzeile behält ihre Höhe auch ohne Punkte — sonst springen die
   Zeilen des Rasters unterschiedlich hoch, je nachdem wo etwas los ist. */
.cal-mini-dots { display: flex; align-items: center; gap: 3px; height: 5px; }
.cal-mini-dot { width: 5px; height: 5px; border-radius: 50%; }

/* ---------- Tagesliste unter dem Raster ---------- */
.cal-tagliste-kopf { display: flex; align-items: center; gap: var(--s-2); margin: var(--s-6) 0 var(--s-3); }
.cal-tagliste-kopf h3 { font-size: 14px; line-height: 20px; margin: 0; flex: 1; min-width: 0; }

@media (max-width: 767px) {
  /* Die Leiste stand vorher als umbrechende Reihe da und brauchte drei
     Zeilen in wechselnder Anordnung. Jetzt drei feste Zeilen: blättern,
     wählen, umschalten. */
  .cal-toolbar { flex-direction: column; align-items: stretch; gap: var(--s-2); }
  .cal-nav { width: 100%; margin-right: 0; }
  .cal-nav .cal-label {
    flex: 1; min-width: 0; text-align: center;
    font-size: 16px; line-height: 20px;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .cal-views { width: 100%; }
  /* Die Systemregel „44px auf Touch" galt bisher nur für die Segmentleiste
     der Bereichsumschaltung. Die Ansichtsknöpfe und die Blätterpfeile des
     Kalenders standen auf 36px — gerade die trifft man am häufigsten. */
  .cal-views button { min-height: 44px; }
  .cal-nav .btn { min-height: 44px; }
  .cal-nav .btn-icon { width: 44px; }
  .cal-tasks-toggle { min-height: 44px; }
  .cal-tagliste-kopf .btn { min-height: 44px; }

  /* Die Tagesansicht bekommt einen schmaleren Zeitstreifen und etwas
     niedrigere Stunden — bei 15 Zeilen sind das über 100 Pixel Gewinn. */
  .cal-day-view { --cal-gutter: 44px; }
  .cal-day-hours { grid-auto-rows: 52px; }

  /* Sich überschneidende Termine tragen hier keinen Titel (siehe
     calendar.js). Damit sie trotzdem als Termine erkennbar bleiben, sind sie
     in ihrer Farbe getönt — das Raster liest sich dann als Gestalt des
     Tages, und die Liste darunter nennt die Namen. */
  .cal-day-evt.is-stumm .cal-day-evt-title,
  .cal-day-evt.is-stumm .cal-day-evt-loc { display: none; }
  .cal-day-evt.is-stumm {
    background: color-mix(in srgb, var(--evt, #8B93FF) 24%, var(--surface-3));
  }
  .cal-day-evt.is-stumm .cal-day-evt-time { color: var(--text-secondary); }

  /* Die Liste unter der Zeitleiste. */
  .cal-tagband { margin-top: var(--s-5); }

  .cal-agenda-evt { padding: var(--s-3); }
}

/* ── 54. Hardware-Inventar ─────────────────────────────────────────────────
   Die Geräteliste sah aus wie jede andere Liste im Projekt: gleiche
   Zeilenkarten, gleiche Gewichtung, und was in einem Rechner steckt, stand
   hinter einem Klick. Für ein Inventar ist das genau falsch herum — man
   führt es, um zu *sehen*, was man hat.

   Deshalb hier Karten statt Zeilen: Symbol nach Art, Name, und das
   Innenleben direkt darunter. Alles aus den Tokens; die einzige Farbe je
   Karte ist der Status. */

.hw-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
  gap: var(--s-4);
}

.hw-card {
  display: flex; flex-direction: column;
  background: var(--surface-1);
  border: 1px solid var(--border);
  border-radius: var(--r-xl);
  box-shadow: var(--shadow-1);
  overflow: hidden;
  transition: border-color .15s ease;
}
.hw-card:hover { border-color: var(--border-strong); }
/* Abgegeben, defekt, Ersatz: bleibt lesbar, tritt aber zurück. */
.hw-card.is-ruhend { opacity: .72; }
.hw-card.is-ruhend:hover { opacity: 1; }
.hw-card.is-selected { border-color: var(--accent); background: var(--overlay-accent); }

.hw-kopf {
  display: flex; align-items: center; gap: var(--s-3);
  padding: var(--s-4);
  border-bottom: 1px solid var(--border);
}
/* Die Kachel sagt **was** es ist, nicht **wie es steht**. Zuerst trug sie die
   Statusfarbe — dann war das halbe Raster grün, weil fast alles im Einsatz
   ist, und die Farbe sagte nichts mehr. Den Status trägt der Punkt rechts;
   dort fällt Rot auch auf. Gleiche Machart wie das Markenzeichen in der
   Seitenleiste. */
.hw-icon {
  flex: none;
  display: grid; place-items: center;
  width: 40px; height: 40px;
  border-radius: var(--r-lg);
  background: var(--overlay-accent);
  color: var(--accent);
}
.hw-icon svg { width: 20px; height: 20px; }
.hw-titel { flex: 1; min-width: 0; }
.hw-titel h3 {
  margin: 0; font-size: 14px; line-height: 19px; font-weight: 600;
  color: var(--text-primary); overflow-wrap: anywhere;
}
.hw-unter { font-size: 12px; line-height: 16px; color: var(--text-muted); overflow-wrap: anywhere; }
.hw-status {
  flex: none; display: flex; align-items: center; gap: var(--s-2);
  font-size: 11px; color: var(--text-tertiary); white-space: nowrap;
}

/* Das Innenleben — je Zeile Art links, Bezeichnung rechts. Die Artspalte
   hat feste Breite, damit die Bezeichnungen untereinander fluchten und
   die Karte als Datenblatt lesbar wird. */
.hw-inhalt { padding: var(--s-2) var(--s-4); display: flex; flex-direction: column; }
.hw-teil {
  display: flex; align-items: baseline; gap: var(--s-3);
  padding: var(--s-2) 0;
  border-bottom: 1px solid color-mix(in srgb, var(--border) 55%, transparent);
}
.hw-teil:last-child { border-bottom: none; }
.hw-teil-art {
  flex: none; width: 92px;
  display: flex; align-items: center; gap: var(--s-2);
  font-size: 11px; color: var(--text-muted);
}
.hw-teil-art svg { width: 13px; height: 13px; flex-shrink: 0; }
.hw-teil-text {
  flex: 1; min-width: 0;
  font-size: 12px; line-height: 17px; color: var(--text-secondary);
  overflow-wrap: anywhere;
}

.hw-leer { padding: var(--s-4); font-size: 12px; color: var(--text-muted); }

.hw-fuss {
  display: flex; align-items: center; gap: var(--s-2);
  margin-top: auto;
  padding: var(--s-3) var(--s-4);
  border-top: 1px solid var(--border);
  background: var(--surface-2);
}
.hw-fuss-info { flex: 1; min-width: 0; font-size: 11px; color: var(--text-muted); overflow-wrap: anywhere; }

/* Auswahlkästchen wie in Kartenlisten (Abschnitt 34) — die Regeln aus 22
   greifen nur für `.row-card`. */
.hw-card .check-select { opacity: .45; }
.hw-card:hover .check-select,
.hw-card.is-selected .check-select { opacity: 1; }

/* ---------- Lager ----------
   Die Lagerkachel ist **dieselbe Karte** wie im Geräteraum: Kopf mit Symbol
   und Namen, Datenblatt darunter, Fußleiste mit den Knöpfen. Sie erbt dazu
   `.hw-card`, `.hw-kopf`, `.hw-inhalt`, `.hw-teil` und `.hw-fuss` — neu ist
   hier nur, was es im Geräteraum nicht gibt: die Abzeichenzeile und die
   Stückzahl.

   Vorher war die Kachel eine lose Flex-Zeile mit mittig zentriertem Inhalt.
   In einer Reihe gleich hoher Kacheln saßen Titel, Abzeichen und Knöpfe
   dadurch in jeder Karte auf einer anderen Höhe — derselbe Fehler wie in
   Version 104, nur im anderen Raum. */
/* Nur hier, nicht im Geräteraum: Dort ist die Unterzeile einzeilig, und ein
   oben ausgerichtetes Symbol stünde neben ihrer Mitte. */
.hw-fach .hw-kopf { align-items: flex-start; }
/* Die Abzeichen sind die Identität eines Lagerteils („RAM · 8 GB") und
   stehen deshalb unter dem Namen, wo bei einem Gerät die Unterzeile steht. */
.hw-marken {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: var(--s-1); margin-top: var(--s-1);
}
/* Die Stückzahl ersetzt nicht mehr das Symbol — sonst verlor man die Art
   ausgerechnet dort, wo mehrere Teile liegen. Sie steht rechts im Kopf, wo
   bei einem Gerät der Status steht. */
.hw-menge {
  flex: none; margin-left: auto;
  font-family: var(--font-mono); font-size: 14px; font-weight: 600;
  color: var(--text-primary); white-space: nowrap;
}
/* Eine lange Notiz zog vorher die ganze Reihe auf (sechs Zeilen bei der
   DDR5). Zwei Zeilen, der Rest im Titel-Attribut und im Dialog. */
.hw-teil-text.is-notiz {
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;
  overflow: hidden;
}
.hw-fuss-spacer { flex: 1 1 auto; }

@media (max-width: 767px) {
  .hw-grid { grid-template-columns: minmax(0, 1fr); }
  .hw-teil-art { width: 76px; }
  .hw-fuss .btn { min-height: 44px; }
  .hw-fuss .btn-icon { width: 44px; }
}

/* ── 54b. Inventar dichter ─────────────────────────────────────────────────
   Vom Owner gemeldet: „muss kompakter". Vier Geräte füllten zwei Bildschirme.
   Zwei Ursachen, beide behoben:

   1. Jede Gruppe bekam ihr eigenes Raster. Bei einem Gerät je Art stand eine
      schmale Karte in einer sonst leeren Zeile. Die Überschrift ist jetzt ein
      Element **im** Raster über die volle Breite, und die Vorgabe sortiert
      nach Name statt nach Art — dieselben vier Geräte füllen damit eine Zeile.
   2. Die Karte trug Kopf, Inhalt **und** eine Fußleiste mit eigenem Knopf.
      Die Fußleiste ist weg: Öffnen und Löschen sitzen als Symbolknöpfe im
      Kopf, der Status als Punkt vor der Unterzeile. */

.hw-gruppe {
  grid-column: 1 / -1;
  display: flex; align-items: center; gap: var(--s-2);
  margin: var(--s-3) 0 0;
  font-size: 13px; font-weight: 600; color: var(--text-secondary);
}
.hw-gruppe:first-child { margin-top: 0; }
.hw-gruppe svg { width: 14px; height: 14px; color: var(--text-muted); }

.hw-kopf { padding: var(--s-3); gap: var(--s-2); }
.hw-icon { width: 32px; height: 32px; border-radius: var(--r-md); }
.hw-icon svg { width: 18px; height: 18px; }
.hw-titel h3 { font-size: 13px; line-height: 18px; }
/* Der Statuspunkt sitzt jetzt in der Unterzeile — die eigene Spalte dafür
   entfällt und mit ihr eine Menge Breite. */
.hw-unter { display: flex; align-items: center; gap: var(--s-2); }
.hw-unter .row-dot { flex: none; }
.hw-kopf .dnd-handle,
.hw-kopf .btn-icon { flex: none; }

.hw-inhalt { padding: var(--s-1) var(--s-3) var(--s-2); }
.hw-teil { padding: 3px 0; gap: var(--s-2); }
.hw-teil-art { width: 78px; }
.hw-teil-text { line-height: 16px; }
.hw-leer { padding: var(--s-2) var(--s-3) var(--s-3); }

@media (max-width: 767px) {
  .hw-teil-art { width: 68px; }
  /* Auf Touch bleiben die Symbolknöpfe im Kopf greifbar. */
  .hw-kopf .btn-icon { min-height: 44px; width: 44px; }
}

/* ── 54c. Karten einheitlich ───────────────────────────────────────────────
   Vom Owner gemeldet: „die Container sollen einheitlicher aussehen".

   Ursache war der Kopf. Name und Unterzeile durften umbrechen, also war der
   Kopf mal eine, mal drei Zeilen hoch — und damit lagen Symbol, Knöpfe und
   die Trennlinie darunter in **jeder** Karte auf einer anderen Höhe. Eine
   Reihe aus vier Karten sah dadurch aus wie versehentlich verrutscht.

   Beide Zeilen sind jetzt einzeilig mit Auslassungspunkten; der ganze Text
   steht im Titel-Attribut und im Dialog. Damit ist jeder Kopf exakt gleich
   hoch, und die Karten einer Reihe fluchten wieder. */
.hw-titel { min-width: 0; }
.hw-titel h3 { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Der Punkt darf nicht mitschrumpfen, wenn der Text gekürzt wird. */
.hw-unter { display: flex; align-items: center; gap: var(--s-2); min-width: 0; white-space: nowrap; }
.hw-unter .row-dot { flex: none; }
.hw-unter > span:not(.row-dot) { overflow: hidden; text-overflow: ellipsis; }

/* Gleiche Höhe je Reihe: Der Inhaltsbereich wächst in den freien Platz,
   statt die Karte kurz enden zu lassen. Vier Karten nebeneinander mit vier
   verschiedenen Unterkanten waren genau das, was unruhig wirkte. */
.hw-inhalt, .hw-leer { flex: 1 1 auto; }

/* ── 54d. Lager-Filter ─────────────────────────────────────────────────────
   Die Abzeichen auf einer Lagerkachel — Art und Größe — sind zugleich die
   Filter darüber. Beide Reihen stehen in **einer** Chip-Zeile; der Trenner
   macht sichtbar, dass es zwei verschiedene Fragen sind („was ist es" und
   „wie groß"), die sich kombinieren lassen. */
.hw-filter-trenner {
  flex: none; align-self: stretch;
  width: 1px; margin: 0 var(--s-2);
  background: var(--border-strong);
}
/* Symbol im Abzeichen: gleiche Größe wie der Text, damit die Zeile nicht
   auseinanderläuft. */
.hw-marken .badge svg,
.row-card-meta .badge svg { width: 12px; height: 12px; flex-shrink: 0; }
