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

:root {
  color-scheme: dark;
  /* Brand: Aperture-Konzept (siehe BRAND.md). Gold/Schwarz/Weiss.
     --accent = Brand-Gold #C9A227 (1:1 aus Brand-Guide).
     --bg = Brand-Schwarz #111111.
     --accent2 ist ein technischer Alias auf --danger: viele
     bestehende JSX-Stellen schreiben var(--accent2) fuer Status/Fehler-
     Hover. Brand-Guide erlaubt nur Gold/Schwarz/Weiss als Markenfarben
     — der frueher hier verwendete Burgunder-Ton ist raus, fuer Status
     greift die semantische Danger-Farbe. */
  --bg: #111111;
  --surface: #181818;
  --surface2: #1f1f1f;
  --border: rgba(255,255,255,0.07);
  --accent: #C9A227;
  --accent2: var(--danger);
  --text: #f0f0f0;
  --muted: #9a9aa2;
  --success: #4ade80;
  /* Semantische Status-Farben — damit Module nicht jeweils eigene Hex-Werte
     hartkodieren (das unterliefe Hell-/Dunkel-Modus). */
  --warning: #f59e0b;
  --danger: #ef4444;
  --info: #60a5fa;
  --purple: #a78bfa;
  /* ── Design-Tokens (Linear/Vercel + Apple-Materials) — Farbpalette fix ──
     Glass = transluzente Fläche + Blur + Sättigungs-Boost + feiner Rahmen.
     Apple-typisch: weiche, größere Radien, oberer Licht-Glanz an der Kante,
     sanftes Spring-Easing. Alles zentral über Tokens. */
  --radius: 14px;
  --radius-lg: 18px;
  --radius-sm: 10px;
  --radius-xs: 6px;   /* Pillen, Badges, Mini-Boxen */
  --glass-bg: rgba(255,255,255,0.025);
  --glass-bg-hover: rgba(255,255,255,0.045);
  --glass-border: rgba(255,255,255,0.09);
  --glass-border-strong: rgba(255,255,255,0.14);
  /* Apple-Material: kräftiger Blur + Sättigung hebt den Hintergrund an. */
  --blur: blur(20px) saturate(180%);
  --blur-strong: blur(28px) saturate(190%);
  /* Oberer Licht-Glanz an der Glaskante (visionOS-Anmutung). */
  --glass-highlight: inset 0 1px 0 rgba(255,255,255,0.06);
  --shadow-sm: 0 1px 2px rgba(0,0,0,0.4);
  --shadow-md: 0 2px 8px rgba(0,0,0,0.28), 0 16px 40px rgba(0,0,0,0.32);
  --shadow-lg: 0 32px 80px rgba(0,0,0,0.6);
  /* Sanftes Spring-Easing — Apple-artiges Ein-/Ausschwingen. */
  --ease: cubic-bezier(0.32, 0.72, 0, 1);
  /* Gradient-Text: subtiler Hell-Grau-Verlauf (Linear-Stil) bzw. Akzent. */
  --grad-text: linear-gradient(135deg, #ffffff 0%, #9a9aa2 100%);
  --grad-accent: linear-gradient(120deg, var(--accent) 0%, var(--accent-hover) 100%);
  /* ─── Akzent-Stufen (konsolidiert) ────────────────────────────────────
     16+ JSX-Stellen tippten frueher `color-mix(in srgb, var(--accent)
     X%, transparent)` inline mit leicht variierenden Prozent-Werten
     (5/6/7/8/10/12/25/30/35). Konsolidiert auf vier Stufen — Stellen
     die innerhalb ±2% liegen, werden hier auf den Bucket gezogen.
       --accent-subtle        ~ 8% — Hinweis-/Card-Hintergrund
       --accent-soft          ~12% — Badge-Hintergrund, intensiver Hover
       --accent-border        ~30% — Standard-Border auf Akzent-Cards
       --accent-border-strong ~45% — emphasized Border (Pflicht-Hinweise)
     Dazu Status-Tokens fuer --danger im selben Schema. */
  --accent-subtle:        var(--accent-subtle);
  --accent-soft:          var(--accent-soft);
  --accent-border:        var(--accent-border);
  --accent-border-strong: var(--accent-border-strong);
  --danger-subtle:        var(--danger-subtle);
  --danger-soft:          var(--danger-soft);
  --danger-border:        var(--danger-border);
  --danger-border-strong: var(--danger-border-strong);
  /* Theme-abhaengige Zusatz-Tokens — damit der Hell-Modus alles ueber
     einen einzigen Override-Block steuern kann. */
  --accent-fg: #111111;                /* Text auf Akzent-Flaechen (Buttons) — Brand-Schwarz */
  --accent-hover: #b08b1f;             /* btn-primary Hover — leicht dunkler Brand-Gold */
  /* Mode-neutrale Overlay-Tokens: gelten in BEIDEN Themen identisch, weil
     der Untergrund nicht der App-Hintergrund ist sondern ein Bild, Video
     oder eine User-gewaehlte Farbe (cine.welcome Mood-Kachel, Lightbox).
     Token-Namen explizit „overlay" — damit klar ist, dass keine Theme-
     Anpassung erforderlich ist. */
  --overlay-text: rgba(255,255,255,0.92);
  --overlay-text-muted: rgba(255,255,255,0.7);
  --overlay-shadow: 0 1px 2px rgba(0,0,0,0.7);
  --overlay-scrim-top: linear-gradient(180deg, rgba(0,0,0,0.55), transparent);
  --overlay-scrim-bottom: linear-gradient(0deg, rgba(0,0,0,0.6), transparent);
  --overlay-bg: rgba(0,0,0,0.92);
  --overlay-border: rgba(255,255,255,0.3);
  /* Crop-Auswahl (cine.ad-Focal-Point): leicht halbtransparenter Mantel +
     heller Rahmen um die Auswahl. Eigene Tokens, weil sich die Intensitaet
     vom Overlay-Modal-Hintergrund (-bg/-border) unterscheidet. */
  --crop-overlay: rgba(0,0,0,0.55);
  --crop-handle: rgba(255,255,255,0.9);
  /* Disabled-Text — fuer „letzter aktiver Standort kann nicht deaktiviert
     werden"-Labels und aehnliche grayed-out Faelle. */
  --text-disabled: #666;
  /* Letterbox-Rahmen fuer Bild-/Video-Container (Aspect-Ratio-Boxen).
     Dunkler Tone im Dark-Modus, im Hell-Modus per Light-Override. */
  --media-frame: rgba(0,0,0,0.3);
  --input-bg: rgba(255,255,255,0.02);  /* Eingabefelder */
  --input-bg-disabled: rgba(255,255,255,0.015);
  /* Welle-13-Audit: Placeholder dient vielerorts faktisch als Label
     (Suchfelder). Vorher 0.45 -> ~3.4:1 Kontrast — unter AA. */
  --placeholder: rgba(255,255,255,0.65);
  --hover-bg: rgba(255,255,255,0.04);  /* Nav-/Listen-Hover */
  --row-hover: rgba(255,255,255,0.025);

  /* ─── Z-Index-Schichten (High-Tier) ──────────────────────────────────
     Zentralisiert fuer alles, was UEBER der Sidebar (z:100) liegt. Die
     kleinen kontextuellen Werte (Background:0, Inhalt:1, sticky-Header:30,
     Mobile-Sidebar:95, Desktop-Sidebar:100) bleiben inline — sie haengen
     so eng an ihrem Layout, dass ein Token sie nur verschleiern wuerde.
       --z-sticky-banner   Update-/Offline-Banner ueber dem Header
       --z-impersonate     Impersonation-Banner (eine Stufe ueber regulaeren)
       --z-toast           Toaster (kurzlebige Benachrichtigungen)
       --z-modal           Modal-Backdrop + -Card (Bill-/Stammdaten-Dialoge)
       --z-modal-front     Modal das ueber einem anderen Modal liegt
       --z-overlay         Vollbild-Overlays (Lightbox, Bild-Vorschau)
       --z-drag            laufendes Column-Resize / Drag-Cursor
       --z-skip-link       Accessibility-Skip-Link, muss alles ueberlagern */
  --z-dropdown: 100;
  --z-marquee: 150;          /* Marquee-Auswahl-Indikator: zwischen Dropdown und Sticky-Banner */
  --z-sticky-banner: 200;
  --z-impersonate: 201;
  --z-toast: 300;
  --z-modal: 310;
  --z-modal-front: 320;
  --z-overlay: 4000;
  --z-drag: 9999;
  --z-skip-link: 10000;

  /* ─── Typografie-Stufen ──────────────────────────────────────────────
     Vier Schriftgroessen fuer Modul-UI — statt frei gewuerfelter
     Inline-fontSize-Werte. Nutzung ueber die Hilfsklassen .t-xs … .t-lg
     (unter den .badge-Regeln) oder direkt als var(). */
  --text-xs: 10px;  /* Meta, Zeitstempel, Pillen */
  --text-sm: 12px;  /* Tabellen-Sekundaertext, Hinweise */
  --text-md: 13px;  /* Standard-Body in Modulen */
  --text-lg: 15px;  /* betonte Zeilen */
  --text-xl: 18px;  /* Untertitel, Hero-Sublabels */
  --text-2xl: 22px; /* Kachel-Hero-Werte (z.B. KPI-Kacheln) */
  --text-3xl: 30px; /* Page-Hero (gross, sparsam) */

  /* ─── Spacing-Skala ──────────────────────────────────────────────────
     Verbindliche Skala fuer padding/margin/gap. Inline-Pixel-Literale
     wie 'padding: 8px 10px' sind ab sofort untersagt — siehe DESIGN.md
     „Spacing-Konvention". Toleranz +/-1 px gilt als gleicher Bucket;
     d.h. 7px und 9px werden auf den naechstliegenden Token gerundet,
     niemand sieht den Unterschied.
     Im JSX-Inline-Style: style={{padding: 'var(--space-4) var(--space-5)'}}
     oder besser eine Hilfsklasse aus dem .p-* / .g-* / .m-*-Set unten. */
  --space-1: 2px;
  --space-2: 4px;
  --space-3: 6px;
  --space-4: 8px;
  --space-5: 10px;
  --space-6: 12px;
  --space-7: 14px;
  --space-8: 16px;
  --space-9: 20px;  /* feinere Stufe oberhalb von 16 — fuer 18-px-Stellen auf 20 gesnapt */
  --space-10: 24px; /* Hero-Padding — EmptyState, NotificationPanel, SFA-Empty etc. */

  /* ─── Semantische Layout-Konstanten ───────────────────────────────────
     Domain-Konzepte, die nicht in die generische --space-Skala passen.
     Wer einen neuen anlegen will: lieber semantisch benennen als die
     Allowlist im Style-Tokens-Guard fuettern. */
  --empty-padding-y: 36px;  /* Vertikales Hero-Padding leerer Zustaende */
  --tree-indent: 50px;      /* Indent pro Tree-Verschachtelungsebene */

  /* ─── Transition-Dauern ─────────────────────────────────────────────
     Drei Geschwindigkeiten — statt frei gewuerfelter 0.1s/0.12s/0.15s/0.3s
     verstreut im Code. Kombinieren mit var(--ease). */
  --duration-fast: 100ms;   /* schnell — Progress, Drag */
  --duration-base: 150ms;   /* Standard — Hover, Border, Opacity */
  --duration-slow: 300ms;   /* langsam — Layout/Width-Animationen */

  /* ─── Font-Weight ───────────────────────────────────────────────────
     Vier Stufen statt frei gewuerfelter Inline-Zahlen. Im JSX-Inline-Style:
     style={{fontWeight: 'var(--fw-semibold)'}} oder als Hilfsklasse .fw-*. */
  --fw-regular: 400;
  --fw-medium: 500;
  --fw-semibold: 600;
  --fw-bold: 700;
}

/* ─── Hell-Modus ────────────────────────────────────────────────────────────
   Aktiviert ueber data-theme="light" am <html> (gesetzt durch ein Inline-
   Skript noch vor dem ersten Paint, damit es nicht flackert). Die App ist
   ansonsten durchgehend dunkel — der Hell-Modus definiert die komplette
   zweite Farbpalette ueber dieselben Tokens. */
:root[data-theme="light"] {
  color-scheme: light;
  --bg: #f3f3f5;
  --surface: #ffffff;
  --surface2: #ebebee;
  --border: rgba(0,0,0,0.10);
  /* Welle-13-Audit Kontrast-Korrektur: --accent #9a7d10 ergab nur ~3.7:1
     auf --bg #f3f3f5 (WCAG-AA-Mindest 4.5:1). --accent2 ist Alias auf
     --danger (Brand-Guide siehe oben). Dunkel-Modus bleibt unangetastet. */
  --accent: #7d650d;
  --accent2: var(--danger);
  --text: #1c1c1f;
  --muted: #5b5b65;
  --success: #15803d;
  /* Status-Farben fuer den Hell-Modus — dunkler fuer ausreichenden Kontrast. */
  --warning: #b45309;
  --danger: #dc2626;
  --info: #2563eb;
  --purple: #6d28d9;
  --glass-bg: rgba(0,0,0,0.025);
  --glass-bg-hover: rgba(0,0,0,0.05);
  --glass-border: rgba(0,0,0,0.10);
  --glass-border-strong: rgba(0,0,0,0.17);
  --glass-highlight: inset 0 1px 0 rgba(255,255,255,0.85);
  --shadow-sm: 0 1px 2px rgba(0,0,0,0.08);
  --shadow-md: 0 1px 3px rgba(0,0,0,0.07), 0 8px 24px rgba(0,0,0,0.08);
  --shadow-lg: 0 24px 60px rgba(0,0,0,0.20);
  --grad-text: linear-gradient(135deg, #1c1c1f 0%, #66666f 100%);
  --accent-fg: #ffffff;
  --accent-hover: #b0911a;
  --input-bg: rgba(0,0,0,0.022);
  --input-bg-disabled: rgba(0,0,0,0.045);
  --placeholder: rgba(0,0,0,0.70);
  --hover-bg: rgba(0,0,0,0.045);
  --row-hover: rgba(0,0,0,0.03);
  /* Hell-Modus: dezenter neutraler Letterbox-Rahmen statt rgba(0,0,0,0.3). */
  --media-frame: rgba(0,0,0,0.07);
  --crop-overlay: rgba(0,0,0,0.35);
  --crop-handle: rgba(0,0,0,0.85);
  --text-disabled: #999;
}
/* Flaechen, die im Dunkel-Design einen transluzenten/dunklen Verlauf nutzen,
   werden im Hell-Modus solide und hell — sonst kaemen dunkle Karten heraus. */
:root[data-theme="light"] .card,
:root[data-theme="light"] .sidebar,
:root[data-theme="light"] .modal,
:root[data-theme="light"] .toast,
:root[data-theme="light"] .login-card { background: var(--surface); }
:root[data-theme="light"] * { scrollbar-color: rgba(154,125,16,0.5) rgba(0,0,0,0.06); }
:root[data-theme="light"] ::-webkit-scrollbar-track { background: rgba(0,0,0,0.04); }
:root[data-theme="light"] ::-webkit-scrollbar-thumb { background: rgba(154,125,16,0.4); border-color: var(--bg); }
:root[data-theme="light"] ::-webkit-scrollbar-thumb:hover { background: rgba(154,125,16,0.65); }

/* Scrollbar-Platz IMMER reservieren, auch wenn die Page gerade nicht scrollt.
   Sonst wackelt das Layout je nach Seiteninhalt: kurze Liste -> keine
   Scrollbar -> Page 10-15 px breiter -> Header-Knoepfe stehen rechts.
   Lange Liste -> Scrollbar erscheint -> Page schmaler -> der Knopf wrappt
   in eine zweite Zeile. Mit `stable` wird der Platz vorgehalten, das
   Layout bleibt konstant. */
html { scrollbar-gutter: stable; }

body {
  background: var(--bg); color: var(--text); font-family: 'DM Sans', sans-serif;
  -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
  letter-spacing: -0.011em;
}
/* Subtiles Ambient-Leuchten im Hintergrund — gibt den Glass-Flächen Tiefe,
   ohne aufdringlich zu sein. pointer-events:none, damit nichts blockiert. */
body::before {
  content: ''; position: fixed; inset: 0; z-index: 0; pointer-events: none;
  background:
    radial-gradient(55vw 55vh at 10% -8%, color-mix(in srgb, var(--accent) 5.5%, transparent), transparent 60%),
    radial-gradient(50vw 50vh at 100% 0%, color-mix(in srgb, var(--accent2) 4.5%, transparent), transparent 58%);
}

/* Scrollbalken — Default war fast schwarz auf schwarz und kaum sichtbar.
   Mit der Akzentfarbe leicht gelblich werden sie erkennbar, ohne aggressiv
   zu wirken. Firefox: scrollbar-color (Track + Thumb). WebKit: separate
   ::-webkit-scrollbar-* Pseudo-Elemente. Akzent ueber color-mix gegen den
   --accent-Token, damit Hell-Modus den dunkleren Goldton spiegelt. */
* { scrollbar-color: var(--accent-border-strong) var(--hover-bg); scrollbar-width: thin; }
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: var(--hover-bg); }
::-webkit-scrollbar-thumb { background: var(--accent-border); border-radius: 6px; border: 2px solid var(--bg); }
::-webkit-scrollbar-thumb:hover { background: color-mix(in srgb, var(--accent) 60%, transparent); }
::-webkit-scrollbar-corner { background: transparent; }

/* Bewegung reduzieren — respektiert die System-Einstellung (macOS/iOS
   „Bewegung reduzieren", Windows „Animationen anzeigen", GNOME, ...).
   Wirkt auch auf INLINE-style-Attribute: `!important` aus dem Author-
   Layer gewinnt gegen Inline-Styles im normalen Author-Layer (CSS
   Cascade Module Level 4 §6.4.1). Daher reicht eine CSS-Regel —
   wir muessen Inline-`style={{transition: ...}}` NICHT React-seitig
   abschalten.
   Fuer Faelle, in denen React-Logik je nach Setting unterschiedlich
   sein soll (z. B. Auto-Polling pausieren, autoplay verhindern),
   gibt es `useReducedMotion()` in core.jsx. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    transition-duration: 0.01ms !important;
    transition-delay: 0ms !important;
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    animation-delay: 0ms !important;
  }
  html { scroll-behavior: auto !important; }
}

.app { min-height: 100vh; display: flex; position: relative; z-index: 1; }

.sidebar {
  width: 220px;
  background: linear-gradient(180deg, rgba(255,255,255,0.022), rgba(255,255,255,0.006)), var(--bg);
  border-right: 1px solid var(--glass-border); display: flex; flex-direction: column;
  padding: 24px 0; position: fixed; top: 0; left: 0; bottom: 0; z-index: 100;
  backdrop-filter: var(--blur); -webkit-backdrop-filter: var(--blur);
  /* Innere Liste scrollbar, wenn sie laenger ist als der Viewport (Mobile-
     Drawer mit vielen Modulen / kleine Bildschirme). Ohne overflow-y wandert
     der Touch-Scroll nach unten in den Body durch — der Hintergrund scrollt,
     die Navi nicht. overscroll-behavior: contain verhindert zusaetzlich,
     dass ein Bounce am Listen-Ende den Body mitscrollt. */
  overflow-y: auto; overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
}
/* Sidebar-Wordmark — Brand-Konform: Inter 700, klein, „cinema" gold,
   „.tools" auf var(--text) (Theme-konform: hell auf Dark, dunkel auf
   Light). Tracking -0.02em wie im Brand-Guide. */
