/* Open Sans, selbst gehostet (S-01): variable Schrift mit Gewichtsachse
   400-800, je Zeichenbereich eine WOFF2-Datei (Herkunft und Aufbereitung:
   public/assets/fonts/HERKUNFT.txt, Lizenz OFL.txt daneben). Vorher kam die
   Schrift zur Laufzeit von Google Fonts - die CSP (font-src 'self')
   blockierte das, und jeder Seitenaufruf schickte die IP an Google. */
@font-face {
  font-family: 'Open Sans';
  font-style: normal;
  font-weight: 400 800;
  font-display: swap;
  src: url('/assets/fonts/open-sans-latin-ext-wght-normal.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Open Sans';
  font-style: normal;
  font-weight: 400 800;
  font-display: swap;
  src: url('/assets/fonts/open-sans-latin-wght-normal.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
:root {
  /* Mike Bergmann Akademie CI: Markenblau #0072EF / #2E91FC, Akzent #3498db */
  --bg: #0b1220;
  --bg-elev: #121b2c;
  --bg-card: #162034;
  --border: #263449;
  --text: #eaf1f8;
  --text-dim: #93a3b8;
  --accent: #0072EF;          /* Akademie-Primaerblau */
  --accent-hover: #2E91FC;
  --accent-2: #3498db;        /* sekundaerer Akzent (Highlights/KPIs) */
  --warn: #e0a72d;
  /* S-20: #f0554b erreichte als Fehlertext auf der Karte nur 4,35:1. */
  --danger: #f26b62;
  --ist: #3fb950;
  /* S-20: #8b949e erreichte als war-Badge nur 4,0:1. */
  --war: #9aa3ad;
  --pot: #d29922;
  /* S-20: Schrift auf Statusfarben (Balken, Funnel) - dunkle Schrift auf den
     hellen Statusfarben der dunklen Ansicht. */
  --on-bar: #0b1220;
  /* S-20: Rahmen von Eingabefeldern, Tabs und Chips (>= 3:1 gegen
     --bg-elev und --bg-card, WCAG 1.4.11). --border bleibt fuer Trennlinien. */
  --border-strong: #5d7394;
  /* S-20: abgedunkelter Grund fuer Marken im aktiven (blauen) Reiter. */
  --tint-on-accent: rgba(0, 0, 0, .25);
  --radius: 12px;
  --shadow: 0 6px 24px rgba(0, 30, 70, .35);
  --brand: #0072EF;
  --font: 'Open Sans', system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  /* Tokens, die vor der hellen Ansicht als Literale im CSS und in den Seiten
     standen (Spec 2026-08-10, Abschnitt 3.1). Sie muessen hell andere Werte
     haben, deshalb gehoeren sie hierher und nicht in die Regel. */
  --bg-topbar: rgba(13, 17, 23, .85);
  --row-hover: rgba(255, 255, 255, .02);
  /* S-22: Schatten am Rand seitlich scrollbarer Tabellen. */
  --scroll-shadow: rgba(0, 0, 0, .45);
  --tint-accent: rgba(47, 129, 247, .08);
  /* S-20: .18 -> .08, damit --accent-2 auf dem Tag 4,5:1 erreicht. */
  --tint-accent2: rgba(52, 152, 219, .08);
  --bar-soft: rgba(0, 114, 239, .32);
  --tint-ist: rgba(63, 185, 80, .16);
  --tint-war: rgba(139, 148, 158, .18);
  --tint-pot: rgba(210, 153, 34, .16);
  --tint-danger: rgba(240, 85, 75, .08);
  /* Das Logo liegt als dunkle Zeichnung vor und wird dunkel per Filter weiss
     gemacht. Hell muss der Filter WEG, sonst ist es weiss auf Weiss. */
  --logo-filter: brightness(0) invert(1);
  /* Landkarte: Kategorie "sonstige" (weder ist- noch war- noch potenziell). */
  --sonstige: #7c8798;
  /* Leaderboard-Raenge auf /tv (Gold/Silber/Bronze). */
  --medal-1: #f1c40f;
  --medal-2: #bdc3c7;
  --medal-3: #cd7f32;
  /* Cluster-Kreise der Landkarte, nach Anzahl gestuft. */
  --cluster-1: #1f6feb;
  --cluster-2: #2f81f7;
  --cluster-3: #388bfd;
}

/* --- Helle Ansicht "Akademie-Tint" ----------------------------------------
   Spec 2026-08-10, Abschnitt 3. Vom Auftraggeber am 10.08.2026 aus drei
   Vorschlaegen ausgewaehlt: Flaeche mit einem Hauch Markenblau, Karten
   reinweiss.

   :root oben bleibt die DUNKLE Basis - das Produkt war immer dunkel, und ohne
   JavaScript (kein data-theme) bleibt es dabei. Der Bootstrap im <head> jeder
   Seite schreibt IMMER einen konkreten Wert nach data-theme, deshalb genuegt
   dieser eine Block: keine @media-Verdopplung der Palette, ein Ort fuer eine
   Ansicht.

   --accent/--brand/--radius/--font fehlen hier ABSICHTLICH: sie sind in beiden
   Ansichten gleich (Markenvorgabe). test/theme-tokens.test.mjs fuehrt genau
   diese vier als Ausnahmeliste und verlangt fuer JEDES andere Token einen Wert.

   Die Zahlen sind nicht nach Augenmass gewaehlt: test/theme-contrast.test.mjs
   rechnet jedes Paar gegen WCAG AA. Wer hier etwas aendert, laesst den Test
   entscheiden. */
:root[data-theme="light"] {
  --bg: #eaf2fd;
  --bg-elev: #dde8fa;
  --bg-card: #ffffff;
  --border: #c9dbf4;
  --text: #0a1e38;
  --text-dim: #4d6688;
  /* Umgekehrte Richtung: auf hellem Grund ist "heller" kein Hover-Signal. */
  --accent-hover: #0059bd;
  --accent-2: #0f5f9e;
  --warn: #8a6100;
  /* S-20: #c0392b lag als Fehlertext auf --bg knapp unter 4,5:1. */
  --danger: #b3261e;
  /* Abgedunkelt, weil die dunklen Statusfarben auf Weiss nicht lesbar sind:
     #3fb950 erreicht auf Weiss nur ~2.3:1. */
  --ist: #15702f;
  --war: #4d6688;
  --pot: #8a6100;
  --on-bar: #ffffff;
  --border-strong: #647fa6;
  --tint-on-accent: rgba(0, 0, 0, .25);
  /* Der dunkle Schatten (rgba(0,30,70,.35)) wirkt auf Weiss schmutzig. */
  --shadow: 0 2px 10px rgba(10, 50, 110, .10);
  --bg-topbar: rgba(255, 255, 255, .85);
  --row-hover: rgba(10, 30, 56, .03);
  --scroll-shadow: rgba(10, 30, 56, .16);
  --tint-accent: rgba(0, 114, 239, .07);
  --tint-accent2: rgba(15, 95, 158, .10);
  --bar-soft: rgba(0, 114, 239, .22);
  --tint-ist: rgba(21, 112, 47, .09);
  --tint-war: rgba(77, 102, 136, .13);
  --tint-pot: rgba(138, 97, 0, .10);
  --tint-danger: rgba(192, 57, 43, .07);
  --logo-filter: none;
  --sonstige: #54617a;
  /* Gold/Silber/Bronze auf Weiss: die Originaltoene erreichen dort ~1.7:1. */
  --medal-1: #8a6d00;
  --medal-2: #5f676b;
  --medal-3: #8a5420;
  --cluster-1: #1257c4;
  --cluster-2: #1a6bd8;
  --cluster-3: #2a7de8;
}

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body {
  background: var(--bg);
  color: var(--text);
  font-family: var(--font);
  font-size: 15px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}
a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }

/* Sichtbarer Fokusring (Tastaturbedienung / Screenreader) */
:focus-visible { outline: 2px solid var(--accent-hover); outline-offset: 2px; border-radius: 4px; }
a:focus-visible, .btn:focus-visible, .tab:focus-visible, .check:focus-visible,
.admin-tab:focus-visible, .area-tab:focus-visible, .nav a:focus-visible { outline: 2px solid var(--accent-hover); outline-offset: 2px; }

/* Topbar / Nav */
.topbar {
  position: sticky; top: 0; z-index: 50;
  display: flex; align-items: center; gap: 18px;
  padding: 12px 22px;
  background: var(--bg-topbar);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--border);
}
.brand { font-weight: 700; font-size: 16px; letter-spacing: .2px; white-space: nowrap; }
.brand .dot { color: var(--accent); }
/* UI-Review 19.10.2026: mit der sechsten Seite (Verlaengerungen) brach die
   Unternavigation der Geschaeftsfuehrung bei 1440 px in zwei Zeilen um und der
   Kopf wurde doppelt so hoch. Schmalerer Innenabstand, und unter 1500 px
   verzichtet die Benutzerbox auf den Namen (er steht im Tooltip der Rolle und
   im Hamburger-Menue) - so bleibt die Leiste ab etwa 1300 px einzeilig. Der
   Umbruch bleibt als Notloesung erlaubt: ein seitliches Ueberlaufen der Seite
   (gemessen bei 1120 px mit nowrap) waere schlimmer. Unter 1100 px uebernimmt
   das Hamburger-Menue. */
.nav { display: flex; gap: 2px; flex-wrap: wrap; }
.nav a {
  padding: 7px 11px; border-radius: 8px; color: var(--text-dim);
  font-weight: 500; font-size: 14px; white-space: nowrap;
}
@media (max-width: 1500px) { .userbox .uname { display: none; } }
/* Zwischen Hamburger-Grenze (1100 px) und 1400 px reicht das Logo: der
   Schriftzug "Unternehmens·Cockpit" allein kostet ~190 px, ohne ihn passt die
   Leiste der Geschaeftsfuehrung (sechs Seiten) bei 1280 px in eine Zeile. */
@media (min-width: 1101px) and (max-width: 1400px) { .topbar .brand .brand-text { display: none; } }
.nav a:hover { background: var(--bg-elev); color: var(--text); text-decoration: none; }
.nav a.active { background: var(--accent); color: #fff; }
/* Unterseite "bald": bewusst KEIN Link, siehe buildSubNavHtml in app.js - die
   Route/Datei existiert noch nicht. (Das frueher hier genannte Beispiel
   /tv-umsatz ist seit AP-R1 Task 5 keines mehr: die Seite ist in /tv
   verschmolzen und geloescht. Derzeit traegt KEINE Seite das Merkmal, nur der
   Bereich BWA als Ganzes - siehe AREAS in public/app.js.) */
.nav .nav-soon, .mm-link.nav-soon {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 7px 14px; border-radius: 8px; color: var(--text-dim);
  font-weight: 500; font-size: 14px; opacity: .6; cursor: default;
}
.mobile-menu .mm-link.nav-soon { display: flex; }
.topbar .spacer { flex: 1; }
.userbox { font-size: 13px; color: var(--text-dim); display: flex; align-items: center; gap: 10px; }
.userbox .hilfe-knopf { display: inline-flex; align-items: center; justify-content: center; width: 30px; height: 30px; border-radius: 50%;
  border: 1px solid var(--border); background: var(--bg-card); color: var(--text); font-weight: 700; font-size: 15px; text-decoration: none; flex-shrink: 0; }
.userbox .hilfe-knopf:hover { background: var(--bg-elev); text-decoration: none; }
.userbox .hilfe-knopf:focus-visible { outline: 2px solid var(--accent-hover); outline-offset: 2px; }
.userbox .role { padding: 2px 8px; border-radius: 999px; background: var(--bg-elev); border: 1px solid var(--border); font-size: 12px; letter-spacing: .2px; }

.wrap { max-width: 1280px; margin: 0 auto; padding: 24px 22px 64px; }
h1 { font-size: 22px; margin: 6px 0 2px; }
.subtitle { color: var(--text-dim); margin: 0 0 22px; font-size: 14px; }

/* Tabs (Zeitraum) */
.tabs { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 20px; }
.tab {
  padding: 8px 16px; border-radius: 999px; cursor: pointer;
  background: var(--bg-elev); border: 1px solid var(--border-strong);
  color: var(--text-dim); font-weight: 500; font-size: 14px; user-select: none;
  /* font-family/appearance zuruecksetzen, damit <button class="tab"> optisch
     identisch zum frueheren <div class="tab"> ist (Browser-Button-Defaults). */
  font-family: inherit; line-height: inherit; text-align: center;
  -webkit-appearance: none; appearance: none;
}
.tab:hover { color: var(--text); }
.tab.active { background: var(--accent); border-color: var(--accent); color: #fff; }

.custom-range { display: none; gap: 10px; align-items: center; margin: -8px 0 20px; flex-wrap: wrap; }
.custom-range.show { display: flex; }
.custom-range label { color: var(--text-dim); font-size: 13px; }
/* S-21: ALLE Textfelder (auch email/password/number/search), Auswahllisten und
   Textbereiche sehen gleich aus. Vorher traf die Regel nur date/text/select -
   ein Passwortfeld in der Verwaltung stand im Browser-Standard (weiss auf
   dunkel). Checkbox/Radio/Datei behalten ihr eigenes Aussehen. */
input:not([type=checkbox]):not([type=radio]):not([type=file]), select, textarea {
  background: var(--bg-elev); border: 1px solid var(--border-strong); color: var(--text);
  border-radius: 8px; padding: 8px 10px; font-size: 14px; font-family: var(--font);
}
input:not([type=checkbox]):not([type=radio]):not([type=file]):focus, select:focus, textarea:focus { outline: none; border-color: var(--accent); }
input:not([type=checkbox]):not([type=radio]):not([type=file]):focus-visible, select:focus-visible, textarea:focus-visible { outline: 2px solid var(--accent-hover); outline-offset: 2px; }
.btn {
  background: var(--accent); color: #fff; border: none; border-radius: 8px;
  padding: 8px 16px; font-size: 14px; font-weight: 600; cursor: pointer; font-family: var(--font);
}
.btn:hover { filter: brightness(1.08); }
.btn.ghost { background: var(--bg-elev); border: 1px solid var(--border-strong); color: var(--text); }
/* S-21: deaktiviert sieht auch deaktiviert aus - und reagiert nicht auf Hover. */
.btn:disabled, button:disabled { opacity: .45; cursor: not-allowed; }
.btn:disabled:hover { background: var(--accent); filter: none; }
.btn.ghost:disabled:hover { background: var(--bg-elev); }

/* KPI grid */
.kpis { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 14px; margin-bottom: 26px; }
.kpi {
  background: var(--bg-card); border: 1px solid var(--border); border-radius: var(--radius);
  padding: 18px 18px 16px; box-shadow: var(--shadow);
}
.kpi .label { color: var(--text-dim); font-size: 13px; font-weight: 500; margin-bottom: 6px; }
.kpi .value { font-size: 30px; font-weight: 700; letter-spacing: -.5px; }
.kpi .sub { color: var(--text-dim); font-size: 12px; margin-top: 4px; }
.kpi.accent .value { color: var(--accent-2); }

/* Cards / tables */
.grid2 { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; }
@media (max-width: 900px) { .grid2 { grid-template-columns: 1fr; } }
.card {
  background: var(--bg-card); border: 1px solid var(--border); border-radius: var(--radius);
  padding: 18px; box-shadow: var(--shadow); margin-bottom: 18px;
}
.card h2 { font-size: 15px; margin: 0 0 14px; color: var(--text); }
table { width: 100%; border-collapse: collapse; font-size: 14px; }
th, td { text-align: left; padding: 9px 10px; border-bottom: 1px solid var(--border); }
th { color: var(--text-dim); font-weight: 600; font-size: 12px; text-transform: uppercase; letter-spacing: .4px; }
tbody tr:hover { background: var(--row-hover); }
td.num, th.num { text-align: right; font-variant-numeric: tabular-nums; }

.bar { height: 6px; border-radius: 4px; background: var(--accent); }
.barwrap { background: var(--bg-elev); border-radius: 4px; overflow: hidden; height: 6px; margin-top: 5px; }

.badge { display: inline-block; padding: 2px 9px; border-radius: 999px; font-size: 12px; font-weight: 600; }
.badge.ist { background: var(--tint-ist); color: var(--ist); }
.badge.war { background: var(--tint-war); color: var(--war); }
.badge.pot { background: var(--tint-pot); color: var(--pot); }
.chip { display: inline-block; padding: 2px 8px; margin: 1px 2px; border-radius: 6px; background: var(--bg-elev); border: 1px solid var(--border); font-size: 12px; color: var(--text-dim); }

/* Filters */
.filters { display: flex; gap: 18px; flex-wrap: wrap; align-items: flex-start; margin-bottom: 18px; } /* Beschriftungen oben buendig, auch wenn die Produktauswahl zweizeilig ist */
.filter-group { display: flex; flex-direction: column; gap: 6px; }
.filter-group > span, .filter-group > label { color: var(--text-dim); font-size: 12px; font-weight: 600; text-transform: uppercase; letter-spacing: .4px; }
.checks { display: flex; gap: 6px; flex-wrap: wrap; }
.check {
  padding: 6px 12px; border-radius: 999px; cursor: pointer; user-select: none;
  background: var(--bg-elev); border: 1px solid var(--border-strong); color: var(--text-dim); font-size: 13px;
  /* wie .tab: Button-Defaults zuruecksetzen, damit <button class="check"> optisch
     identisch zum frueheren <div class="check"> aussieht. */
  font-family: inherit; line-height: inherit; text-align: center;
  -webkit-appearance: none; appearance: none;
}
.check.on { background: var(--accent); border-color: var(--accent); color: #fff; }
/* S-20: ohne opacity (sie drueckte den Kontrast unter 4,5:1), 12 px. */
.check .cnt { font-size: 12px; font-weight: 400; margin-left: 4px; }

.pager { display: flex; gap: 8px; align-items: center; justify-content: center; margin-top: 18px; }
.pager button { background: var(--bg-elev); border: 1px solid var(--border-strong); color: var(--text); border-radius: 8px; padding: 7px 13px; cursor: pointer; }
.pager button:disabled { opacity: .4; cursor: default; }

.muted { color: var(--text-dim); }
.loading { color: var(--text-dim); padding: 30px; text-align: center; }
.loading::before {
  content: ''; display: inline-block; width: 18px; height: 18px; margin-right: 10px;
  vertical-align: -4px; border: 2px solid var(--border); border-top-color: var(--accent);
  border-radius: 50%; animation: spin .7s linear infinite;
}
.loading .hint { display: block; margin-top: 8px; font-size: 12px; opacity: .85; }
@keyframes spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .loading::before { animation: none; } }
.notice { background: var(--tint-accent); border: 1px solid var(--border); color: var(--text); padding: 12px 16px; border-radius: 10px; font-size: 13px; margin-bottom: 18px; }
.notice.demo { background: var(--tint-pot); border-color: var(--pot); }
/* S-21: gemeinsame Hinweis-Varianten statt lokaler Regeln je Seite. */
.notice.warn { background: var(--tint-pot); border-color: var(--pot); }
.notice.error { background: var(--tint-danger); border-color: var(--danger); }
/* S-22: ein leerer Hinweis (noch nichts zu sagen) nimmt keinen Platz weg. */
.notice:empty { display: none; }
/* Verkauft, aber unvollstaendig (19.10.2026) */
.kpi .warnzeile { margin-top: 6px; font-size: 12px; color: var(--warn); font-weight: 600; }
.verkauf-pruefen ul { margin: 6px 0 0; padding-left: 20px; }
.verkauf-pruefen li { margin: 2px 0; }
.deal-warn { color: var(--warn); font-weight: 600; cursor: help; }

.rhvals { display: grid; grid-template-columns: repeat(24, 1fr); gap: 3px; margin-bottom: 3px; }
.rhvals > div { display: flex; flex-direction: column; align-items: center; line-height: 1.05; font-variant-numeric: tabular-nums; }
.rhvals .hvr { font-size: 11px; font-weight: 700; color: var(--accent-2); }
.rhvals .hvc { font-size: 11px; color: var(--text-dim); }
.rheat { display: grid; grid-template-columns: repeat(24, 1fr); gap: 3px; align-items: end; height: 90px; }
.rhcell { background: var(--bg-elev); border-radius: 3px; height: 100%; position: relative; overflow: hidden; }
.rhcalls { position: absolute; left: 0; right: 0; bottom: 0; background: var(--bar-soft); border-radius: 3px 3px 0 0; }
.rhreached { position: absolute; left: 0; right: 0; bottom: 0; background: var(--accent); border-radius: 3px 3px 0 0; }
.rhlegend { display: flex; gap: 16px; margin-top: 8px; font-size: 12px; color: var(--text-dim); }
.rhlegend i { display: inline-block; width: 11px; height: 11px; border-radius: 3px; margin-right: 6px; vertical-align: -1px; }
.rhaxis { display: grid; grid-template-columns: repeat(24, 1fr); gap: 3px; margin-top: 4px; font-size: 11px; color: var(--text-dim); font-variant-numeric: tabular-nums; }
.rhaxis span { text-align: center; }
.card-error { display: flex; align-items: flex-start; gap: 8px; color: var(--danger);
  background: var(--tint-danger); border: 1px solid var(--danger);
  border-radius: 10px; padding: 10px 14px; font-size: 13px; }
.card-error::before { content: '⚠'; line-height: 1.3; }

/* Map */
#map { height: 70vh; min-height: 480px; border-radius: var(--radius); border: 1px solid var(--border); }
.leaflet-popup-content { font-family: var(--font); }
.legend { display: flex; gap: 16px; margin: 12px 0; font-size: 13px; color: var(--text-dim); }
.legend .dot { display: inline-block; width: 11px; height: 11px; border-radius: 50%; margin-right: 6px; vertical-align: middle; }


/* --- Akademie-Branding ---------------------------------------------------- */
.brand { display: flex; align-items: center; gap: 10px; font-weight: 700; }
.brand .brand-logo { height: 30px; width: auto; filter: var(--logo-filter); opacity: .95; }
.brand .brand-text { font-size: 16px; letter-spacing: -.2px; }
.brand .brand-text .sub { color: var(--accent-2); font-weight: 600; }
.nav a.active { background: var(--accent); color: #fff; }
.btn, button.btn { background: var(--accent); }
.btn:hover { background: var(--accent-hover); }
.tab.active { background: var(--accent); border-color: var(--accent); }
a { color: var(--accent-2); }


/* --- Bereichsleiste (Ebene 1: Vertrieb / Buchhaltung / BWA) ---------------- */
.areabar {
  position: sticky; top: 0; z-index: 51;
  display: flex; align-items: center; gap: 6px;
  padding: 8px 22px;
  /* S-04: feste Mindesthoehe, damit die Leiste beim Nachladen der Navigation
     nicht von 17 auf 50 px springt (Layout-Sprung beim Laden). */
  min-height: 50px;
  background: var(--bg-elev);
  border-bottom: 1px solid var(--border);
}
.areabar .area-tab {
  padding: 6px 16px; border-radius: 8px; color: var(--text-dim);
  font-weight: 600; font-size: 14px; letter-spacing: .2px;
  display: inline-flex; align-items: center; gap: 6px;
}
.areabar .area-tab:hover { background: var(--bg-card); color: var(--text); text-decoration: none; }
.areabar .area-tab.active { background: var(--accent); color: #fff; }
/* S-20: 11 px in voller Textfarbe statt 10 px gedimmt (vorher unter 4,5:1). */
.areabar .area-soon, .nav .area-soon, .mobile-menu .area-soon {
  font-size: 11px; text-transform: uppercase; letter-spacing: .5px;
  background: var(--tint-war); color: var(--text);
  padding: 1px 6px; border-radius: 999px; font-weight: 700;
}
.areabar .area-tab.active .area-soon, .mobile-menu .mm-link.active .area-soon { background: var(--tint-on-accent); color: #fff; }
/* S-17: gesperrter Bereich (nur fuer Admins sichtbar, fuehrt zur
   Freischalt-Anleitung). Ausgegraut, aber lesbar - opacity nur auf dem Symbol. */
.areabar .area-tab.locked, .mobile-menu .mm-link.locked { color: var(--text-dim); font-weight: 500; }
.areabar .area-tab.locked.active, .mobile-menu .mm-link.locked.active { color: #fff; }
.area-lock { font-size: 12px; opacity: .8; }
/* Live-Tafel oeffnet einen neuen Tab (S-25): kleiner Pfeil als Hinweis. */
.ext-mark { font-size: 12px; }
/* Wenn eine Bereichsleiste da ist, klebt die Hauptleiste direkt darunter.
   S-04: vorher fest 41 px - die Leiste ist aber 50 px hoch, beim Scrollen lief
   der Inhalt 9 px weit zwischen beiden Leisten durch. renderNav() misst die
   echte Hoehe und setzt --areabar-h (auch nach einem resize). */
.areabar + .topbar { top: var(--areabar-h, 50px); }

/* Platzhalter-Seiten (Buchhaltung/BWA in Vorbereitung) */
.placeholder {
  text-align: center; padding: 80px 20px; color: var(--text-dim);
}
.placeholder .ph-icon { font-size: 52px; margin-bottom: 18px; opacity: .5; }
.placeholder h1 { color: var(--text); font-size: 26px; margin-bottom: 8px; }
.placeholder p { max-width: 520px; margin: 0 auto 6px; font-size: 15px; line-height: 1.6; }
/* S-35: eine Marke, kein Knopf - ohne Rahmen und ohne Akzentfarbe (sah vorher
   wie ein anklickbarer Knopf aus, der nichts tat). */
.placeholder .ph-badge {
  display: inline-block; margin-top: 20px; padding: 8px 18px; border-radius: 999px;
  background: var(--tint-war); border: none; color: var(--text-dim);
  font-weight: 600; font-size: 14px; cursor: default;
}


/* --- Tabellen und Kacheln auf schmalen Bildschirmen (S-22) -----------------
   Vorher: `.card table { display:block; overflow-x:auto; white-space:nowrap }`
   unter 900 px. display:block nahm der Tabelle ihre Breite - sie schrumpfte
   auf den Inhalt, die Zahlenspalte stand mitten in der Karte, und nowrap
   zwang auch lange Namen in eine Zeile (Seitenbreite 555 px statt 390 px).
   Jetzt scrollt die KARTE bzw. ein .table-scroll-Rahmen, die Tabelle bleibt
   eine Tabelle und fuellt mindestens die Breite. Nur Kopfzellen und Zahlen
   brechen nicht um. Der Schatten am Rand (background-attachment local/scroll)
   zeigt, dass es seitlich weitergeht. */
.table-scroll, .card {
  overflow-x: auto; -webkit-overflow-scrolling: touch;
}
.table-scroll {
  background:
    linear-gradient(to right, var(--bg-card) 30%, transparent) left center / 24px 100% no-repeat local,
    linear-gradient(to left, var(--bg-card) 30%, transparent) right center / 24px 100% no-repeat local,
    linear-gradient(to right, var(--scroll-shadow), transparent) left center / 10px 100% no-repeat scroll,
    linear-gradient(to left, var(--scroll-shadow), transparent) right center / 10px 100% no-repeat scroll;
}
.card table { min-width: 100%; }
th, td.num { white-space: nowrap; }

/* Handy: Tabellen mit class="table-cards" werden zu Karten je Zeile (die
   Spaltenueberschrift steht als data-label vor dem Wert). */
@media (max-width: 480px) {
  table.table-cards thead { display: none; }
  table.table-cards, table.table-cards tbody, table.table-cards tr { display: block; width: 100%; }
  table.table-cards tr { border-bottom: 1px solid var(--border); padding: 8px 0; }
  table.table-cards td { display: flex; justify-content: space-between; gap: 12px; border: none; padding: 4px 2px; text-align: right; }
  table.table-cards td::before { content: attr(data-label); color: var(--text-dim); font-size: 12px; font-weight: 600; text-align: left; }
  table.table-cards td.num { white-space: normal; }
  .kpis { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
/* Kachelwerte passen in die Kachel (ein "2.509.231,27 €" lief bei 1440 px ueber
   den Rand). */
.kpi .value { font-size: clamp(22px, 2.2vw, 30px); font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
.legend { flex-wrap: wrap; }
.legend > span { white-space: nowrap; }


/* --- Handy-Breakpoint (Hochformat, < 480px) --------------------------------
   Zusaetzlich zu den bestehenden Tablet-Breakpoints (640/860/900px). Rein
   additiv – am Desktop/Tablet-Layout aendert sich nichts. */
@media (max-width: 480px) {
  /* Globale Navigation kompakter, damit sie umbricht statt abgeschnitten zu
     werden. .nav/.areabar haben bereits flex-wrap bzw. wrappen ueber .topbar. */
  .topbar { flex-wrap: wrap; gap: 8px 12px; padding: 10px 14px; }
  .areabar { padding: 7px 14px; }
  .areabar .area-tab { padding: 5px 10px; font-size: 13px; }
  .nav a { padding: 6px 10px; font-size: 13px; }
  .brand .brand-text { font-size: 14px; }
  .wrap { padding: 18px 14px 48px; }

  /* Filter nutzen die volle Breite statt gequetscht zu wirken (flex-wrap ist
     bereits gesetzt; hier nur die einzelnen Gruppen auf 100% zwingen). */
  .filters { gap: 12px; }
  .filter-group { width: 100%; }
  .filter-group select,
  .filter-group input[type=text],
  .filter-group input[type=date] { width: 100%; }
}


/* --- Mobiles Hamburger-Menu -------------------------------------------------
   Breakpoint: 768px. Gewaehlt, weil die Bereichsleiste (.areabar, nowrap) auf
   jedem Handy (max. ~430px breit) ueberlaeuft; 768px ist der gaengige
   Tablet/Handy-Umbruch. Der bereits vorhandene 900px-Breakpoint betrifft nur
   das .grid2-Layout und bleibt davon unberuehrt. Oberhalb 768px: Button per
   display:none unsichtbar, beide Navi-Leisten sichtbar -> Desktop unveraendert. */
.hamburger {
  display: none; /* Standard = Desktop: unsichtbar. */
  background: var(--bg-elev); border: 1px solid var(--border-strong); border-radius: 8px;
  width: 42px; height: 38px; cursor: pointer; padding: 0;
  align-items: center; justify-content: center; flex-shrink: 0;
}
.hamburger .hb-bars, .hamburger .hb-bars::before, .hamburger .hb-bars::after {
  content: ''; display: block; width: 20px; height: 2px; background: var(--text);
  border-radius: 2px; transition: transform .2s ease, opacity .2s ease;
}
.hamburger .hb-bars { position: relative; }
.hamburger .hb-bars::before { position: absolute; left: 0; top: -6px; }
.hamburger .hb-bars::after { position: absolute; left: 0; top: 6px; }
/* Offen -> X. */
.hamburger.open .hb-bars { background: transparent; }
.hamburger.open .hb-bars::before { transform: translateY(6px) rotate(45deg); }
.hamburger.open .hb-bars::after { transform: translateY(-6px) rotate(-45deg); }

.mobile-menu {
  display: none; /* Auf Desktop immer aus (auch mit .open) -> siehe Media-Query. */
  position: fixed; left: 0; right: 0; top: 56px; z-index: 60;
  background: var(--bg-card); border-bottom: 1px solid var(--border);
  box-shadow: var(--shadow); padding: 10px 14px 18px;
  max-height: calc(100vh - 56px); overflow-y: auto;
}
.mobile-menu .mm-head {
  color: var(--text-dim); font-size: 11px; font-weight: 700; text-transform: uppercase;
  letter-spacing: .5px; margin: 10px 4px 6px;
}
.mobile-menu .mm-link {
  display: block; padding: 11px 14px; border-radius: 8px; color: var(--text-dim);
  font-weight: 600; font-size: 15px; margin-bottom: 2px;
}
.mobile-menu .mm-link:hover { background: var(--bg-elev); color: var(--text); text-decoration: none; }
.mobile-menu .mm-link.active { background: var(--accent); color: #fff; }
.mobile-menu .mm-sep { border: none; border-top: 1px solid var(--border); margin: 12px 0 4px; }

/* S-04: Hamburger-Breakpoint 1100 px statt 768 px. Zwischen 768 und 1100 px
   (Tablet quer, kleine Laptops) passte die Bereichsleiste samt Unternav nicht
   mehr in eine Zeile, der Kopf wurde zwei- bis dreizeilig. Die Grenze steht
   ein zweites Mal in public/app.js (MOBIL_BREAKPOINT_PX) - beide gleich halten.
   Der Hamburger sitzt im DOM hinter der Userbox (renderMobileMenu), also
   rechts in derselben Zeile - keine CSS-order mehr, damit die Tab-Reihenfolge
   der sichtbaren Reihenfolge entspricht (S-15). */
@media (max-width: 1100px) {
  .hamburger { display: inline-flex; }
  .topbar .nav { display: none; }
  /* Beide Navi-Leisten wandern ins Hamburger-Menu. */
  .areabar { display: none; }
  /* Ohne sichtbare Bereichsleiste klebt die Topbar wieder ganz oben. */
  .areabar + .topbar { top: 0; }
  /* Panel nur im geoeffneten Zustand einblenden. */
  .mobile-menu.open { display: block; }
}
/* Handy: EINE Zeile (Logo + Hamburger). Name, Rolle, Farbschema und Abmelden
   stehen im Mobilmenue (renderMobileMenu). Vorher war der klebende Kopf auf
   390 px 148 px hoch - fast ein Fuenftel des Bildschirms. */
@media (max-width: 768px) {
  .topbar { flex-wrap: nowrap; gap: 12px; padding-top: 9px; padding-bottom: 9px; }
  .brand { flex: 1 1 auto; min-width: 0; }
  .brand .brand-text { overflow: hidden; text-overflow: ellipsis; }
  .topbar .userbox { display: none; }
  .topbar .spacer { display: none; }
}
/* Quer gehaltenes Handy (844 x 390): nichts klebt, sonst bliebe vom Inhalt
   kaum etwas sichtbar. */
@media (max-height: 500px) {
  .areabar, .topbar { position: static; }
}
/* S-23: Tippziele mindestens 44 px auf Touch-Geraeten und schmalen Schirmen. */
@media (pointer: coarse), (max-width: 768px) {
  .btn, .tab, .check, .pager button, .quickpicks button, .admin-tab,
  input:not([type=checkbox]):not([type=radio]):not([type=file]), select { min-height: 44px; }
  .hamburger { width: 44px; height: 44px; }
  .userbox .themebtn { min-width: 44px; min-height: 44px; justify-content: center; }
  .checks { gap: 8px; }
  /* Kaestchen: groesser, und die Beschriftung (bzw. .tap-check in Tabellenzellen)
     ist die 44-px-Klickflaeche. */
  input[type=checkbox], input[type=radio] { width: 22px; height: 22px; }
  label:has(> input[type=checkbox]), label:has(> input[type=radio]) { min-height: 44px; display: inline-flex; align-items: center; gap: 8px; }
  .tap-check { min-width: 44px; justify-content: center; cursor: pointer; }
}

/* Angemeldet-Abschnitt am Ende des Mobilmenues (S-14/S-15). */
.mobile-menu .mm-user { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; padding: 6px 4px 0; color: var(--text-dim); font-size: 14px; }
.mobile-menu .mm-user .mm-name { color: var(--text); font-weight: 600; }
.mobile-menu .mm-user .role { padding: 2px 8px; border-radius: 999px; background: var(--bg-elev); border: 1px solid var(--border); font-size: 12px; }
.mobile-menu .mm-user .themebtn { display: inline-flex; align-items: center; gap: 5px; padding: 6px 12px; border-radius: 999px; background: var(--bg-card); border: 1px solid var(--border-strong); color: var(--text-dim); font-size: 13px; font-family: inherit; cursor: pointer; min-height: 44px; }


/* --- Umschalter Hell/Dunkel/OS-Design (Spec 2026-08-10, Abschnitt 8) ------
   Sitzt in der .userbox, wird von renderUser() in public/app.js gebaut. */
.userbox .themebtn {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 3px 10px; border-radius: 999px;
  background: var(--bg-card); border: 1px solid var(--border);
  color: var(--text-dim); font-size: 12px; font-family: inherit;
  line-height: 1.6; cursor: pointer; white-space: nowrap;
  -webkit-appearance: none; appearance: none;
}
.userbox .themebtn:hover { color: var(--text); border-color: var(--accent); }
.userbox .themebtn .tsym { font-size: 13px; line-height: 1; }
/* Auf dem Handy nur das Symbol - die Kopfzeile ist dort ohnehin knapp. */
@media (max-width: 480px) { .userbox .themebtn .tlabel { display: none; } }


/* --- Betriebs-Banner (Datenquelle / Ersteinrichtung) ----------------------
   Vorher als inline cssText in public/app.js und public/kunden-liste.html mit
   dunklen Literalen (#3a1414 / #3a2f13 / #ffb4ad …), die auf hellem Grund
   unlesbar waren. Farbe kommt jetzt aus den Tokens; die Links erben sie ueber
   currentColor, damit kein zweiter Farbwert gepflegt werden muss. */
.topbanner { border-bottom: 1px solid; padding: 10px 18px; font-size: 13px; text-align: center; }
.topbanner a { color: currentColor; text-decoration: underline; }
/* S-20: DECKENDER Grund (Tint als Verlauf ueber --bg-card). Der Tint allein
   war durchsichtig und lag auf --bg - hell nur 4,31:1; gerechnet in
   test/theme-contrast.test.mjs ("Balken ... deckend auf Karte"). */
.topbanner.quelle { background: linear-gradient(var(--tint-danger), var(--tint-danger)), var(--bg-card); color: var(--danger); border-bottom-color: var(--danger); }
.topbanner.setup { background: linear-gradient(var(--tint-pot), var(--tint-pot)), var(--bg-card); color: var(--pot); border-bottom-color: var(--pot); }
/* Gleiche Farben, aber als abgesetzter Kasten im Inhalt (Kundenliste). */
.boxbanner {
  background: var(--tint-danger); color: var(--danger);
  border: 1px solid var(--danger); border-radius: 10px;
  padding: 14px; margin: 16px; font-size: 13px;
}


/* --- Gemeinsame Bausteine aus public/app.js -------------------------------- */

/* Nur fuer Screenreader sichtbar (z. B. "(gesperrt)", "oeffnet neuen Tab"). */
.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;
}
/* S-15: Sprunglink "Zum Inhalt" - erst bei Tastaturfokus sichtbar. */
.skip { position: absolute; left: -999px; top: 8px; z-index: 100; padding: 8px 14px; border-radius: 8px; background: var(--accent); color: #fff; font-weight: 600; }
.skip:focus { left: 12px; top: 8px; }

/* S-05: ruhiges Nachladen - der alte Inhalt bleibt stehen, halbtransparent. */
.is-loading { opacity: .5; pointer-events: none; transition: opacity .15s; }
@media (prefers-reduced-motion: reduce) { .is-loading { transition: none; } }

/* S-04/S-14: Name in der Userbox mit Auslassung, Abmelden als Knopf. */
.userbox .uname { max-width: 22ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.btn.logout { padding: 5px 12px; font-size: 13px; font-weight: 600; }
.btn.logout:hover { text-decoration: none; }
/* S-16: das Logo ist der Weg zur Startseite. */
.brand a:hover .brand-text, .brand a:focus-visible .brand-text { text-decoration: underline; }

/* S-19: "Daten von 14:51" unter der Ueberschrift (nicht mehr im h1). */
.stand { color: var(--text-dim); font-size: 12px; margin: 0 0 12px; }

/* S-03: Fehlerzustand mit technischem Detail und "Erneut versuchen". */
.card-error { flex-wrap: wrap; }
.card-error .fehler-text { flex: 1 1 240px; }
.card-error details { flex-basis: 100%; color: var(--text-dim); font-size: 12px; }
.card-error details summary { cursor: pointer; }
.card-error .btn { margin-left: auto; }
/* S-03/S-17: Kein-Zugriff-Zustand (Mitarbeiter: Aussage, Admin: Schritte). */
.kein-zugriff { max-width: 640px; }
.kein-zugriff ol { padding-left: 20px; margin: 8px 0 0; }
.kein-zugriff li { margin-bottom: 6px; }

/* S-18: Meldung unter dem eigenen Zeitraum. */
.zeitraum-fehler { color: var(--danger); font-size: 13px; flex-basis: 100%; }
.zeitraum-fehler:empty { display: none; }

/* S-24: Zusammenfassung unter der Erreichbarkeits-Heatmap. */
.rhsumme { color: var(--text-dim); font-size: 12px; margin-top: 6px; }