.sidebar-logo {
  font-family: 'Inter', system-ui, sans-serif;
  font-weight: var(--fw-bold); font-size: 22px; letter-spacing: -0.02em;
  color: var(--accent); padding: 0 24px 4px;
}

/* Wordmark = BrandMark + „cinema.tools" als geschlossene Einheit.
   Farben kommen ausschliesslich aus diesen Klassen — Inline-Overrides
   sind nicht mehr noetig, Container-Selektoren wie .sidebar-logo span
   greifen nicht mehr durch. */
.wordmark {
  display: inline-flex; align-items: baseline; gap: var(--space-4);
  color: var(--accent);
}
.wordmark-text { color: var(--accent); }
.wordmark-tools { color: var(--text); }
.nav { padding: 16px 12px; flex: 1; display: flex; flex-direction: column; gap: 2px; }
/* Gruppen werden durch Abstand + Sektions-Label getrennt — keine harten
   Trennstriche. Eine Linie direkt über/unter einem aktiven (abgerundeten,
   gelb hinterlegten) Eintrag wirkt sonst asymmetrisch. Linear-/Vercel-Stil. */
.nav-group { display: flex; flex-direction: column; gap: 2px; }
.nav-group + .nav-group { margin-top: 16px; }
.nav-section {
  font-size: 9px; font-weight: 700; letter-spacing: 1.2px; text-transform: uppercase;
  color: var(--muted); opacity: 0.5; padding: 2px 12px 4px;
}
.version-row:hover { color: var(--accent) !important; opacity: 1; }
.nav-item {
  display: flex; align-items: center; gap: 10px; padding: 8px 12px;
  border-radius: 8px; cursor: pointer; font-size: 14px; font-weight: 500;
  color: var(--muted); transition: background 0.15s, color 0.15s; border: none; background: none; text-align: left; width: 100%;
  position: relative;
}
.nav-item:hover { background: var(--hover-bg); color: var(--text); }
.nav-item.active { background: var(--accent-soft); color: var(--accent); }
/* Aktiver Eintrag: feiner Akzent-Marker links (Linear-Stil) */
.nav-item.active::before {
  content: ''; position: absolute; left: 0; top: 50%; transform: translateY(-50%);
  width: 3px; height: 16px; border-radius: 2px; background: var(--accent);
}
.nav-item .icon { width: 18px; display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0; }
.sidebar-footer { padding: 16px 24px; border-top: 1px solid var(--border); font-size: 12px; color: var(--muted); }
.user-badge { display: flex; align-items: center; gap: 8px; margin-bottom: 12px; }
.avatar { width: 30px; height: 30px; border-radius: 50%; background: var(--accent); display: flex; align-items: center; justify-content: center; font-weight: 700; font-size: 12px; color: var(--accent-fg); }
.logout-btn { background: none; border: 1px solid var(--border); color: var(--muted); padding: 6px 12px; border-radius: 6px; cursor: pointer; font-size: 12px; width: 100%; transition: all 0.15s; }
.logout-btn:hover { border-color: var(--accent2); color: var(--accent2); }

/* min-width:0 ist entscheidend: ein flex-item bekommt per Default
   min-width:auto und kann damit von seinen unschrumpfbaren Kindern
   (flex-shrink:0 Elemente in Welcome-Cards, breite Tabellen-Zeilen)
   ueber die verfuegbare Breite hinausgedrueckt werden. Folge: bei
   Pages mit breiten Inhalten wird .main breiter, bei Pages mit
   schmalem Empty-State (z.B. cine.welcome-Filter ohne Eintraege)
   schrumpft sie — der Page-Header rutscht damit je nach Filter. */
.main { margin-left: 220px; flex: 1; min-width: 0; padding: 40px; }
.page-header { margin-bottom: 32px; }
.page-title {
  font-family: 'Inter', system-ui, sans-serif;
  font-weight: var(--fw-bold); font-size: 29px; letter-spacing: -0.02em;
  background: var(--grad-text); -webkit-background-clip: text; background-clip: text;
  color: transparent;
}
/* Windows-High-Contrast/forced-colors-Modus uebermalt Hintergruende,
   color:transparent wuerde dann den Titel komplett verschwinden lassen.
   forced-color-adjust:none + Fallback-Color halten den Titel lesbar. */
@media (forced-colors: active) {
  .page-title {
    forced-color-adjust: none;
    background: none;
    color: CanvasText;
  }
}
.page-sub { color: var(--muted); font-size: 14px; margin-top: 4px; }

/* Gradient-Text-Helfer — frei verwendbar (Hervorhebungen, Hero-Zahlen). */
.gradient-text { background: var(--grad-text); -webkit-background-clip: text; background-clip: text; color: transparent; }
.gradient-accent { background: var(--grad-accent); -webkit-background-clip: text; background-clip: text; color: transparent; }

/* Glass-Card: leicht transluzent, feiner Rahmen, weicher Schatten. Hebt
   sich nur dezent vom Hintergrund ab — definiert über Rahmen + Tiefe. */
.card {
  background: var(--glass-bg);
  border: 1px solid var(--glass-border);
  border-radius: var(--radius); padding: 24px;
  backdrop-filter: var(--blur); -webkit-backdrop-filter: var(--blur);
  box-shadow: var(--shadow-md), var(--glass-highlight);
}
.card-title { font-size: 13px; font-weight: 600; letter-spacing: 1px; text-transform: uppercase; color: var(--muted); margin-bottom: 16px; }

/* Karte/Kachel mit dezentem Anheben beim Hover — ersetzt Inline-JS-Hover
   (onMouseOver/Out). Auf eine Karte zusaetzlich zu .card setzen. Nur fuer
   NICHT klickbare Karten — klickbare bekommen .card-interactive. */
.card-lift { transition: transform 0.15s var(--ease), box-shadow 0.15s var(--ease); }
.card-lift:hover { transform: translateY(-2px); box-shadow: var(--shadow-lg); }

/* Klickbare Karte/Kachel — sanfter Hover-Lift + Press-Feedback (analog zum
   .btn:active-Eindruecken). Zusaetzlich zu .card bzw. .format-card setzen.
   Im Hover bleibt --glass-highlight erhalten, damit .card-Karten ihren
   oberen Licht-Glanz nicht verlieren. */
.card-interactive { cursor: pointer; transition: transform 0.18s var(--ease), box-shadow 0.18s var(--ease), border-color 0.18s var(--ease); }
.card-interactive:hover { transform: translateY(-1px); box-shadow: var(--shadow-md), var(--glass-highlight); border-color: var(--glass-border-strong); }
.card-interactive:active { transform: translateY(0) scale(0.995); }

/* Card-Variante fuer „Mit Vorsicht"-Aktionen (Diagnose, destruktive Tools). */
.card-danger {
  border-color: var(--danger-border-strong);
  background: color-mix(in srgb, var(--danger) 4%, var(--surface));
}
/* Card-Variante fuer kritische Hinweise (npm install fehlt, Migrations-Drift). */
.card-purple {
  border-color: color-mix(in srgb, var(--purple) 40%, transparent);
  background: color-mix(in srgb, var(--purple) 8%, var(--surface));
}
/* Card-Variante fuer Brand-Akzent-Hinweise (Impersonation-Banner,
   Super-Admin-Tenant-Filter, „Achtung, du arbeitest gerade als …"). */
.card-accent-soft {
  border-color: var(--accent-border);
  background: var(--accent-subtle);
}

/* User-Badge in der Sidebar — Hover via CSS statt JS (respektiert reduced
   motion + Keyboard-Focus). active-Modifier toggelt den Akzent-Hintergrund. */
.user-badge {
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  transition: background 0.15s var(--ease), border-color 0.15s var(--ease);
}
.user-badge:hover, .user-badge:focus-visible { background: var(--hover-bg); }
.user-badge.active {
  background: var(--accent-subtle);
  border-color: var(--accent-border);
}

/* Tab-Leiste — Akzent-Unterstrich beim aktiven Tab. Verwendet ueberall, wo
   eine Page mehrere Sektionen hat (Organisation, Tenant-Modal etc.). */
.tab-bar { display: flex; gap: 4px; border-bottom: 1px solid var(--border); flex-wrap: wrap; }
.tab-bar > .tab {
  background: none; border: none; border-bottom: 2px solid transparent;
  border-radius: 0; padding: 10px 18px; color: var(--muted); font-weight: 600;
  font-size: 13px; cursor: pointer; display: inline-flex; align-items: center; gap: 8px;
  font-family: inherit;
}
.tab-bar > .tab:hover { color: var(--text); }
.tab-bar > .tab.active { color: var(--accent); border-bottom-color: var(--accent); }

/* Auswahl-Kachel (Poster/Film/History) — Akzent-Rahmen beim Hover.
   Ersetzt Inline-JS-Hover (onMouseEnter/Leave). */
.pick-tile { border: 2px solid var(--border); border-radius: var(--radius-sm); cursor: pointer; transition: border-color 0.15s var(--ease); }
.pick-tile:hover { border-color: var(--accent); }
/* Auswahl-Zeile (Such-Dropdown o. Ae.) — Hintergrund-Hover. */
.pick-row { cursor: pointer; transition: background 0.15s var(--ease); }
.pick-row:hover { background: var(--hover-bg); }

.grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; margin-bottom: 24px; }
.grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 24px; }
/* Grid-Spalten duerfen NICHT vom Inhalt aufgeblaeht werden: ein 1fr-Track
   hat implizit min-width:auto (= min-content). Enthaelt die Spalte ein
   inneres Grid (z. B. die Kinofilm-Plakate in cine.ad), draengt dessen
   min-content die Spalte ueber die Viewport-Breite → horizontaler Overflow
   der ganzen Seite, v. a. auf dem Handy. min-width:0 laesst die Kinder
   schrumpfen. (DESIGN.md §5 Punkt 6.) */
.grid-2 > *, .grid-3 > * { min-width: 0; }

.stat-value {
  font-family: 'Inter', system-ui, sans-serif;
  font-weight: var(--fw-bold); font-size: 42px; letter-spacing: -0.02em;
  background: var(--grad-text); -webkit-background-clip: text; background-clip: text;
  color: transparent;
}
.stat-label { font-size: 13px; color: var(--muted); margin-top: 2px; }
.stat-delta { font-size: 12px; margin-top: 6px; }
.stat-delta.up { color: var(--success); }
.stat-delta.warn { color: var(--accent); }

.upload-zone {
  border: 1.5px dashed var(--glass-border-strong); border-radius: var(--radius); padding: 48px 24px;
  text-align: center; cursor: pointer; transition: border-color 0.2s, background 0.2s; position: relative;
  background: var(--glass-bg);
}
.upload-zone:hover { border-color: var(--accent); background: var(--accent-subtle); }
.upload-icon { font-size: 40px; margin-bottom: 12px; }
.upload-text { font-size: 15px; font-weight: 500; color: var(--text); margin-bottom: 6px; }
.upload-hint { font-size: 13px; color: var(--muted); }
.upload-zone input { position: absolute; inset: 0; opacity: 0; cursor: pointer; }

.ad-canvas {
  border-radius: var(--radius); overflow: hidden; position: relative; aspect-ratio: 16/9;
  background: linear-gradient(135deg, #0d0d1a 0%, #1a0a2e 100%);
  display: flex; align-items: center; justify-content: center;
}
.ad-canvas img { width: 100%; height: 100%; object-fit: contain; }

.btn {
  display: inline-flex; align-items: center; gap: 8px; padding: 9px 18px;
  border-radius: var(--radius-sm); font-size: 14px; font-weight: 600; cursor: pointer;
  border: 1px solid transparent;
  transition: background 0.18s var(--ease), border-color 0.18s var(--ease), color 0.18s var(--ease), box-shadow 0.18s var(--ease), transform 0.12s var(--ease);
  text-decoration: none; letter-spacing: 0.2px;
}
/* Apple-artiges Press-Feedback: kurz eindrücken. */
.btn:active:not(:disabled) { transform: scale(0.97); }
.btn-primary { background: var(--accent); color: var(--accent-fg); box-shadow: 0 1px 0 rgba(255,255,255,0.18) inset, var(--shadow-sm); }
.btn-primary:hover { background: var(--accent-hover); }
.btn-outline { background: var(--glass-bg); border-color: var(--glass-border); color: var(--text); }
.btn-outline:hover { background: var(--glass-bg-hover); border-color: var(--glass-border-strong); color: var(--text); }
.btn-danger { background: var(--danger-subtle); border-color: var(--danger-border); color: var(--danger); }
.btn-danger:hover { background: var(--danger-soft); border-color: var(--danger-border-strong); }
/* Geschwister fuer „erledigt" / „bestaetigt"-Aktionen — gleicher
   transluzent-tinted Button-Stil mit Success-Gruen statt Danger-Rot. */
.btn-success { background: color-mix(in srgb, var(--success) 10%, transparent); border-color: color-mix(in srgb, var(--success) 30%, transparent); color: var(--success); }
.btn-success:hover { background: color-mix(in srgb, var(--success) 16%, transparent); border-color: color-mix(in srgb, var(--success) 50%, transparent); }
/* Solide rote Variante fuer hart-bestaetigende Aktionen (anonymisieren,
   loeschen, freigeben). Modifier .btn-danger.btn-strong nutzt Vollflaeche
   ohne die nicht-token-konforme '#fff'-Schriftfarbe — Default-Schrift via
   var(--accent-fg), bleibt im Hell- und Dunkelmodus lesbar. */
.btn-danger.btn-strong { background: var(--danger); border-color: var(--danger); color: var(--accent-fg); }
.btn-danger.btn-strong:hover { filter: brightness(1.1); }
.btn-sm { padding: 6px 13px; font-size: 13px; }
/* Noch kompakter als .btn-sm — fuer mehrere Aktionen nebeneinander in
   einer Zeile (Stundenleiste, Reload-Buttons in Kosten-Widgets, etc.).
   Sammelt die zuvor ~14 Mal kopierten Inline-Overrides
   (style={{fontSize:'var(--text-sm)',padding:'3px 10px'}}). */
.btn-xs { padding: 3px 10px; font-size: var(--text-sm); }
.btn:disabled { opacity: 0.4; cursor: not-allowed; }

/* ─── A11y: globale Fokus-Indikatoren ─────────────────────────────────────
   :focus-visible greift nur bei Tastatur-Navigation (kein blauer Ring beim
   Klicken). Buttons + Links + Tab-Items bekommen einen weichen Akzent-Ring,
   damit sich Tastatur-User orientieren koennen. */
.btn:focus-visible,
.btn-icon:focus-visible,
.logout-btn:focus-visible,
a:focus-visible,
button:focus-visible,
[role="button"]:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.btn:focus-visible {
  box-shadow: 0 0 0 4px var(--accent-border);
}

/* Skip-to-content Link — fuer Tastatur-Nutzer der erste fokussierbare
   Eintrag, ueberspringt Sidebar/Topbar und springt in den Hauptinhalt.
   Default unsichtbar via off-screen-Positionierung; bei Fokus sichtbar. */
.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: var(--z-skip-link);
  background: var(--accent);
  color: var(--accent-fg);
  padding: 10px 16px;
  border-radius: 0 0 6px 0;
  font-weight: 600;
  text-decoration: none;
}
.skip-link:focus {
  left: 0;
  outline: 2px solid var(--text);
  outline-offset: -4px;
}

/* Icon-only Button — quadratisch, transluzent, dezenter Hover. Fuer reine
   Icon-Aktionen (Karten-Aktionen, Modal-Schliessen, Listen-Zeilen). */
.btn-icon {
  display: inline-flex; align-items: center; justify-content: center;
  padding: 6px; border-radius: var(--radius-sm);
  background: none; border: 1px solid transparent; color: var(--muted);
  cursor: pointer;
  transition: background 0.15s var(--ease), color 0.15s var(--ease), border-color 0.15s var(--ease);
}
.btn-icon:hover { background: var(--hover-bg); color: var(--text); border-color: var(--glass-border); }
.btn-icon:active:not(:disabled) { transform: scale(0.94); }
.btn-icon:disabled { opacity: 0.4; cursor: not-allowed; }

/* Button-Gruppe / segmentierte Auswahl — zusammenhaengende Buttons als EIN
   Steuerelement (Umschalter, Filter). Markup:
     <div class="btn-group">
       <button class="btn btn-sm btn-primary">Aktiv</button>
       <button class="btn btn-sm btn-outline">Inaktiv</button>
     </div>
   Aktives Segment btn-primary, inaktive btn-outline. Die Klasse uebernimmt
   das Zusammenfuegen (Radien + ueberlappende Raender) — KEIN Inline-Style. */
.btn-group { display: inline-flex; }
/* Weicher Wechsel des aktiven Segments — etwas knackiger (0.15s) als der
   .btn-Standard. Vollstaendige Property-Liste, weil transition als Shorthand
   die .btn-Regel komplett ersetzt (sonst gingen border/shadow verloren). */
.btn-group > .btn {
  border-radius: 0; margin-left: -1px;
  transition: background 0.15s var(--ease), color 0.15s var(--ease), border-color 0.15s var(--ease), box-shadow 0.15s var(--ease), transform 0.12s var(--ease);
}
.btn-group > .btn:first-child { margin-left: 0; border-top-left-radius: var(--radius-sm); border-bottom-left-radius: var(--radius-sm); }
.btn-group > .btn:last-child { border-top-right-radius: var(--radius-sm); border-bottom-right-radius: var(--radius-sm); }
/* Aktives Segment nach vorn — sonst verdeckt der Nachbar-Rand den Akzent. */
.btn-group > .btn-primary { position: relative; z-index: 1; }
/* Sanft eingleitender Aktiv-Indikator: eine dezente Unterstreichung unter dem
   aktiven Segment skaliert beim Aktivwerden von 0 -> 1 ein. Greift nur, wenn
   prefers-reduced-motion NICHT auf reduce steht (oben global geregelt). */
.btn-group > .btn-primary::after {
  content: ''; position: absolute; left: 8px; right: 8px; bottom: 2px;
  height: 2px; border-radius: 2px;
  background: color-mix(in srgb, var(--accent-fg) 70%, transparent);
  transform: scaleX(0.4); transform-origin: center;
  transition: transform 0.22s var(--ease), opacity 0.22s var(--ease);
  opacity: 0.85;
}
.btn-group > .btn-primary:hover::after { transform: scaleX(1); opacity: 1; }

.form-group { margin-bottom: 16px; }
.form-label { display: block; font-size: 12px; font-weight: 600; letter-spacing: 1px; text-transform: uppercase; color: var(--muted); margin-bottom: 8px; }
.form-input, .form-select {
  width: 100%; background: var(--input-bg); border: 1px solid var(--glass-border); color: var(--text);
  padding: 10px 14px; border-radius: var(--radius-sm); font-size: 14px; font-family: 'DM Sans', sans-serif;
  transition: border-color 0.16s var(--ease), box-shadow 0.16s var(--ease), background 0.16s var(--ease);
}
.form-input:hover, .form-select:hover { border-color: var(--glass-border-strong); }
.form-input:focus, .form-select:focus {
  outline: none; border-color: var(--accent);
  /* background-color statt shorthand `background`: das Shorthand resettet
     sonst background-image, -repeat und -position. In Kombination mit der
     :hover-Regel weiter unten (die nur background-image neu setzt) fuehrt
     das dazu, dass der Chevron-SVG ueber die ganze Feldbreite kachelt,
     sobald der User gleichzeitig fokussiert + hovert. */
  box-shadow: 0 0 0 3px var(--accent-soft); background-color: var(--input-bg);
}
/* Placeholder optisch klar vom echten Wert trennen — sonst sehen
   vorgeschlagene Beispielwerte aus wie tatsaechlich eingetragen.
   Italic + reduzierte Opacity reicht: das Auge erkennt sofort „leer". */
.form-input::placeholder { color: var(--placeholder); font-style: italic; opacity: 0.7; }

/* Konsistente Filter-/Toolbar-Reihen. Alle direkten Kinder (Buttons,
   Inputs, Selects, btn-groups) bekommen dieselbe Mindesthoehe (38 px =
   .form-input-Hoehe) und vertikalen Mittenausgleich. Verhindert das
   typische „Treppen"-Layout, wenn eine Reihe btn-sm (28 px) neben
   form-input (38 px) mischt. */
.filter-bar {
  display: flex; gap: 8px; flex-wrap: wrap; align-items: center;
  margin-bottom: 12px;
}
.filter-bar > * { min-height: 38px; box-sizing: border-box; }
.filter-bar .btn { padding-top: 0; padding-bottom: 0; }
.filter-bar .form-input,
.filter-bar .form-select { padding-top: 0; padding-bottom: 0; height: 38px; line-height: normal; }
.filter-bar .btn-group { display: inline-flex; min-height: 38px; }
.filter-bar .btn-group > .btn { min-height: 38px; padding-top: 0; padding-bottom: 0; }
/* Mobile: jedes Filter-Element nimmt die volle Breite, sauber gestackt
   statt unschoen halbiert. Die Reihen bleiben einheitlich hoch. */
@media (max-width: 640px) {
  .filter-bar { gap: 8px; }
  .filter-bar > * { flex: 1 1 100%; width: 100%; max-width: 100% !important; min-width: 0 !important; }
  .filter-bar .btn-group { width: 100%; }
  .filter-bar .btn-group > .btn { flex: 1 1 0; }
  .filter-bar .btn:not(.btn-group .btn) { justify-content: center; }
  /* iOS Safari zoomt bei Input-Fokus rein, wenn font-size < 16 px.
     Auf Touch-Geraeten hochziehen — kein Zoom-Tanz beim Tippen mehr. */
  .form-input, .form-select { font-size: 16px; }
  /* Mindest-Tap-Target nach Apple HIG/Material Design — 30 px war zu klein.
     .btn-icon (z. B. Aktionen-Spalten in Tabellen) hatte 6 px Padding ->
     etwa 24 px Touchflaeche. Hochziehen auf 44x44 px, weil Finger keine
     Mauszeiger sind. */
  .btn-sm { min-height: 40px; }
  .btn-icon { min-width: 44px; min-height: 44px; padding: 10px; }
}

/* Dashboard-Umsatz-Hero: Periode-Umschalter (30 Tage / Monat / Jahr / Gesamt).
   Auf Desktop ein einreihiger Flex-Strang, auf Mobile 2x2-Grid — sonst brachen
   die 4 Buttons unschoen 3+1 und „Gesamt" stand alleine in einer zweiten Zeile. */
.revenue-periods { display: flex; gap: 4px; flex-wrap: wrap; justify-content: flex-end; }
@media (max-width: 640px) {
  .revenue-periods { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; width: 100%; }
  .revenue-periods .btn { min-height: 40px; }
}

/* Kleiner Abschnitts-Titel in Masken/Karten — Versalien, gedaempft.
   Ersetzt mehrfach kopierte Inline-Styles (frueher uneinheitlich 11/12 px). */
.section-label {
  font-size: 11px; font-weight: 700; letter-spacing: 0.6px;
  text-transform: uppercase; color: var(--muted);
}

/* Schreibgeschützte / deaktivierte Felder — sollen klar NICHT wie ein
   beschreibbares Eingabefeld aussehen: flacher Hintergrund, kein
   sichtbarer Rahmen, gedämpfter Text, kein Hover/Focus, not-allowed-
   Cursor. Dadurch optisch klar von editierbaren Feldern unterscheidbar. */
.form-input:disabled, .form-select:disabled,
.form-input[readonly], textarea.form-input:disabled {
  background: var(--input-bg-disabled);
  border-color: transparent;
  color: var(--muted);
  cursor: not-allowed;
  box-shadow: none;
  -webkit-text-fill-color: var(--muted);
  opacity: 1;
}
.form-input:disabled:hover, .form-select:disabled:hover,
.form-input[readonly]:hover { border-color: transparent; }
.form-input:disabled:focus, .form-select:disabled:focus,
.form-input[readonly]:focus { box-shadow: none; border-color: transparent; }
/* Deaktivierte Dropdowns: kein Chevron, kein Pointer — wirken sonst klickbar. */
select.form-input:disabled, select.form-select:disabled {
  background-image: none; cursor: not-allowed; padding-right: 14px;
}

/* Dropdowns: native Pfeil entfernen, eigenen Chevron setzen.
   Data-URIs koennen keine var()-Tokens — daher pro Theme ein eigener
   Override mit den jeweils passenden Muted-/Akzent-Farben (Dunkel:
   #9a9aa2/#e8c547, Hell: #66666f/#9a7d10). Wer die Token-Palette
   aendert, muss diese vier URIs mitziehen. */
select.form-input, select.form-select, .form-select {
  appearance: none; -webkit-appearance: none; -moz-appearance: none;
  cursor: pointer; padding-right: 36px;
  background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5L6 6.5L11 1.5' stroke='%239a9aa2' stroke-width='1.7' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 13px center;
}
select.form-input:hover, select.form-select:hover, .form-select:hover {
  background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5L6 6.5L11 1.5' stroke='%23e8c547' stroke-width='1.7' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}
:root[data-theme="light"] select.form-input, :root[data-theme="light"] select.form-select, :root[data-theme="light"] .form-select {
  background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5L6 6.5L11 1.5' stroke='%2366666f' stroke-width='1.7' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}
:root[data-theme="light"] select.form-input:hover, :root[data-theme="light"] select.form-select:hover, :root[data-theme="light"] .form-select:hover {
  background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5L6 6.5L11 1.5' stroke='%239a7d10' stroke-width='1.7' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}
select.form-input option, select.form-select option { background: var(--surface); color: var(--text); }

/* Scroll-Wrapper fuer Tabellen mit mehreren Spalten — verhindert dass das
   Card-Layout auf Mobile horizontal aus dem Viewport ausbricht. Tabelle
   selbst bleibt display:table (Spalten von Kopf und Body bleiben aligned),
   der Wrapper macht den Scroll. */
.table-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }
/* Sticky-Header in scrollenden Tabellen: Kopfzeile bleibt beim vertikalen
   Scrollen sichtbar. Solider Hintergrund noetig, sonst scheinen die Zeilen
   durch den (sonst transparenten) th-Hintergrund. */
.table-scroll .table thead th { position: sticky; top: 0; background: var(--surface); z-index: 1; }

/* Mobile-Karten-Stack fuer Tabellen unter 640px.
   Tabellen mit .table-stack werden auf kleinen Bildschirmen zu vertikal
   gestapelten „Karten" je Zeile — jedes td bekommt einen Label-Praefix
   aus seinem data-label-Attribut (das die jeweilige JSX-Stelle setzt).
   Migration ist pro Tabelle Folgearbeit (data-label-Attribute brauchen
   Spalten-Wissen) — das Pattern liegt bereit. */
@media (max-width: 640px) {
  /* Stack-Tabellen brauchen keinen horizontalen Scroll — die Zeilen
     liegen als Block-Karten untereinander. Sonst zeigt iOS Safari bei
     mono-Font-Inhalten (Hex-Codes, IDs) gelegentlich einen Pseudo-Scroll,
     der die ganze Seite horizontal verschiebt. */
  .table-scroll:has(.table-stack) { overflow-x: visible; }
  .table-stack { display: block; min-width: 0 !important; max-width: 100%; }
  .table-stack thead { display: none; }
  .table-stack tbody, .table-stack tr { display: block; }
  .table-stack tr {
    border: 1px solid var(--border); border-radius: var(--radius-sm);
    margin-bottom: 10px; padding: 10px 12px; background: var(--surface);
  }
  .table-stack tr:hover td { background: transparent; }
  .table-stack td {
    display: block; padding: 4px 0; border: none;
    font-size: var(--text-md);
    /* Inline `max-width`/`white-space:nowrap` (z. B. fuer Label/URL-Spalten
       mit Ellipsis im Desktop-Tabellenmodus) im Stack-Mode aufheben — sonst
       wirkt der Zeilen-Hintergrund nicht durchgaengig, weil der Textcontainer
       schmaler ist als die Karte. */
    max-width: none !important;
    white-space: normal !important;
    word-break: break-word;
    overflow: visible !important;
    text-overflow: clip !important;
    /* Rechts-bündige Zahlen-Spalten (Samples/p50/p75/p95 etc.) im Stack-Modus
       links bündig — sonst springt der Wert ans rechte Karten-Ende und
       sitzt weit weg vom data-label-Praefix oben links. */
    text-align: left !important;
  }
  .table-stack td::before {
    content: attr(data-label); display: block;
    font-size: var(--text-xs); color: var(--muted);
    font-weight: 600; text-transform: uppercase; letter-spacing: 1px;
    margin-bottom: 2px;
  }
  /* Wenn data-label fehlt, kein Pseudo-Element. */
  .table-stack td:not([data-label])::before { content: none; }
  /* Leeres data-label (z. B. fuer Action-Spalte) auch kein Pseudo-Element. */
  .table-stack td[data-label=""]::before { content: none; }
  /* Aktionen-Spalte im Mobile-Modus: Buttons untereinander, jeder volle
     Kartenbreite. Verhindert das haessliche „2 in einer Reihe, 1 darunter"-
     Wrapping wenn 3 Aktionen nicht in einer Zeile reinpassen. */
  .table-stack td[data-label="Aktionen"] {
    flex-direction: column !important;
    align-items: stretch !important;
    gap: 6px !important;
  }
  .table-stack td[data-label="Aktionen"] > button {
    width: 100%;
    justify-content: center;
  }

  /* AD.LINK-Code-Liste: 9 Spalten waren als 9 Stack-Zeilen pro Karte zu
     gespreizt. Wir paaren die Sekundaer-Infos (Datum, Quelle+Kanal,
     Scans+Letzter-Scan, Status+Aktion) zu kompakten 2-Spalten-Zeilen. */
  .table-adlink td { padding: 3px 0; }
  .table-adlink td[data-label="Erstellt"],
  .table-adlink td[data-label="Letzter Scan"] {
    display: inline-block; width: 50%; vertical-align: top;
    font-size: var(--text-xs);
  }
  .table-adlink td[data-label="Erstellt"]::before,
  .table-adlink td[data-label="Letzter Scan"]::before {
    margin-bottom: 1px;
  }
  .table-adlink td[data-label="Quelle"],
  .table-adlink td[data-label="Kanal"] {
    display: inline-block; width: 50%; vertical-align: top;
  }
  .table-adlink td[data-label="Scans"] {
    display: inline-block; width: 60%; vertical-align: middle;
    text-align: left !important;
    padding-top: 6px !important; padding-bottom: 6px !important;
  }
  /* Scans-Label inline („SCANS 0" statt Stack), damit das Status-Badge
     daneben auf Augenhoehe mit der Zahl sitzt — nicht zwischen Label und
     Zahl wie im vorigen Versuch. */
  .table-adlink td[data-label="Scans"]::before {
    display: inline !important; margin-right: 8px !important; margin-bottom: 0 !important;
  }
  .table-adlink td[data-label="Status"] {
    display: inline-block; width: 40%; vertical-align: middle;
    text-align: right;
    padding-top: 6px !important; padding-bottom: 6px !important;
  }
  .table-adlink td[data-label="Status"]::before { display: none; }
  /* „Öffnen"-Button als full-width Footer-Aktion. */
  .table-adlink td[data-label=""] {
    margin-top: 6px; padding-top: 6px;
    border-top: 1px solid var(--border) !important;
  }
  .table-adlink td[data-label=""] .btn { width: 100%; }

  /* Web-Vitals-Tabelle: 7 Spalten als 7 Stack-Zeilen waren zu hoch.
     Layout pro Karte: Zeile 1 = Metrik (gross) + Status-Badge rechts,
     Zeile 2 = Page (muted), Zeile 3 = Samples/p50/p75/p95 in 4 Quartilen
     inline. */
  .table-webvitals td { padding: 2px 0; }
  .table-webvitals td[data-label="Metrik"] {
    display: inline-block; width: 60%; vertical-align: middle;
    font-size: var(--text-lg) !important; font-weight: 600;
  }
  .table-webvitals td[data-label="Metrik"]::before { display: none; }
  .table-webvitals td[data-label="Status (p75)"] {
    display: inline-block; width: 40%; vertical-align: middle;
    text-align: right !important;
  }
  .table-webvitals td[data-label="Status (p75)"]::before { display: none; }
  .table-webvitals td[data-label="Page"] {
    font-size: var(--text-xs); color: var(--muted);
    margin-bottom: 6px;
  }
  .table-webvitals td[data-label="Page"]::before { display: none; }
  .table-webvitals td[data-label="Samples"],
  .table-webvitals td[data-label="p50"],
  .table-webvitals td[data-label="p75"],
  .table-webvitals td[data-label="p95"] {
    display: inline-block; width: 25%; vertical-align: top;
    font-size: var(--text-xs);
  }
  .table-webvitals td[data-label="Samples"]::before,
  .table-webvitals td[data-label="p50"]::before,
  .table-webvitals td[data-label="p75"]::before,
  .table-webvitals td[data-label="p95"]::before {
    margin-bottom: 1px;
  }

  /* npm-Versions-Tabelle: 5 Spalten als 5 Stack-Zeilen waren zu hoch.
     Layout: Zeile 1 = Paket-Name (gross) + Status-Badge rechts,
     Zeile 2 = Installiert/package.json/Neueste als 3 Drittel inline. */
  .table-npm td { padding: 2px 0; }
  .table-npm td[data-label="Paket"] {
    display: inline-block; width: 60%; vertical-align: middle;
    font-size: var(--text-md) !important; font-weight: 600;
  }
  .table-npm td[data-label="Paket"]::before { display: none; }
  .table-npm td[data-label="Status"] {
    display: inline-block; width: 40%; vertical-align: middle;
    text-align: right !important;
  }
  .table-npm td[data-label="Status"]::before { display: none; }
  .table-npm td[data-label="Installiert"],
  .table-npm td[data-label="package.json"],
  .table-npm td[data-label="Neueste"] {
    display: inline-block; width: 33.33%; vertical-align: top;
    font-size: var(--text-xs);
  }
  .table-npm td[data-label="Installiert"]::before,
  .table-npm td[data-label="package.json"]::before,
  .table-npm td[data-label="Neueste"]::before {
    margin-bottom: 1px;
  }

  /* Häufigste-Fehler-Tabelle: Message als prominenter Header oben,
     Häufigkeit + User + Zuletzt als 3 Spalten inline. */
  .table-errgroup td { padding: 2px 0; }
  .table-errgroup td[data-label="Message"] {
    font-family: 'DM Mono', monospace !important;
    margin-bottom: 4px;
  }
  .table-errgroup td[data-label="Message"]::before { display: none; }
  .table-errgroup td[data-label="Häufigkeit"],
  .table-errgroup td[data-label="User"],
  .table-errgroup td[data-label="Zuletzt"] {
    display: inline-block; width: 33.33%; vertical-align: top;
    font-size: var(--text-xs);
  }
  .table-errgroup td[data-label="Häufigkeit"]::before,
  .table-errgroup td[data-label="User"]::before,
  .table-errgroup td[data-label="Zuletzt"]::before {
    margin-bottom: 1px;
  }

  /* Einzel-Fehler-Tabelle: Zeit + Quelle-Badge oben, Page + User inline,
     Message als breiter Text unten. Aufgeklappter Stack-Trace bleibt
     als Block-Karte unter dem Eintrag. */
  .table-errlist td { padding: 2px 0; }
  .table-errlist td[data-label="Zeit"] {
    display: inline-block; width: 60%; vertical-align: middle;
    font-size: var(--text-xs);
  }
  .table-errlist td[data-label="Quelle"] {
    display: inline-block; width: 40%; vertical-align: middle;
    text-align: right !important;
  }
  .table-errlist td[data-label="Quelle"]::before { display: none; }
  .table-errlist td[data-label="Page"],
  .table-errlist td[data-label="User"] {
    display: inline-block; width: 50%; vertical-align: top;
    font-size: var(--text-xs);
  }
  .table-errlist td[data-label="Page"]::before,
  .table-errlist td[data-label="User"]::before {
    margin-bottom: 1px;
  }
  .table-errlist td[data-label="Message"] {
    margin-top: 4px; padding-top: 4px;
    border-top: 1px solid var(--border) !important;
    font-family: 'DM Mono', monospace !important;
  }

  /* cine.welcome-Karte auf Mobile: Action-Knoepfe waren als schmale
     Spalte rechts (minWidth 130). Bei iPhone-Breite (~375 px) druckte
     die Spalte den Titel-Bereich in 3 Zeilen und sah unsauber aus.
     Fix: Karten-Container darf umbrechen, Action-Knopfleiste rutscht
     in eine eigene Zeile am Ende und wird als 2-Spalten-Grid
     dargestellt. */
  .welcome-card { flex-wrap: wrap; }
  .welcome-card-actions {
    flex-direction: row !important;
    min-width: 100% !important;
    flex-basis: 100% !important;
    flex-wrap: wrap;
    gap: 6px !important;
    margin-top: 4px;
  }
  .welcome-card-actions .btn {
    flex: 1 1 calc(50% - 3px);
    min-width: 0;
    justify-content: center;
  }

  /* Kompakte Variante fuer Dashboard-Uebersichts-Tabellen (Mandanten,
     Letzte Jobs, Trash, Recent-Invoices): statt jedes Feld eigene Zeile
     ein 2-Spalten-Grid. Halbiert die vertikale Hoehe. data-prom-Attribut
     auf einem <td> macht das Feld full-width oben (Mandant-Name, Film-
     Titel) — der Rest verteilt sich. Optional data-stat fuer rechtsbuendige
     Mono-Zahlen-Felder. */
  .table-stack-dense tbody tr {
    display: grid; grid-template-columns: 1fr 1fr;
    gap: 4px 12px;
    border: 1px solid var(--border); border-radius: var(--radius-sm);
    margin-bottom: 8px; padding: 9px 11px; background: var(--surface);
  }
  .table-stack-dense thead { display: none; }
  .table-stack-dense, .table-stack-dense tbody { display: block; }
  .table-stack-dense td {
    display: block; padding: 0; border: none;
    font-size: var(--text-md);
    min-width: 0;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .table-stack-dense td::before {
    content: attr(data-label); display: block;
    font-size: var(--text-xs); color: var(--muted);
    font-weight: 600; text-transform: uppercase; letter-spacing: 1px;
    margin-bottom: 1px;
  }
  .table-stack-dense td:not([data-label])::before { content: none; }
  .table-stack-dense td[data-prom] {
    grid-column: 1 / -1; font-weight: 600; font-size: var(--text-lg);
    border-bottom: 1px solid var(--border); padding-bottom: 5px;
    margin-bottom: 3px;
  }
  .table-stack-dense td[data-prom]::before { display: none; }
  .table-stack-dense tr:hover td { background: transparent; }

  /* Beleg-Positionen-Tabelle (cine.bill, bill-editor.jsx): die Tabelle
     hat Sonderfaelle (heading-Rows mit colSpan, aufklappbare Detail-
     Zeilen), die ein .table-stack nicht sauber tragen wuerde. Statt
     dem Karten-Stack also nur die Hilfsspalten ausblenden — uebrig
     bleiben Bezeichnung, Menge, Einzelpreis und Summe. */
  .bill-line-table .bill-line-col-unit,
  .bill-line-table .bill-line-col-vat,
  .bill-line-table .bill-line-col-disc { display: none; }

  /* SFA-Stats Top-Filme: im Karten-Stack zeigen wir den vollen Titel,
     damit der User auf dem Handy nicht durch Ellipsis raten muss. */
  .sfa-stats-film-title { white-space: normal !important; max-width: none !important; }
}

/* Desktop-Verhalten der Top-Filme-Zelle: Ellipsis, einzeilig. */
.sfa-stats-film-title {
  max-width: 200px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.table { width: 100%; border-collapse: collapse; }
.table th { font-size: 11px; letter-spacing: 1.5px; text-transform: uppercase; color: var(--muted); padding: 10px 14px; text-align: left; border-bottom: 1px solid var(--border); }
.table td { padding: 12px 14px; font-size: 14px; border-bottom: 1px solid var(--border); }
.table tr:last-child td { border-bottom: none; }
.table tr:hover td { background: var(--row-hover); }

.badge { display: inline-block; padding: 3px 10px; border-radius: 20px; font-size: 11px; font-weight: 600; border: 1px solid transparent; }
.badge-success { background: color-mix(in srgb, var(--success) 12%, transparent); color: var(--success); border-color: color-mix(in srgb, var(--success) 22%, transparent); }
.badge-warn { background: var(--accent-soft); color: var(--accent); border-color: var(--accent-border); }
.badge-info { background: color-mix(in srgb, var(--info) 12%, transparent); color: var(--info); border-color: color-mix(in srgb, var(--info) 24%, transparent); }
.badge-gray { background: var(--hover-bg); color: var(--muted); border-color: var(--glass-border); }
.badge-danger { background: var(--danger-soft); color: var(--danger); border-color: var(--danger-border-strong); }
.badge-purple { background: color-mix(in srgb, var(--purple) 14%, transparent); color: var(--purple); border-color: color-mix(in srgb, var(--purple) 35%, transparent); }

/* Typografie-Hilfsklassen — siehe --text-* Tokens im :root-Block. */
.t-xs { font-size: var(--text-xs); }
.t-sm { font-size: var(--text-sm); }
.t-md { font-size: var(--text-md); }
.t-lg { font-size: var(--text-lg); }
.t-xl { font-size: var(--text-xl); }
.t-2xl { font-size: var(--text-2xl); }
.t-3xl { font-size: var(--text-3xl); }

/* Font-Weight-Hilfsklassen — neuer Inline-fontWeight-Wert ist seit
   Konvention untersagt (siehe DESIGN.md). Klassen-Namen folgen der
   gaengigen CSS-Schrift-Kraeftigkeitsskala. */
.fw-regular  { font-weight: 400; }
.fw-medium   { font-weight: 500; }
.fw-semibold { font-weight: 600; }
.fw-bold     { font-weight: 700; }

/* Spacing-Hilfsklassen — fuer padding-Kombinationen, die mit +/-1 px
   Toleranz mehrfach im Code auftauchten. Token-Werte sind im :root
   definiert (--space-*). Wer beide Achsen unterschiedlich braucht,
   schreibt das per Token direkt im style-Attribut. */
.p-tiny     { padding: var(--space-2) var(--space-4); }  /* ~3px 8px: Badges, Pillen */
.p-snug     { padding: var(--space-2) var(--space-5); }  /* ~4px 10px: small Buttons */
.p-base     { padding: var(--space-4) var(--space-5); }  /* ~8px 10px: Default Cards */
.p-cosy     { padding: var(--space-5) var(--space-7); }  /* ~10px 14px: Card-Titles, Modals */
.p-spacious { padding: var(--space-6) var(--space-8); }  /* ~12px 16px: Hero, prominente Cards */

/* btn-action: Buttons in einer vertikalen Aktions-Spalte (Welcome-Karten-
   Knopf-Reihe rechts). Icon + Text linksbuendig zueinander, nowrap. */
.btn.btn-action {
  display: inline-flex; align-items: center;
  justify-content: flex-start; gap: 6px; white-space: nowrap;
}

/* Color-Picker (admin Mandant-Bearbeiten + generate Manuell-Farbe).
   Vorher in 4 Modulen identische 8-Property-Inline-Styles. */
.color-input {
  width: 44px; height: 36px; padding: 2px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg);
  cursor: pointer;
}

/* Card-Modifier:
   .card-flush — die Card hat padding:0 und overflow:hidden, weil
     der Inhalt (z.B. eine volle Tabelle) bündig bis an die Card-Kante
     gehen soll. Tritt ~12× im Code auf — eigene Klasse vermeidet die
     Wiederholung des Inline-Styles {padding:0, overflow:hidden}. */
.card.card-flush { padding: 0; overflow: hidden; }

/* Inline-Code-Chip (sfa-records Pflichtfeld-Hinweise, Diagnose).
   Token-baisiert statt fester rgba(0,0,0,…), damit der Hell-Modus
   passt. */
.code-chip {
  font-family: 'DM Mono', monospace;
  font-size: var(--text-sm);
  padding: 1px 6px;
  background: var(--hover-bg);
  border-radius: var(--radius-xs);
  border: 1px solid var(--border);
}

.login-page { min-height: 100vh; display: flex; align-items: center; justify-content: center; background: var(--bg); position: relative; overflow: hidden; }
.login-bg { position: absolute; inset: 0; background: radial-gradient(ellipse at 20% 50%, var(--accent-subtle) 0%, transparent 60%), radial-gradient(ellipse at 80% 20%, color-mix(in srgb, var(--accent2) 5%, transparent) 0%, transparent 50%); }
.login-card {
  position: relative; z-index: 1; width: min(400px, calc(100vw - 24px));
  background: linear-gradient(180deg, rgba(255,255,255,0.045), rgba(255,255,255,0.015));
  border: 1px solid var(--glass-border-strong);
  border-radius: var(--radius-lg); padding: 40px;
  backdrop-filter: var(--blur-strong); -webkit-backdrop-filter: var(--blur-strong);
  box-shadow: var(--shadow-lg), var(--glass-highlight);
}
.login-title { font-family: 'Inter', system-ui, sans-serif; font-weight: var(--fw-bold); font-size: 32px; letter-spacing: -0.02em; color: var(--accent); margin-bottom: 4px; }
.login-sub { font-size: 13px; color: var(--muted); margin-bottom: 32px; }

.progress-bar { height: 4px; background: var(--border); border-radius: 2px; overflow: hidden; margin-top: 8px; }
.progress-fill { height: 100%; background: var(--accent); border-radius: 2px; transition: width 0.5s ease; }

.format-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; }
/* Format-Kachel (cine.ad) — Hover-Lift, Border-Hover und :active kommen aus
   .card-interactive (Markup setzt beide Klassen). Hier nur das Format-
   spezifische: Hintergrund-Hover + selected-Zustand. background steht mit
   in der transition, weil diese Regel die aus .card-interactive ueberschreibt
   (gleiche Spezifitaet, spaeter im Stylesheet). */
.format-card {
  border: 1px solid var(--glass-border); border-radius: var(--radius-sm); padding: 14px 10px;
  text-align: center; background: var(--glass-bg);
  transition: border-color 0.18s var(--ease), background 0.18s var(--ease), transform 0.18s var(--ease), box-shadow 0.18s var(--ease);
}
.format-card:hover { background: var(--glass-bg-hover); }
.format-card.selected { border-color: var(--accent); background: var(--accent-subtle); }
.format-ratio { font-family: 'Inter', system-ui, sans-serif; font-weight: var(--fw-bold); font-size: 18px; letter-spacing: -0.02em; }
.format-name { font-size: 11px; color: var(--muted); margin-top: 2px; }

.cost-pill { display: inline-flex; align-items: center; gap: 6px; background: var(--accent-soft); border: 1px solid var(--accent-border); border-radius: 20px; padding: 6px 14px; font-size: 13px; color: var(--accent); font-weight: 600; }

.generating { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 16px; padding: 40px; min-height: 300px; }
.spin { width: 40px; height: 40px; border: 3px solid var(--border); border-top-color: var(--accent); border-radius: 50%; animation: spin 0.8s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }
@keyframes progress-pulse { 0%,100% { opacity:0.35; transform:scaleX(0.5); transform-origin:left; } 50% { opacity:1; transform:scaleX(1); transform-origin:left; } }

.tabs { display: flex; gap: 0; border-bottom: 1px solid var(--border); margin-bottom: 24px; overflow-x: auto; }
/* Funktioniert auf <div> UND <button> — Button-Chrome wird zurueckgesetzt. */
.tab { padding: 10px 20px; font-size: 14px; font-weight: 500; font-family: inherit; cursor: pointer; background: none; border: 0; border-bottom: 2px solid transparent; border-radius: 0; color: var(--muted); margin-bottom: -1px; white-space: nowrap; }
.tab.active { color: var(--accent); border-bottom-color: var(--accent); }
.tab:hover:not(.active) { color: var(--text); }

.modal-overlay {
  /* --z-modal (310): Modals liegen UEBER Sticky-Bannern (200/201) und
     Toasts (300). Vorher stand hier faelschlich --z-sticky-banner, womit
     Impersonation-Banner und Toasts ueber den Dialogen lagen und einzelne
     Module das per Inline-zIndex individuell flicken mussten. */
  position: fixed; inset: 0; background: rgba(0,0,0,0.55); z-index: var(--z-modal);
  display: flex; align-items: center; justify-content: center; padding: 20px;
  backdrop-filter: blur(6px) saturate(140%); -webkit-backdrop-filter: blur(6px) saturate(140%);
}
.modal {
  background: linear-gradient(180deg, rgba(28,28,33,0.9), rgba(20,20,24,0.9));
  border: 1px solid var(--glass-border-strong); border-radius: var(--radius-lg);
  padding: 32px; width: 100%; max-width: 480px;
  backdrop-filter: var(--blur-strong); -webkit-backdrop-filter: var(--blur-strong);
  box-shadow: var(--shadow-lg), var(--glass-highlight);
  /* Wheel/Touch im Modal nicht zum Body durchreichen — sonst scrollt der
     Hintergrund weiter, wenn das Modal selbst nichts zu scrollen hat
     (kurze Inhalte) oder am Scroll-Rand angekommen ist. */
  overscroll-behavior: contain;
}
/* Solange ein CccModal offen ist, Body-Scroll komplett sperren — kein
   Hintergrund-Scroll bei kurzen Inhalten, kein Bounce-Bleed auf iOS. */
html:has(.modal-overlay) { overflow: hidden; }
.modal-title { font-family: 'Inter', system-ui, sans-serif; font-weight: var(--fw-bold); font-size: 24px; letter-spacing: -0.02em; margin-bottom: 8px; }

/* Toast-Einflug von unten — wird vom globalen prefers-reduced-motion-Block
   (animation-duration: 0.01ms) automatisch deaktiviert. */
@keyframes toast-in {
  from { opacity: 0; transform: translateY(12px); }
  to   { opacity: 1; transform: translateY(0); }
}
.toast {
  position: fixed; bottom: 24px; right: 24px;
  background: linear-gradient(180deg, rgba(28,28,33,0.92), rgba(20,20,24,0.92));
  border: 1px solid var(--glass-border-strong); border-radius: var(--radius-sm);
  padding: 14px 20px; z-index: var(--z-toast); max-width: 400px;
  backdrop-filter: var(--blur); -webkit-backdrop-filter: var(--blur);
  box-shadow: var(--shadow-lg), var(--glass-highlight);
  animation: toast-in 0.28s var(--ease);
}
.toast.error { border-color: color-mix(in srgb, var(--accent2) 40%, transparent); color: var(--accent2); }
.toast.success { border-color: color-mix(in srgb, var(--success) 40%, transparent); color: var(--success); }

.actions-row { display: flex; gap: 10px; align-items: center; margin-top: 20px; flex-wrap: wrap; }
.export-bar { display: flex; align-items: center; justify-content: space-between; margin-bottom: 20px; gap: 12px; flex-wrap: wrap; }
.search-input {
  background: var(--input-bg); border: 1px solid var(--glass-border); color: var(--text);
  padding: 8px 14px; border-radius: var(--radius-sm); font-size: 14px; width: 240px;
  transition: border-color 0.16s var(--ease), box-shadow 0.16s var(--ease);
}
.search-input:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }

/* Skeleton-Shimmer fuer Platzhalter beim Laden */
@keyframes skeletonShimmer {
  0%   { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}

/* ─── Mobile / Responsive + einklappbare Sidebar ────────────────────────────
   Desktop-Standard: Sidebar fest links. Auf dem Handy (<=768px) ODER wenn am
   Desktop manuell eingeklappt (.app.sidebar-collapsed) wird die Sidebar zur
   Schublade, die ueber einen Hamburger in der fixen Topbar geoeffnet wird.
   Topbar, Schliessen-Knopf, Backdrop + Hamburger sind in der Basis fertig
   gestylt — nur ihr display schaltet je nach Modus. */
.mobile-topbar {
  display: none; align-items: center; gap: 12px;
  position: fixed; top: 0; left: 0; right: 0; height: 50px;
  background: var(--surface); border-bottom: 1px solid var(--border);
  /* Topbar liegt UEBER der Sidebar-Schublade (z-index 100) und ueber dem
     Backdrop (99) — damit der Hamburger immer klickbar bleibt und im
     offenen Zustand das Schliessen-Symbol genau dort sitzt, wo vorher das
     Oeffnen-Symbol war. */
  z-index: 105; padding: 0 12px;
}
.hamburger {
  background: none; border: none; color: var(--text);
  font-size: 22px; line-height: 1; cursor: pointer; padding: 6px 8px;
}
.mobile-topbar-logo {
  font-family: 'Inter', system-ui, sans-serif;
  font-weight: var(--fw-bold); font-size: 18px;
  letter-spacing: -0.02em; color: var(--accent);
}
.mobile-topbar-logo span { color: var(--text); }
.mobile-topbar-logo span { color: var(--text); }
.sidebar-backdrop {
  display: none; position: fixed; inset: 0;
  background: rgba(0,0,0,0.6); z-index: 99;
  /* Touch-Move auf dem Backdrop nicht zum Body durchreichen — sonst kann
     ein Streifen-Wisch am Sidebar-Rand den Inhalt darunter mitscrollen. */
  touch-action: none;
}
/* Wenn die Mobile-Schublade offen ist (App-Klasse 'sidebar-drawer-open'),
   den Body-Scroll lockern — kein doppeltes Scroll-Verhalten (Drawer-Liste
   UND Body gleichzeitig), kein Background-Bleed durch Bounce-Edges. */
.app.sidebar-drawer-open { overflow: hidden; height: 100vh; }
@media (max-width: 768px) {
  html:has(.app.sidebar-drawer-open) { overflow: hidden; }
}
/* Sticky-Banner im Main-Bereich (Impersonation, Offline, Update).
   Default: oben ankleben. Auf Mobile durch eine engere Regel weiter
   unten unter die fixe 50px-Topbar geschoben. */
.sticky-banner { top: 0; }
/* Einklapp-Knopf in der Sidebar — auf dem Handy unnoetig (dort ist die
   Sidebar ohnehin eine Schublade), daher nur am Desktop sichtbar. */
.sidebar-toggle {
  background: none; border: none; color: var(--muted); cursor: pointer;
  padding: 4px; display: inline-flex; align-items: center; border-radius: 6px;
  transition: background 0.15s, color 0.15s;
}
.sidebar-toggle:hover { background: var(--hover-bg); color: var(--text); }

/* Desktop: Seitenleiste manuell eingeklappt -> gleiches Schubladen-Verhalten
   wie auf dem Handy, ausgeloest per Klasse statt Breakpoint. */
@media (min-width: 769px) {
  .app.sidebar-collapsed .sidebar {
    width: 260px;
    transform: translateX(-100%);
    transition: transform 0.22s ease;
    /* --shadow-lg statt fixem rgba: die Schublade liegt wie ein Overlay
       ueber dem Inhalt — gleiche Tiefenstufe wie Modal/Toast, und der
       Hell-Modus bekommt automatisch seine weichere Variante. */
    box-shadow: var(--shadow-lg);
  }
  .app.sidebar-collapsed .sidebar.sidebar-open { transform: translateX(0); }
  .app.sidebar-collapsed .sidebar-backdrop { display: block; }
  .app.sidebar-collapsed .main { margin-left: 0; padding-top: 66px; }
  .app.sidebar-collapsed .mobile-topbar { display: flex; }
  .app.sidebar-collapsed .bill-editor-bar { top: 50px; }
  /* Sidebar startet unter der Topbar, damit der Hamburger (jetzt mit X-Icon
     im offenen Zustand) immer klickbar ist und seine Position behaelt. */
  .app.sidebar-collapsed .sidebar { top: 50px; }
}

/* cine.bill Stammdaten: Spaltenkopf-Zeile fuer Zahlungsziele nur auf
   Desktop sichtbar — Mobile bricht das Grid in Rows, da brauchen wir die
   Kopfzeile nicht (Beschriftungen stehen als placeholder im Input). */
@media (max-width: 640px) {
  .bill-terms-head { display: none !important; }
}

@media (max-width: 768px) {
  /* Sidebar -> Schublade von links, beginnt unter der 50px-Topbar damit
     der Hamburger immer klickbar ist und sein Icon (Menu/Close) dort
     bleibt, wo der User es erwartet. */
  .sidebar {
    width: 78vw; max-width: 300px; top: 50px;
    transform: translateX(-100%);
    transition: transform 0.22s ease;
    /* --shadow-lg statt fixem rgba: die Schublade liegt wie ein Overlay
       ueber dem Inhalt — gleiche Tiefenstufe wie Modal/Toast, und der
       Hell-Modus bekommt automatisch seine weichere Variante. */
    box-shadow: var(--shadow-lg);
  }
  .sidebar.sidebar-open { transform: translateX(0); }
  .sidebar-backdrop { display: block; }
  /* Auf dem Handy ist Einklappen sinnlos — Knopf ausblenden. */
  .sidebar-toggle { display: none; }

  /* Hauptbereich volle Breite, Platz fuer die fixe Topbar.
     Kein overflow-x:auto mehr — Tabellen scrollen jetzt intern (siehe
     .table-Regel unten), nicht das gesamte Layout. So bleibt der Card-
     Rahmen sichtbar, auch wenn eine Tabelle horizontal scrollt. */
  .main { margin-left: 0; padding: 16px; padding-top: 66px; }
  /* Sticky-Banner (Impersonation, Offline, Update) gehoeren auf Mobile UNTER
     die fixe 50px-Topbar. position:fixed statt sticky, weil sticky-Verhalten
     in Browsern mit body{overflow-x:hidden} unzuverlaessig sein kann. !important
     sichert gegen inline-Top-Reste aus altem Bundle ab. */
  .sticky-banner {
    position: fixed !important;
    top: 50px !important;
    left: 0; right: 0;
    /* z-index muss UNTER Backdrop (99) + Sidebar (100) bleiben, sonst
       ueberlagert der fixed Banner die Schubladen-Navigation. Der inline
       gesetzte z-index 200/201 ist auf Desktop sinnvoll, auf Mobile aber
       zu hoch — daher hier explizit niedriger erzwingen. */
    z-index: 90 !important;
  }
  /* Wenn ein Banner sichtbar ist, schiebt eine zusaetzliche Klasse auf .main
     den Inhalt darunter; siehe app.jsx (banner-visible). */
  .main.has-sticky-banner { padding-top: 110px; }
  .page-header { margin-bottom: 20px; }

  /* Cards: an Mobile-Breite anpassen + verhindern dass Kind-Elemente
     ueber den Card-Rand hinausragen. Padding etwas kleiner als auf Desktop. */
  .card { padding: 16px; max-width: 100%; }

  /* Kompaktere Tabellen auf Mobile, sonst kostet jede Spalte zu viel
     horizontalen Platz. Die Tabellen selbst werden via JSX-Wrapper in
     ein scrollbares Element gepackt — display:block auf <table> direkt
     ist auf Safari-iOS unzuverlaessig (Spalten von Kopf und Body driften
     auseinander), daher der explizite Wrapper-Ansatz. */
  .table th { padding: 8px 10px; }
  .table td { padding: 10px 10px; }

  /* Body als letzte Verteidigung: niemals horizontal scrollen. Wenn doch
     irgendwo ein Element zu breit wird, wird es geclippt statt das Layout
     zu sprengen. */
  body { overflow-x: hidden; }

  /* Fixe Topbar mit Hamburger-Knopf */
  .mobile-topbar { display: flex; }

  /* Dialoge: (fast) volle Breite, oben ausgerichtet */
  .modal-overlay { padding: 10px; align-items: flex-start; }
  .modal { max-width: none !important; padding: 18px; }

  /* Mehrspalten-Grids einspaltig: .grid-2 (z.B. cine.ad Formular+Vorschau)
     und .grid-3 (Dashboard) quetschen sonst den kompletten Workflow in
     ~160px-Spalten. Format-Kacheln bleiben 2-spaltig — einspaltig wuerde
     die Auswahl zu lang. */
  .grid-2, .grid-3 { grid-template-columns: 1fr; }
  .format-grid { grid-template-columns: repeat(2, 1fr); }

  /* Sticky-Aktionsleiste unter die fixe Topbar schieben */
  .bill-editor-bar { top: 50px; margin: -16px -16px 14px; padding: 12px 16px; }
}

/* cine.bill Editor: Aktionsleiste bleibt beim Scrollen sichtbar */
.bill-editor-bar {
  position: sticky; top: 0; z-index: 30;
  background: var(--bg); border-bottom: 1px solid var(--border);
  margin: -40px -40px 18px; padding: 18px 40px;
}

/* TMS-Helper: Mobile-Optimierungen ───────────────────────────────────────────
   Die Wochen-Toolbar hat 8–9 Buttons + ein Wochen-Label. Auf Desktop passt
   das in eine Reihe, auf Mobile bricht es um. Drei Regeln, die zusammen den
   Umbruch lesbar machen:
   1. Wochen-Label nimmt nicht mehr 220 px in Anspruch, sondern schrumpft.
   2. Spacer zwischen Wochen-Navigation und Aktionen verschwindet (sonst
      bleibt eine Leerzeile mitten im Wrap).
   3. Trailer-Aufruf-Button im Film-Listen-Eintrag wird kompakter, damit der
      Titel mehr Platz behaelt. */
/* Desktop: Mobile-Only-Elemente verstecken. Zahnrad-Overflow-Trigger und
   sein Aufklapp-Panel sind ausschliesslich fuer Mobile gedacht — auf
   Desktop ist die Toolbar lang genug fuer alle Aktionen. */
@media (min-width: 640px) {
  .tms-desktop-hide { display: none !important; }
}
@media (max-width: 640px) {
  .tms-toolbar { gap: 6px !important; }
  .tms-toolbar-spacer { display: none !important; }
  /* Wochen-Navigation (Pfeil-Label-Pfeil) bekommt eine eigene volle Zeile
     und sitzt darin zusammenhaengend. Das Label zwischen den Pfeilen waechst
     mit (flex:1), schrumpft minWidth auf 0, font-size geht runter. */
  .tms-nav-group { flex: 1 1 100% !important; gap: 6px !important; }
  .tms-week-label {
    min-width: 0 !important; font-size: 13px;
    flex: 1 1 auto !important; text-align: center !important;
  }
  .tms-trailer-btn { min-width: 0 !important; padding: 6px 10px; }
  /* Sekundaere Aktionen (Aktualisieren, Heute, Datum) verlieren ihren Text-
     Label und werden zu Icon-Buttons, damit die Toolbar in zwei Reihen passt
     statt vier. Title-Attribute geben die Bedeutung weiter (Long-Tap auf Touch,
     Hover auf Desktop). */
  .tms-btn-label { display: none !important; }
  /* Selten genutzte Aktionen verstecken — sie werden ueber das Zahnrad-
     Overflow-Menue erreichbar (siehe .tms-desktop-hide-Block unten in
     der Toolbar). */
  .tms-mobile-hide { display: none !important; }
}

/* ─── Brand-Lockup ───────────────────────────────────────────────────────
   Aperture-Mark + Wortmarke. Brand-Guide siehe BRAND.md.
   .brand-mark    — kleines SVG (mark-gold.svg) inline neben Text
   .brand-lockup  — Container fuer Mark + Wordmark in Sidebar/Login */
.brand-mark { display: inline-block; vertical-align: middle; flex-shrink: 0; }
.brand-lockup { display: inline-flex; align-items: center; gap: var(--space-5); }


/* ─── Marketing-Landing ──────────────────────────────────────────────────
   Pre-Login-Schauseite (public/js/marketing.jsx). Eigene Layout-Logik,
   damit sie sich vom App-Frame absetzt — kein Sidebar, kein
   Versions-Banner, sondern brand-Header + Hero + Modul-Galerie. */
.marketing-page {
  min-height: 100vh;
  background: var(--bg); color: var(--text);
  display: flex; flex-direction: column;
}
.marketing-header {
  display: flex; align-items: center; justify-content: space-between;
  padding: var(--space-7) var(--space-8);
  border-bottom: 1px solid var(--border);
  position: sticky; top: 0; z-index: var(--z-sticky-banner);
  background: color-mix(in srgb, var(--bg) 92%, transparent);
  backdrop-filter: var(--blur); -webkit-backdrop-filter: var(--blur);
}
.marketing-brand,
.marketing-footer-brand {
  font-family: 'Inter', system-ui, sans-serif;
  font-weight: var(--fw-bold); font-size: 20px; letter-spacing: -0.02em;
  color: var(--accent);
  display: inline-flex; align-items: baseline; gap: var(--space-4);
}
.marketing-hero {
  text-align: center;
  padding: 96px var(--space-8) 64px;
  max-width: 720px; margin: 0 auto;
}
.marketing-hero-mark { display: inline-block; margin-bottom: var(--space-8); color: var(--accent); }
.marketing-hero-title {
  font-family: 'Inter', system-ui, sans-serif;
  font-weight: var(--fw-bold); font-size: 64px; letter-spacing: -0.03em;
  margin-bottom: var(--space-8);
}
.marketing-hero-pitch {
  font-size: 19px; line-height: 1.55; color: var(--muted);
  margin-bottom: 32px;
}
.marketing-hero-cta {
  display: flex; align-items: center; justify-content: center;
  gap: var(--space-7); flex-wrap: wrap;
}
.marketing-hero-secondary {
  color: var(--accent); text-decoration: none; font-weight: var(--fw-semibold);
  font-size: 15px; padding: 12px 8px;
  background: none; border: 0; cursor: pointer;
  font-family: inherit;
}
.marketing-hero-secondary:hover { text-decoration: underline; }
.marketing-final-cta-row {
  display: flex; align-items: center; justify-content: center;
  gap: var(--space-7); flex-wrap: wrap;
}
.btn-lg { padding: 14px 28px; font-size: 16px; font-weight: var(--fw-semibold); }
.marketing-section-title {
  font-family: 'Inter', system-ui, sans-serif;
  font-weight: var(--fw-bold); font-size: 29px; letter-spacing: -0.02em;
  text-align: center; margin-bottom: 40px;
}
.marketing-modules-section,
.marketing-usp-section {
  padding: 64px var(--space-8);
  max-width: 1100px; margin: 0 auto; width: 100%;
}
.marketing-modules {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 20px;
}
.marketing-module-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 24px;
  transition: border-color var(--duration-base) var(--ease), transform var(--duration-base) var(--ease);
}
.marketing-module-card:hover { border-color: color-mix(in srgb, var(--accent) 40%, var(--border)); transform: translateY(-2px); }
.marketing-module-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--space-5); margin-bottom: var(--space-6);
}
.marketing-module-title {
  font-family: 'Inter', system-ui, sans-serif;
  font-weight: var(--fw-bold); font-size: 20px; letter-spacing: -0.02em;
  color: var(--accent);
}
.marketing-module-badge {
  font-size: var(--text-xs); font-weight: var(--fw-semibold);
  text-transform: uppercase; letter-spacing: 0.5px;
  padding: 3px 8px; border-radius: var(--radius-xs);
  background: color-mix(in srgb, var(--info) 12%, transparent);
  color: var(--info);
  border: 1px solid color-mix(in srgb, var(--info) 28%, transparent);
}
.marketing-module-desc { color: var(--muted); line-height: 1.55; font-size: 14px; }
.marketing-usps {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 24px;
}
.marketing-usp { padding: 20px; }
.marketing-usp-title {
  font-family: 'Inter', system-ui, sans-serif;
  font-weight: var(--fw-bold); font-size: 18px; letter-spacing: -0.02em;
  margin-bottom: var(--space-5); color: var(--text);
}
.marketing-usp-body { color: var(--muted); line-height: 1.55; font-size: 14px; }
.marketing-final-cta {
  text-align: center;
  padding: 80px var(--space-8);
  background: var(--accent-subtle);
  border-top: 1px solid var(--accent-soft);
  border-bottom: 1px solid var(--accent-soft);
}
.marketing-final-title {
  font-family: 'Inter', system-ui, sans-serif;
  font-weight: var(--fw-bold); font-size: 36px; letter-spacing: -0.02em;
  margin-bottom: var(--space-6);
}
.marketing-final-sub { color: var(--muted); font-size: 17px; margin-bottom: 28px; }
.marketing-footer {
  display: flex; align-items: center; justify-content: space-between;
  padding: 32px var(--space-8);
  flex-wrap: wrap; gap: var(--space-6);
  color: var(--muted); font-size: 14px;
}
.marketing-footer-links { display: flex; gap: 24px; flex-wrap: wrap; }
.marketing-footer-links a,
.marketing-footer-link-btn {
  color: var(--muted); text-decoration: none;
  background: none; border: 0; padding: 0; cursor: pointer;
  font-family: inherit; font-size: inherit;
}
.marketing-footer-links a:hover,
.marketing-footer-link-btn:hover { color: var(--accent); }

@media (max-width: 640px) {
  .marketing-header { padding: var(--space-6) var(--space-6); }
  .marketing-hero { padding: 56px var(--space-6) 40px; }
  .marketing-hero-title { font-size: 44px; }
  .marketing-hero-pitch { font-size: 16px; }
  .marketing-modules-section,
  .marketing-usp-section { padding: 48px var(--space-6); }
  .marketing-final-cta { padding: 56px var(--space-6); }
  .marketing-final-title { font-size: 28px; }
}

/* ─── Rechtliches-Lesefassung ─────────────────────────────────────────────
   Frame (.marketing-page Header + Footer) kommt aus dem Marketing-Block
   oben. Diese Regeln stylen die Subnav und den eingebetteten HTML-
   Inhalt aus /api/legal/content (kommt per dangerouslySetInnerHTML
   ins .legal-content rein, deshalb selektieren wir via Descendant). */
/* Single sticky Top-Bar fuer die Rechtliches-Seite: Logo links,
   Tabs (Impressum/Datenschutz/Nutzungsbedingungen) mittig, Anmelden
   rechts. Ersetzt den getrennten marketing-header + legal-subnav,
   damit nur EINE Bar oben pinnt. */
.legal-header {
  position: sticky; top: 0; z-index: var(--z-sticky-banner);
  background: color-mix(in srgb, var(--bg) 92%, transparent);
  backdrop-filter: var(--blur); -webkit-backdrop-filter: var(--blur);
  border-bottom: 1px solid var(--border);
  display: flex; align-items: center; gap: var(--space-6);
  padding: var(--space-5) var(--space-8);
  flex-wrap: wrap;
}
.legal-tabs {
  display: flex; gap: var(--space-3); flex-wrap: wrap;
  margin-left: auto; margin-right: auto;
}
.legal-subnav-tab {
  font-family: 'Inter', system-ui, sans-serif;
  font-weight: var(--fw-medium); font-size: 13px;
  color: var(--muted); text-decoration: none;
  padding: 6px 14px;
  border: 1px solid var(--border); border-radius: var(--radius-xs);
  transition: color var(--duration-base) var(--ease), border-color var(--duration-base) var(--ease), background var(--duration-base) var(--ease);
}
.legal-subnav-tab:hover { color: var(--text); border-color: color-mix(in srgb, var(--accent) 40%, var(--border)); }
.legal-subnav-tab.active {
  color: var(--accent);
  background: var(--accent-soft);
  border-color: var(--accent-border-strong);
}

.legal-main { max-width: 860px; margin: 0 auto; padding: 32px var(--space-8) 64px; width: 100%; }
.legal-loading, .legal-error {
  padding: 48px 0; color: var(--muted); text-align: center;
}
.legal-error { color: var(--danger); }

/* Eingebetteter Inhalt aus /api/legal/content — Brand-Typo (Inter
   Bold fuer Hauptueberschriften), Sektionen mit Trennlinie zwischen
   den drei Bereichen (Impressum / Datenschutz / Nutzungsbedingungen).
   h2 sind kompakte Sub-Section-Labels in Gold, nicht Brand-Hero-
   Headings — sonst gewinnt das Layout vor dem juristischen Text. */
.legal-content section.legal {
  padding: 36px 0 40px;
  border-bottom: 1px solid var(--border);
  /* Sticky-Header (legal-header) verdeckt sonst den Section-Anfang —
     ohne scroll-margin landen Klicks auf #impressum/#datenschutz/
     #nutzungsbedingungen mit der Ueberschrift hinter dem Header. */
  scroll-margin-top: 80px;
}
.legal-content section.legal:first-of-type { padding-top: 8px; }
.legal-content section.legal:last-of-type { border-bottom: 0; padding-bottom: 16px; }
.legal-content h1 {
  font-family: 'Inter', system-ui, sans-serif;
  font-weight: var(--fw-bold); font-size: 32px; letter-spacing: -0.02em;
  margin-bottom: var(--space-3);
  scroll-margin-top: 80px;
}
.legal-content h2 {
  font-family: 'Inter', system-ui, sans-serif;
  font-weight: var(--fw-bold); font-size: 13px; letter-spacing: 0.8px;
  color: var(--accent); text-transform: uppercase;
  margin: 28px 0 var(--space-5);
  scroll-margin-top: 80px;
}
.legal-content h3 {
  font-family: 'Inter', system-ui, sans-serif;
  font-weight: var(--fw-semibold); font-size: 16px; letter-spacing: -0.01em;
  color: var(--text);
  margin: 22px 0 var(--space-3);
}
.legal-content p,
.legal-content ul,
.legal-content ol { line-height: 1.6; color: var(--text); font-size: 15px; margin-bottom: var(--space-5); }
.legal-content p.lead { font-size: 14px; color: var(--muted); margin-bottom: 24px; }
.legal-content ul, .legal-content ol { padding-left: 22px; }
.legal-content li { margin-bottom: var(--space-2); }
.legal-content a { color: var(--accent); text-decoration: none; }
.legal-content a:hover { text-decoration: underline; }
.legal-content strong { color: var(--text); font-weight: var(--fw-semibold); }

.legal-content .toc {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 16px 22px;
  margin: 16px 0 28px;
}
.legal-content .toc strong {
  display: block;
  font-size: 11px; font-weight: var(--fw-bold);
  letter-spacing: 1px; text-transform: uppercase;
  color: var(--muted);
  margin-bottom: var(--space-3);
}
.legal-content .toc a { display: block; color: var(--text); font-size: 13px; padding: 3px 0; }
.legal-content .toc a:hover { color: var(--accent); }

.legal-content .block {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 16px 22px;
  margin: var(--space-5) 0;
}
.legal-content .block p:last-child { margin-bottom: 0; }
.legal-content .important {
  background: color-mix(in srgb, var(--warning) 10%, transparent);
  border: 1px solid color-mix(in srgb, var(--warning) 28%, transparent);
  border-radius: var(--radius-sm);
  padding: 14px 18px;
  font-size: 14px;
  margin: var(--space-5) 0;
}
.legal-content table {
  width: 100%; border-collapse: collapse;
  margin: var(--space-5) 0;
  font-size: 14px;
}
.legal-content thead th {
  text-align: left; padding: 10px 12px;
  font-size: 11px; font-weight: var(--fw-bold);
  text-transform: uppercase; letter-spacing: 0.6px;
  color: var(--muted);
  border-bottom: 1px solid var(--border);
}
.legal-content tbody td {
  padding: 10px 12px;
  border-bottom: 1px solid var(--border);
  vertical-align: top;
  line-height: 1.5;
}
.legal-content tbody tr:last-child td { border-bottom: 0; }
.legal-content .meta {
  margin-top: 40px; padding-top: 16px;
  border-top: 1px solid var(--border);
  text-align: center;
  color: var(--muted); font-size: 13px;
}

@media (max-width: 640px) {
  .legal-header { padding: var(--space-4) var(--space-6); gap: var(--space-4); }
  .legal-tabs { margin: 0; flex-basis: 100%; order: 3; }
  .legal-main { padding: 24px var(--space-6) 48px; }
  .legal-content h1 { font-size: 26px; }
  .legal-content section.legal {
    padding: 28px 0 32px;
    /* Header ist auf mobile hoeher (Tab-Streifen umbricht in eine
       zweite Zeile) — Sprungziel entsprechend tiefer ansetzen. */
    scroll-margin-top: 140px;
  }
  .legal-content h1,
  .legal-content h2 { scroll-margin-top: 140px; }
  .legal-content table { font-size: 13px; }
  .legal-content thead th,
  .legal-content tbody td { padding: 8px 10px; }
}
