/* ============================================
   ShopOS · Global Design System
   Inspired by: deep black, high contrast,
   rounded cards, colored accents
   ============================================ */

/* Manrope – App-Schrift seit Design v2 (22.07.), selbst gehostet
   (DSGVO: keine Anfrage an Google-Fonts-CDN, keine IP an Google/US).
   Variable Font: eine Datei deckt Gewichte 200–800 ab. Die fetten
   Schnitte (700/800) tragen den v2-Look – Zahlen, Titel, Labels. */
@font-face {
  font-family: 'Manrope';
  font-style: normal;
  font-weight: 200 800;
  font-display: swap;
  src: url('/fonts/manrope-latin.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;
}
@font-face {
  font-family: 'Manrope';
  font-style: normal;
  font-weight: 200 800;
  font-display: swap;
  src: url('/fonts/manrope-latin-ext.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;
}

/* Inter – Vorgänger-Schrift, bleibt als Fallback deklariert (Dateien liegen weiter
   in /fonts). Nichts referenziert sie mehr aktiv; kann mit dem v2-Abschluss weg. */
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 300 800;
  font-display: swap;
  src: url('/fonts/inter-latin.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;
}
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 300 800;
  font-display: swap;
  src: url('/fonts/inter-latin-ext.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;
}

:root {
  /* ═══ DESIGN v2 (22.07.) · Graphit statt Navy ═══
     Palette aus den Claude-Design-Screens (.claude/design-v2/screens.html).
     Die TOKEN-NAMEN sind unverändert – jede Seite fährt automatisch mit.
     Kontraste unten sind gemessen (WCAG), nicht geschätzt. */

  /* Core Backgrounds – Graphit, kaum gesättigt */
  --bg:        #0c0e13;   /* Seite */
  --bg2:       #15181f;   /* Karten */
  --bg3:       #101318;   /* eingesenkte Boxen IN Karten, Hover */
  --bg4:       #0a0c11;   /* tiefste Fläche (inaktive Tage, Skeleton) */

  /* Borders. v2 trennt fast nur noch über Fläche + Haarlinie;
     --border2/--border3 bleiben absichtlich == --bg2/--bg3 (Invariante von v1:
     "unsichtbar im Dark" – Regeln, die darauf bauen, brechen so nicht). */
  --border:    #232833;
  --border2:   #15181f;
  --border3:   #101318;
  /* Haarlinien-Trenner in Listen/Karten (v2-Signatur: rgba statt Vollton,
     damit dieselbe Linie auf Karte UND Sheet funktioniert). */
  --hairline:  rgba(255,255,255,.06);
  /* Rand von BEDIENELEMENTEN (Eingabefeld, Auswahlfeld, Textarea) – nicht von
     Dekoration. Genau diese Trennung fehlte vorher: derselbe kraeftige Rand lag
     auf Boxen, Zeilen und KV-Trennlinien und machte Sheets unruhig.
     Dekorative Linien nehmen jetzt --border, Bedienelemente diesen Token.

     Kurzzeitig war das hier ein Alias auf --border (19.07.). Das war falsch:
     --border ist auf --bg2 zu leise fuer eine Feldkante, und die Basisregel von
     .form-input stand ohnehin auf --border2 – im Dark exakt --bg2, also gar kein
     Rand. Eingabefelder im Sheet hatten dadurch Kontrast 1.00 zum Untergrund und
     waren schlicht unsichtbar. Ein eigener Token fuer Feldkanten ist berechtigt. */
  --border-strong: #3a4150;

  /* Sheet-Flaechen · Design v2 „Sheet-Vorlage" (23.07., .claude/design-v2/sheets.html).
     UMGEKEHRT zum alten „Schiefer": das Sheet ist jetzt DUNKLER als die Karten
     (#12151c, zwischen Seite #0c0e13 und Karte #15181f). Getrennt wird ueber den
     abgedunkelten Scrim + den oberen Schatten. Felder/Boxen im Sheet sind HELLER
     als das Sheet (#252b36) und bleiben dadurch rahmenlos sichtbar.
     REGEL bleibt: Kontrast Feld/Sheet >= 1.25. Gemessen (23.07.): Feld/Sheet 1.29
     (dark) / 1.29 (light). Der Mock nutzt #1c2028 (nur 1.12) – bewusst leicht
     angehoben, sonst verschwinden leere Felder. Werte immer nachmessen. */
  --surface-sheet:  #12151c;
  --surface-sunken: #252b36;
  --surface-input:  #252b36;
  /* Zieh-Griff oben am Sheet. War #2a3a5a – der letzte hartcodierte Rest der alten
     Sheet-Welt und nach dem Zusammenlegen der einzige blaue Fleck im Sheet; er las
     sich als "Streifen in der alten Hintergrundfarbe" (19.07. gemeldet).
     Jetzt aus dem neutralen Grau der Textskala gemischt: kein Blaustich, und der
     Light Mode kommt automatisch mit, weil --text3 dort ebenfalls neutral ist. */
  --handle:         color-mix(in srgb, var(--text3) 42%, transparent);

  /* Text – v2-Hellskala. ACHTUNG (gilt weiter): --text2 ist im Dark == Akzent,
     also NICHT neutral. Neutrale Zahlen/Texte nehmen --text. */
  --text:      #eef2fb;
  --text2:     #7fa5ff;
  --text3:     #8892a6;   /* gemessen: 5.67 auf Karte, 5.21 auf Sheet */
  --text-label: #8892a6;  /* Feld-Labels in Sheets */
  --text-muted: #98a6bd;  /* Hinweise/Sekundärtext in Sheets.
                             Gemessen: 6.62 auf Sheet, 5.23 in der Input-Box. */

  /* Marke – nur der Login-Moment (Gradient/Button/Focus auf index.html).
     Bewusst NICHT --accent: die Login-Seite hat kein Dock und keine Sidebar,
     sie steht fuer sich. Innerhalb der App gilt --accent. */
  --brand:         #5b6ef5;

  /* Shops – PF blau, KA grün (Kernkonzept, s. CLAUDE.md). Zieht sich durch
     6 Seiten und war überall anders: PF mal #2563eb, #1d4ed8 oder #60a5fa;
     KA mal #047857, #16a34a oder #22c55e. Die tatsächlich gerenderte Farbe
     im Schichtplaner war aber längst --accent bzw. --green (die Tailwind-
     Regeln davor waren toter Code) – deshalb bauen die Tokens darauf auf.
     Light-Werte kommen automatisch mit, weil --accent/--green sie haben. */
  --shop-pf:       var(--accent);
  --shop-ka:       var(--green);

  /* Accent – v2-Blaufamilie aus den Screens:
     #7fa5ff = Text/Icons/aktive Nav (hell), #5b8cff = gefuellte Flaechen/Balken,
     #3a6bff = tiefes Ende fuer Verlaeufe. */
  --accent:        #7fa5ff;
  --accent2:       #5b8cff;
  --accent-deep:   #3a6bff;
  /* Tint-Flaeche fuer Badges/Chips/Hover – ausschliesslich background, nie Text. */
  --accent-light:  rgba(91,140,255,.14);
  --accent-border: rgba(91,140,255,.45);
  --accent-bg:     rgba(91,140,255,.10);

  /* Text AUF einer gefuellten Akzent-/Gruenflaeche (Primaer-Button, aktiver Toggle,
     Heute-Marker). Muss mit dem Theme wechseln: im Dark sind --accent (#7eb0ff) und
     --green (#22d3a0) HELL, weisse Schrift darauf ergibt Kontrast 2.20 bzw. 1.95 –
     unter jeder Lesbarkeitsschwelle. Im Light sind beide dunkel, da stimmt Weiss.
     Vorher stand ueberall hart color:#fff, was nur im Light Mode richtig war. */
  --on-accent:     #071427;
  --on-green:      #04231a;

  /* Status Colors – v2: Text-Ton hell, Fill-Ton eine Stufe kraeftiger.
     --green-fill/--accent2 fuer Balken & gefuellte Flaechen (wie in den Screens:
     Text #4ade9a, Balken #34d399). */
  --green:        #4ade9a;
  --green-fill:   #34d399;
  --green-bg:     rgba(52,211,153,.14);
  --green-border: rgba(52,211,153,.40);

  --red:        #ff6b7a;
  --red-bg:     rgba(255,107,122,.13);
  --red-border: rgba(255,107,122,.40);

  /* Amber aus den Screens (VVL-Bonus, Warnung) */
  --yellow:        #f0a500;
  --yellow-bg:     rgba(240,165,0,.13);
  --yellow-border: rgba(240,165,0,.40);

  --purple:        #b18bff;
  --purple-bg:     rgba(177,139,255,.13);
  --purple-border: rgba(177,139,255,.40);

  --orange:        #f5813b;
  --orange-bg:     rgba(245,129,59,.13);

  /* Fortschritts-Track (leerer Balken) – heller als die Karte, gemessen 1.17 */
  --track:         #22262e;

  /* ═══ Band – der farbige Modul-Kopf (Design v2) ═══
     Gradient identisch in Dark UND Light (o2-Blau-Familie); auf dem Band gelten
     eigene "on-band"-Farben statt der Textskala. */
  --band-grad:        linear-gradient(160deg, #2f5bd8, #3a52c8);
  /* Oberkante des Verlaufs – fuer theme-color-Metas und den Statusleisten-
     Streifen (body.ui-v2::before), damit die OS-Leiste ins Band uebergeht. */
  --band-top:         #2f5bd8;
  --on-band:          #ffffff;
  --on-band-dim:      rgba(255,255,255,.8);
  --on-band-faint:    rgba(255,255,255,.7);
  --band-tint:        rgba(255,255,255,.16);  /* Icon-Kacheln, Pills auf dem Band */
  --band-tint-strong: rgba(255,255,255,.2);
  --band-line:        rgba(255,255,255,.2);   /* Trennlinie im Band */

  /* Shadows */
  --shadow-sm: 0 2px 8px #00000040;
  --shadow-md: 0 4px 20px #00000060;
  --shadow-lg: 0 8px 40px #00000080;
  --shadow-accent: 0 4px 24px rgba(91,140,255,.22);

  /* Radius */
  --radius-xs: 6px;
  --radius-sm: 10px;
  --radius:    14px;
  --radius-lg: 20px;
  --radius-xl: 28px;

  /* Typography */
  --font: 'Manrope', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;

  /* Ebenen – benannt statt geraten. Vorher lagen die Sheets wild zwischen
     201 und 1301, je nach Seite. Reihenfolge von unten nach oben:
     Topbar(40) < Dock/Nav(100) < Modal(200) < Sheet(900/901)
     < Modal-ueber-Sheet(950) < Toast(9999) */
  --z-topbar:      40;
  --z-nav:         100;
  --z-modal:       200;
  --z-overlay:     900;
  --z-sheet:       901;
  /* Bestaetigung, die AUS einem offenen Sheet kommt (z.B. "Buchung loeschen?").
     Ein normales Modal (200) laege hinter dem Sheet-Scrim (900): der Dialog waere
     unsichtbar-abgedunkelt und unklickbar, der naechste Tap traefe den Scrim und
     schloesse nur das Sheet. Wer ein Modal aus einem Sheet oeffnet: .over-sheet. */
  --z-modal-sheet: 950;
  --z-toast:       9999;
}

/* ═══════════════════════════════════════════════
   LIGHT MODE  ·  aktiv via  <html data-theme="light">
   Dark bleibt Default (:root oben). Nur Variablen +
   wenige hartcodierte Stellen werden hier überschrieben.
   Palette orientiert an o2-Blau (#1C5BC7).
   ═══════════════════════════════════════════════ */
:root[data-theme="light"] {
  /* Hintergründe & Flächen – v2, Werte aus dem Light-Mock
     (.claude/design-v2/screens-light.html): Seite #f4f6fa, Karte #fff,
     eingesenkt #eef1f6. */
  --bg:   #F4F6FA;   /* Seiten-Hintergrund */
  --bg2:  #FFFFFF;   /* Karten, Tiles */
  --bg3:  #EEF1F6;   /* Inputs, verschachtelte Flächen, Hover */
  --bg4:  #E6E9EF;   /* tiefste Fläche (Autofill, Skeleton-Mid) */

  /* Ränder */
  --border:  #DFE3EA;
  --border2: #E9ECF2;
  --border3: #F1F3F7;
  --hairline: rgba(20,28,40,.07);
  /* Feldkante im Light Mode: auf Weiss reicht ein Hauch mehr als --border. */
  --border-strong: #C9CFDA;

  /* Sheet im Light Mode: das Sheet ist hier die hellste Flaeche (Weiss), die
     Abstufung geht also nach UNTEN. --bg3 waere dafuer zu nah an Weiss
     (Kontrast ~1.06) – ohne Rahmen verschwaende das Feld. #DEE3EC ergibt 1.29
     (gemessen 22.07.) und liegt damit gleichauf mit dem Dark-Wert. */
  --surface-sheet:  var(--bg2);
  --surface-sunken: #DEE3EC;
  --surface-input:  #DEE3EC;
  /* --handle bewusst NICHT ueberschrieben: die color-mix-Formel aus :root loest
     sich hier mit dem hellen --text3 auf und ergibt automatisch den richtigen Ton. */

  /* Text – v2: neutrales Anthrazit statt Navy. AA-gemessen (22.07.):
     --text3 4.94 auf --bg / 5.63 auf Karte; --text-muted 4.95 in der Box. */
  --text:  #151A23;
  --text2: #5A6472;
  --text3: #5E6878;
  --text-label: #5A6472;
  --text-muted: #56606E;

  /* Akzent – o2-Blau (bleibt der Anker im Light Mode) */
  --accent:        #1C5BC7;
  --accent2:       #164BA6;   /* Hover/dunkler, zugleich Fill-Ton */
  --accent-deep:   #164BA6;
  --accent-light:  #DCE8FB;   /* Tint-Fläche: Badges, Info, Focus-Ring */
  --accent-border: rgba(28,91,199,0.22);
  --accent-bg:     #E6EEFB;

  /* Hier sind --accent/--green dunkel → Weiss ist richtig (s. Dark-Block oben) */
  --on-accent:     #FFFFFF;
  --on-green:      #FFFFFF;

  /* Status. Text-Töne AA-geprüft (dunkel); FILL-Töne heller wie im Mock, damit
     Balken/gefüllte Flächen dieselbe Optik wie Dark haben. */
  --green: #15733F;  --green-fill: #1E9E5E;  --green-bg: #DFF3E7;  --green-border: #BCE3CC;
  --red:   #B42318;  --red-bg:   #FBE3E1;  --red-border:   #F3C9C4;
  /* #B45309 verfehlte AA: 4.41 auf dem eigenen Abzeichen-Ton, 4.35 sogar auf
     dem Seitenhintergrund. #A34A08 -> 5.21 / 5.13. */
  --yellow:#A34A08;  --yellow-bg:#FCEFD6;  --yellow-border:#F0DCB2;
  --purple:#6D28D9;  --purple-bg:#EDE4FC;  --purple-border:#DAC9F5;
  --orange:#C2410C;  --orange-bg:#FBE7D6;

  /* Fortschritts-Track */
  --track: #E3E7EE;
  /* Band-Tokens bewusst NICHT überschrieben: der blaue Modul-Kopf ist in beiden
     Modi identisch (weiße Schrift auf o2-Blau, Kontrast 5.8–6.5). */

  /* Schatten – weich & bläulich statt schwarz */
  --shadow-sm: 0 1px 3px rgba(21,40,80,0.06), 0 1px 2px rgba(21,40,80,0.07);
  --shadow-md: 0 4px 16px rgba(21,40,80,0.10);
  --shadow-lg: 0 12px 40px rgba(21,40,80,0.16);
  --shadow-accent: 0 4px 18px rgba(28,91,199,0.22);
}
/* Pre-Paint-Hintergrund (verhindert Dark-Flash) */
html[data-theme="light"] { background: #EEF0F4; }
/* Hartcodierte Glow-Schatten der Primär-Buttons im Light Mode dämpfen */
:root[data-theme="light"] .btn-primary:hover { box-shadow: 0 6px 22px rgba(28,91,199,0.26); }
:root[data-theme="light"] .btn-primary { box-shadow: 0 2px 10px rgba(28,91,199,0.20); }

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

html { font-size: 15px; background: var(--bg); }

/* Scrollbar ausblenden */
* { scrollbar-width: none; -ms-overflow-style: none; }
*::-webkit-scrollbar { display: none; }

body {
  font-family: var(--font);
  background: var(--bg);
  color: var(--text);
  min-height: 100vh;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  /* Page Transition wird komplett via JS in utils.js gesteuert */
}

/* Home-Indicator-Bereich abdecken – nur Mobile (env() = 0 auf Android, daher fixe Hoehe) */
@media (max-width: 768px) {
  body::after {
    content: "";
    position: fixed;
    bottom: 0; left: 0; right: 0;
    height: 60px;
    background: var(--bg);
    z-index: 49;
    pointer-events: none;
  }
}

/* ── Autofill Fix ── */
input:-webkit-autofill,
input:-webkit-autofill:hover,
input:-webkit-autofill:focus {
  -webkit-box-shadow: 0 0 0 1000px var(--bg4) inset !important;
  -webkit-text-fill-color: var(--text) !important;
  caret-color: var(--text) !important;
  transition: background-color 5000s ease-in-out 0s;
}

/* ── Typography ── */
h1, h2, h3, h4 { font-weight: 700; letter-spacing: -0.03em; line-height: 1.2; }
p { line-height: 1.6; color: var(--text2); }
a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }

/* ── Cards ── */
.card {
  background: var(--bg2);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
  padding: 20px;
  box-sizing: border-box;
  min-width: 0;
}


/* Accent top border on cards */

/* ── Buttons ── */
/* Sicherheitsnetz: ein Icon ohne eigene Groessenangabe skaliert im Button auf
   seine viewBox hoch (hier: 410px statt 16px – im Kalender-Sheet passiert, als
   eine seitenlokale "svg"-Regel entfiel). Greift NUR ohne width-Attribut,
   laesst also jedes bewusst dimensionierte Icon unberuehrt. */
.btn svg:not([width]) { width: 16px; height: 16px; flex-shrink: 0; }

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  padding: 9px 18px;
  border-radius: var(--radius-sm);
  font-size: 13px;
  font-weight: 600;
  font-family: var(--font);
  cursor: pointer;
  border: none;
  transition: all 0.15s ease;
  white-space: nowrap;
  letter-spacing: -0.01em;
}

.btn-primary {
  background: var(--accent);
  color: var(--on-accent);
  box-shadow: var(--shadow-accent);
}
.btn-primary:hover { background: var(--accent2); transform: translateY(-1px); box-shadow: 0 6px 28px color-mix(in srgb, var(--accent) 25%, transparent); }
.btn-primary:active { transform: translateY(0); }

.btn-secondary {
  background: var(--bg3);
  color: var(--text2);
  border: 1px solid var(--border2);
}
.btn-secondary:hover { background: var(--bg4); color: var(--text); border-color: var(--border3); }

.btn-ghost {
  background: transparent;
  color: var(--text2);
  border: 1px solid var(--border);
}
.btn-ghost:hover { background: var(--bg3); color: var(--text); }

.btn-danger {
  background: var(--red-bg);
  color: var(--red);
  border: 1px solid var(--red-border);
}
.btn-danger:hover { background: var(--red); color: #fff; }

.btn-sm { padding: 6px 12px; font-size: 12px; border-radius: var(--radius-xs); }

/* ── Button Loading State ── */
.btn-loading {
  pointer-events: none;
  opacity: 0.75;
  position: relative;
  color: transparent !important;
}

.btn-loading::after {
  content: '';
  position: absolute;
  width: 14px;
  height: 14px;
  border: 2px solid currentColor;
  border-color: #fff #fff #fff transparent;
  border-radius: 50%;
  animation: btnSpin 0.6s linear infinite;
  /* currentColor ist transparent wegen oben — fix: */
  border-color: rgba(255,255,255,0.9) rgba(255,255,255,0.9) rgba(255,255,255,0.9) transparent;
}

.btn-loading.btn-secondary::after,
.btn-loading.btn-ghost::after {
  border-color: var(--text2) var(--text2) var(--text2) transparent;
}

.btn-loading.btn-danger::after {
  border-color: var(--red) var(--red) var(--red) transparent;
}

@keyframes btnSpin {
  to { transform: rotate(360deg); }
}

/* ── Inputs ── */
.input, .form-input {
  width: 100%;
  padding: 10px 14px;
  /* RAHMENLOS – die Flaeche macht das Feld lesbar, nicht eine Kante
     (DESIGN.md Prinzip 2: Weissraum statt Linien).
     Zwei Irrwege davor, beide am 19.07.: erst --border2 (im Dark exakt --bg2,
     also gar kein Rand -> Feld unsichtbar), dann ein sichtbarer Rand als Pflaster
     -- der widersprach genau dem Prinzip, das die App gerade eingefuehrt hatte.
     Richtig ist: --surface-input hat gegen JEDE Flaeche, auf der ein Feld liegen
     kann (Karte --bg2 wie Sheet --surface-sheet), Kontrast >= 1.25. */
  background: var(--surface-input);
  border: none;
  border-radius: var(--radius-sm);
  color: var(--text);
  font-size: 16px; /* min 16px verhindert iOS Auto-Zoom beim Fokus */
  font-family: var(--font);
  outline: none;
  transition: border-color 0.15s, box-shadow 0.15s, transform 0.15s;
}

/* Ohne Rahmen traegt den Fokus allein der Ring. Der innere 1px-Ring ersetzt die
   frueher gefaerbte Kante (border-color greift bei border:none nicht mehr),
   der aeussere 3px-Hof macht ihn auch auf dunklem Grund eindeutig.
   Nicht --accent-light: das ist eine Tint-FLAECHE und als Ring zu schwach. */
.input:focus, .form-input:focus {
  box-shadow: inset 0 0 0 1px var(--accent),
              0 0 0 3px color-mix(in srgb, var(--accent) 30%, transparent);
  transform: translateY(-1px);
}

.input::placeholder, .form-input::placeholder { color: var(--text3); }

/* Auswahlfeld: eigener Pfeil statt des System-Widgets, damit ein <select> genauso
   aussieht wie ein <input>. Lag vorher als Kopie in kalender.html und
   schichtplaner.html – mit je eigener, hartcodierter Pfeilfarbe (#7a92ba bzw.
   #5a7099), die im Light Mode beide falsch waren.
   Die Farbe muss hier ausnahmsweise zweimal als Hex stehen: eine data:-URI kann
   kein var(--…) aufloesen. Die Werte sind --text3 aus beiden Modi. */
select.input, select.form-input {
  cursor: pointer;
  -webkit-appearance: none; appearance: none;
  padding-right: 38px;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%238090aa' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'><polyline points='6 9 12 15 18 9'/></svg>");
  background-repeat: no-repeat;
  background-position: right 12px center;
}
:root[data-theme="light"] select.input,
:root[data-theme="light"] select.form-input {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%2364748B' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'><polyline points='6 9 12 15 18 9'/></svg>");
}

.input:disabled, .form-input:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

/* Input with icon */
.input-wrap { position: relative; }
.input-wrap .form-input { padding-right: 42px; }

/* ── Badges ── */
.badge {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 3px 10px;
  border-radius: 20px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.01em;
}


/* Role badges */
.badge-superadmin { background: var(--purple-bg); color: var(--purple); border: 1px solid var(--purple-border); }
.badge-admin      { background: var(--accent-light); color: var(--accent); border: 1px solid var(--accent-border); }
.badge-mitarbeiter{ background: var(--bg3); color: var(--text3); border: 1px solid var(--border2); }
.badge-aktiv      { background: var(--green-bg); color: var(--green); border: 1px solid var(--green-border); }
.badge-inaktiv    { background: var(--red-bg); color: var(--red); border: 1px solid var(--red-border); }

/* ── Semantische Abzeichen-Farben ────────────────────────────────────────
   EINE Zuordnung fuer die ganze App. Vorher gab es vier Abzeichen-Systeme
   (10px GROSS / 12px eckig / 11px mit Rahmen / 9px Pille) und derselbe Typ
   hatte je nach Seite eine andere Farbe: "Wunschfrei" war in anfragen blau,
   im Dashboard gelb; "Wunschschicht" sogar hartkodiert (#3b5bdb).
   Dashboards Variante baute ausserdem `var(--green)20` zusammen – ungueltiges
   CSS, das Abzeichen rendete deshalb ganz ohne Fuellung.
   Bedeutung laut CLAUDE.md: gruen=ok, rot=Alarm, gelb=Warnung/Wunschfrei,
   blau=Schicht/Termin, grau=Randnotiz. */
.badge-green   { background: var(--green-bg);    color: var(--green);  border: 1px solid var(--green-border); }
.badge-red     { background: var(--red-bg);      color: var(--red);    border: 1px solid var(--red-border); }
.badge-yellow  { background: var(--yellow-bg);   color: var(--yellow); border: 1px solid var(--yellow-border); }
.badge-accent  { background: var(--accent-light); color: var(--accent); border: 1px solid var(--accent-border); }
/* --text3 auf --bg3 ergibt im Light nur 4.39; --text-muted bringt 4.99. */
.badge-neutral { background: var(--bg3);         color: var(--text-muted); border: 1px solid var(--border2); }
/* Kleinere Variante fuer Zeilen und Statuszeilen (ersetzt .antrag-status-pill). */
.badge.badge-sm { font-size: 10px; padding: 2px 8px; }

/* Shop-Identitaet auf Buttons: PF blau, KA gruen (wie im Schichtplaner). */
.btn.shop-pf { color: var(--accent); border-color: var(--accent-border); }
.btn.shop-ka { color: var(--green);  border-color: var(--green-border); }

/* ── Kennzahl-Karte ──────────────────────────────────────────────────────
   Lag doppelt lokal (dashboard: padding 22px + cursor:pointer, mitarbeiter:
   20px 22px ohne) und wurde von styles.css referenziert, ohne je global
   definiert zu sein. Klickbar nur per Modifier.                            */
.stat-card-new {
  background: var(--bg2);
  border: 1px solid var(--border);
  border-radius: 16px;
  padding: 20px 22px;
  box-shadow: var(--shadow-sm);
  transition: border-color .2s, transform .2s;
}
.stat-card-new.clickable { cursor: pointer; }
.stat-card-new:hover { border-color: var(--border2); transform: translateY(-1px); }
.stat-card-top { display: flex; align-items: flex-start; justify-content: space-between; margin-bottom: 12px; }
.stat-card-label { font-size: 11px; font-weight: 700; color: var(--text3); text-transform: uppercase; letter-spacing: .06em; }
.stat-card-value-big { font-size: 32px; font-weight: 800; color: var(--text); letter-spacing: -.05em; line-height: 1; margin-bottom: 6px; }
.stat-card-value-big .unit { font-size: 16px; font-weight: 600; color: var(--text3); letter-spacing: 0; margin-right: 3px; }
.stat-card-sub-text { font-size: 12px; color: var(--text3); }

/* ── Chip / Filter-Pill ──────────────────────────────────────────────────
   Ersetzt 7 konkurrierende Systeme (allein 5 in provision.html).
   Aktiv-Farbe per Modifier, nicht per eigener Klasse je Seite.            */
.chip {
  display: inline-flex; align-items: center; justify-content: center; gap: 5px;
  padding: 9px 12px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  background: var(--bg2);
  color: var(--text2);
  font-family: var(--font); font-size: 12.5px; font-weight: 600;
  white-space: nowrap; cursor: pointer;
  transition: background .15s, border-color .15s, color .15s;
  -webkit-tap-highlight-color: transparent;
}
.chip:active { opacity: .8; }
.chip-count { font-size: 12px; font-weight: 700; color: var(--text3); transition: color .15s; }
.chip.active { color: var(--accent); background: var(--accent-bg); border-color: var(--accent-border); }
.chip.active .chip-count { color: inherit; opacity: .75; }
.chip.active.green  { color: var(--green);  background: var(--green-bg);  border-color: var(--green-border); }
.chip.active.red    { color: var(--red);    background: var(--red-bg);    border-color: var(--red-border); }
.chip.active.yellow { color: var(--yellow); background: var(--yellow-bg); border-color: var(--yellow-border); }
.chip.active.purple { color: var(--purple); background: var(--purple-bg); border-color: var(--purple-border); }

/* ── Icon-Button ─────────────────────────────────────────────────────────
   Ersetzt 8 Prev/Next-Nachbauten (waren 28–34px). 44px = Mindest-Touchziel;
   das Icon bleibt klein, die Trefferflaeche nicht.                        */
.icon-btn {
  width: 44px; height: 44px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  background: var(--bg2);
  color: var(--text2);
  cursor: pointer;
  flex-shrink: 0;
  transition: border-color .15s, color .15s, background .15s;
  -webkit-tap-highlight-color: transparent;
}
.icon-btn:hover  { border-color: var(--accent-border); color: var(--accent); }
.icon-btn:active { opacity: .7; }
.icon-btn.ghost  { border-color: transparent; background: none; }
.icon-btn.danger:hover { border-color: var(--red-border); color: var(--red); }

/* ── Toolbar ── (Seitenkopf-Leiste: Info links, Navigation rechts) */
.toolbar {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; margin-bottom: 16px;
}
.toolbar-info { font-size: 12px; color: var(--text3); min-width: 0; }
.toolbar-nav  { display: flex; align-items: center; gap: 6px; flex-shrink: 0; }
.toolbar-label { font-size: 14px; font-weight: 700; color: var(--text); min-width: 52px; text-align: center; }

/* ── Segmented Control ── (Ansichts-Umschalter; ersetzt 3 Nachbauten) */
.segmented {
  display: inline-flex; gap: 4px; padding: 3px;
  background: var(--bg3); border: 1px solid var(--border);
  border-radius: var(--radius-sm);
}
.segmented button {
  border: none; background: none; cursor: pointer;
  font-family: var(--font); font-size: 12.5px; font-weight: 600;
  color: var(--text3); padding: 7px 14px; border-radius: var(--radius-xs);
  min-height: 34px;
  transition: background .15s, color .15s;
}
.segmented button.active { background: var(--accent); color: var(--on-accent); }
.segmented button:not(.active):hover { color: var(--text2); }

/* ── FAB ── (.kal-fab und .pv-fab waren byte-identisch) */
.fab {
  position: fixed;
  right: 16px; bottom: calc(96px + env(safe-area-inset-bottom));
  width: 52px; height: 52px;
  border-radius: var(--radius-lg);
  border: none; cursor: pointer;
  background: var(--accent); color: var(--bg);
  display: flex; align-items: center; justify-content: center;
  box-shadow: 0 6px 20px color-mix(in srgb, var(--accent) 35%, transparent);
  z-index: var(--z-nav);
}
.fab:active { opacity: .85; }
@media (min-width: 769px) { .fab { display: none; } }

/* ── Empty-State ─────────────────────────────────────────────────────────
   Ersetzt 13 Nachbauten (Paddings von 8 bis 64px). Vorbild war
   zeiterfassung.html: Icon + Titel + erklaerender Satz.
   Der CTA ist Pflicht, wo es eine sinnvolle naechste Aktion gibt – 14 der 15
   alten Leerzustaende waren Sackgassen ("Keine Daten" und sonst nichts).     */
.empty-state {
  text-align: center;
  padding: 48px 16px;
  color: var(--text3);
}
.empty-state-icon { font-size: 34px; margin-bottom: 12px; opacity: .5; line-height: 1; }
.empty-state-title { font-size: 14px; font-weight: 600; color: var(--text2); margin-bottom: 4px; }
.empty-state-text  { font-size: 12.5px; color: var(--text3); line-height: 1.5; max-width: 320px; margin: 0 auto; }
.empty-state-cta   { margin-top: 16px; }
.empty-state.compact { padding: 28px 16px; }

/* ── Listenzeile ── (ersetzt ~18 lokale Karten-Nachbauten) */
.list-card {
  background: var(--bg2);
  border: 1px solid var(--border);
  border-radius: 16px;
  overflow: hidden;
  margin-bottom: 10px;
}
.list-row {
  display: flex; align-items: center; gap: 12px;
  padding: 12px 14px;
  border-bottom: 1px solid var(--border);
  transition: background .15s;
  -webkit-tap-highlight-color: transparent;
}
.list-row:last-child { border-bottom: none; }
.list-row.clickable { cursor: pointer; }
.list-row.clickable:active { background: var(--bg3); }
.list-row-info { flex: 1; min-width: 0; }
.list-row-title { font-size: 13px; font-weight: 600; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.list-row-sub { font-size: 11px; color: var(--text3); margin-top: 2px; display: flex; gap: 6px; align-items: center; flex-wrap: wrap; }

/* ── Tables ── */
.table-wrap {
  background: var(--bg2);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
  box-shadow: var(--shadow-sm);
}

.table-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 20px;
  border-bottom: 1px solid var(--border);
  gap: 12px;
  flex-wrap: wrap;
}

.table-header h3 { font-size: 14px; font-weight: 600; color: var(--text); }

table { width: 100%; border-collapse: collapse; }

thead th {
  padding: 10px 20px;
  text-align: left;
  font-size: 11px;
  color: var(--text3);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  background: var(--bg3);
  border-bottom: 1px solid var(--border);
}

tbody td {
  padding: 14px 20px;
  font-size: 13px;
  border-bottom: 1px solid var(--border);
  color: var(--text2);
  transition: background 0.1s;
}

tbody td:first-child { color: var(--text); }
tbody tr:last-child td { border-bottom: none; }
tbody tr { border-left: 2px solid transparent; transition: all 0.12s; }
tbody tr:hover td { background: var(--bg3); }
tbody tr:hover { border-left-color: var(--accent); }

/* ── Search Input ── */
.search-input {
  background: var(--bg3);
  border: 1px solid var(--border2);
  border-radius: var(--radius-sm);
  padding: 8px 14px;
  font-size: 13px;
  font-family: var(--font);
  color: var(--text);
  outline: none;
  width: 220px;
  transition: border-color 0.15s, box-shadow 0.15s;
}
.search-input:focus { border-color: var(--accent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 30%, transparent); }
.search-input::placeholder { color: var(--text3); }

/* ── Stat Cards ── */


.stat-card::before {
  content: '';
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 2px;
}

.stat-card.blue::before   { background: linear-gradient(90deg, var(--accent), #818cf8); }
.stat-card.green::before  { background: linear-gradient(90deg, var(--green), #34d399); }
.stat-card.yellow::before { background: linear-gradient(90deg, var(--yellow), #fbbf24); }
.stat-card.red::before    { background: linear-gradient(90deg, var(--red), #fb7185); }
.stat-card.purple::before { background: linear-gradient(90deg, var(--purple), #c084fc); }





/* ── Form Layout ── */
/* Zwei Felder nebeneinander (von/bis, Datum/Uhrzeit). Stapelt unter 769px auf
   eine Spalte (Regel weiter unten im Mobil-Block) – deshalb Grid, nicht Flex.
   Ersetzt auch .kal-field-row. */
.form-row { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; margin-bottom: 16px; }
.form-row:last-child { margin-bottom: 0; }
/* Den Abstand nach unten traegt die Zeile, nicht die Felder darin – sonst
   haette ihn nur das erste (das letzte hat margin-bottom:0). */
.form-row .form-group { margin-bottom: 0; min-width: 0; }
.form-group { margin-bottom: 16px; }
.form-group:last-child { margin-bottom: 0; }
.form-label { font-size: 12px; color: var(--text2); font-weight: 500; display: block; margin-bottom: 6px; }

/* ── Bottom-Sheet ─────────────────────────────────────────────────────────
   EINE Komponente für alle Sheets. Vorher lagen 9 Kopien in den Seiten:
   3 Easings, 3 Radien, 5 max-height-Werte, 6 z-index-Ebenen (201–1301) und
   3 verschiedene Hintergründe – für dasselbe Element.

   Verhält sich auf JEDER Breite gleich (bleibt unten angedockt). Der "Desktop"
   ist hier ein geteilter Shop-PC mit Touch – isSharedPC() in utils.js existiert
   genau deswegen. Ein Muster, das überall gleich ist, schlägt fünf clevere.
   Einzige Ausnahme: .sheet--centered für Inhalte, die ein echter Dialog sind.

   Öffnen/Schließen NICHT selbst bauen → openSheet(id)/closeSheet(id) in utils.js
   (kümmert sich um Overlay, Scroll-Lock, ESC und Swipe-down).                */
.sheet-overlay {
  position: fixed; inset: 0;
  z-index: var(--z-overlay);
  background: rgba(8, 13, 24, .70);
  display: none;
}
.sheet-overlay.show { display: block; }

.sheet {
  position: fixed; left: 0; right: 0; bottom: 0;
  z-index: var(--z-sheet);
  background: var(--surface-sheet);
  /* Keine Kante: Scrim + oberer Schatten setzen das dunkle Sheet von der Seite ab
     (Design v2 Sheet-Vorlage). */
  border: none;
  border-radius: 24px 24px 0 0;
  box-shadow: 0 -20px 50px -12px rgba(0,0,0,.7);
  padding: 0 22px calc(24px + env(safe-area-inset-bottom));
  max-height: 88vh;
  overflow-y: auto;
  transform: translateY(110%);
  transition: transform .32s cubic-bezier(.32, .72, 0, 1);
  visibility: hidden; pointer-events: none;
}
.sheet.show { transform: translateY(0); visibility: visible; pointer-events: auto; }

/* Zieh-Griff: signalisiert "nach unten wischen schließt" */
.sheet-handle {
  width: 44px; height: 5px; border-radius: 3px;
  background: var(--handle);
  margin: 10px auto 18px;
  flex-shrink: 0;
}
/* ── Sheet-Kopf (VERTRAG: jedes Sheet hat ihn – Titel links, Schliessen rechts) ──
   Vorher hatte jede Seite ihren eigenen Kopf: profils .sheet-head, dashboards
   .ziel-sheet-header, anfragens Badge-Zeile, und 9 Sheets gar keinen Titel. */
.sheet-head {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 12px; margin-bottom: 16px;
}
.sheet-head-text { flex: 1; min-width: 0; }
/* Optionaler Icon-Platz links im Kopf – z.B. die Terminfarbe im Kalender oder
   der Typ eines Antrags. Traegt Bedeutung, deshalb Teil des Kopfes statt Beiwerk. */
.sheet-head-icon {
  width: 40px; height: 40px; flex-shrink: 0;
  border-radius: var(--radius-sm);
  display: flex; align-items: center; justify-content: center;
}
/* Steht dort ein Mensch (Antrag, Mitarbeiter), ist es ein Avatar – rund. */
.sheet-head-icon.avatar { border-radius: 50%; font-size: 14px; font-weight: 700; }
.sheet-title { font-size: 22px; font-weight: 800; color: var(--text); margin: 0 2px 14px; letter-spacing: -0.01em; }
.sheet-sub   { font-size: 12.5px; color: var(--text3); line-height: 1.5; margin: -10px 2px 14px; }
/* Im Kopf tragen die Abstaende der Kopf selbst – nicht Titel/Untertitel. */
.sheet-head .sheet-title { margin: 0; }
.sheet-head .sheet-sub   { margin: 4px 0 0; }

/* Schliessen: das einzige sichtbare "hier kommst du wieder raus". Am Handy
   zusaetzlich zum Zieh-Griff, am PC das einzige – dort gibt es keinen Griff. */
.sheet-close {
  flex-shrink: 0;
  width: 36px; height: 36px;
  display: flex; align-items: center; justify-content: center;
  /* Sieht aus wie .icon-btn – dieselbe Rolle (Icon-Bedienelement), also dieselbe
     Optik: abgerundetes Quadrat, sichtbare Kante, Akzent beim Hover.
     Zwei Korrekturen vom 19.07.:
     1. War border-radius:50% – der einzige runde Button der App. Rund bleibt
        Menschen (Avataren) vorbehalten.
     2. War randlos auf --surface-sunken. Nachdem die Sheet-Flaeche auf --bg2
        gezogen wurde, ergab das Kontrast 1.01 zum Untergrund – der Button war
        praktisch unsichtbar, nur das Icon trug ihn noch. Die Kante macht ihn
        wieder als Bedienelement lesbar. */
  border: none;
  border-radius: 12px;
  background: var(--surface-input);
  color: var(--text-muted);
  cursor: pointer;
  transition: background .15s, color .15s;
  -webkit-tap-highlight-color: transparent;
}
/* Rahmenlos wie die Felder – die Flaeche traegt ihn. Beim Hover uebernimmt der Akzent. */
.sheet-close:hover  { background: var(--accent-light); color: var(--accent); }
.sheet-close:active { opacity: .7; }

/* ── Inhalts-Bausteine: Kennzahl oben, Herleitung darunter ──
   Ersetzt die Eigenbauten sp-stat-*, pv-item-*, ze-sum-*, url-stat-*,
   kal-detail-row, antrag-sheet-label/-value, ziel-sheet-sub. */
.sheet-metric { margin-bottom: 18px; }
.sheet-metric-val {
  font-size: 30px; font-weight: 800; color: var(--text);
  line-height: 1.1; letter-spacing: -0.02em; font-variant-numeric: tabular-nums;
}
.sheet-metric-label { font-size: 12px; color: var(--text3); margin-top: 4px; }
/* Kennzahl im Alarmzustand (z.B. Resturlaub im Minus). */
.sheet-metric-val.warn { color: var(--red); }

/* Abschnitts-Titel in Sheets und Dialogen (trennt Herleitung von Liste).
   Ersetzt url-sec-lbl, pv-field-label und die inline gestylten Varianten
   im Dashboard. */
.sheet-sec-label {
  font-size: 11px; font-weight: 700; color: var(--text3);
  text-transform: uppercase; letter-spacing: .06em;
  margin: 20px 2px 10px;
}

/* Trennlinie relativ zur FLAECHE, nicht als fester Rand-Token. Feste Werte sind
   hier zweimal schiefgegangen: --border2 ist im Dark exakt --bg2 (unsichtbar),
   --border liegt zu nah an der Schiefer-Sheetflaeche #1b2233 (Kontrast 1.1).
   Aus --text3 gemischt passt sie sich jeder Flaeche und beiden Modi an und
   bleibt trotzdem leise. Mehr Zeilenhoehe traegt die Trennung mit. */
.sheet-kv {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 14px; padding: 13px 0;
  border-bottom: 1px solid color-mix(in srgb, var(--text3) 18%, transparent);
}
.sheet-kv:last-child { border-bottom: none; }
.sheet-kv-label { font-size: 15px; color: var(--text-muted); min-width: 0; }
.sheet-kv-val {
  font-size: 16px; font-weight: 700; color: var(--text);
  font-variant-numeric: tabular-nums; text-align: right; flex-shrink: 0;
}
.sheet-kv-val.muted { font-weight: 600; color: var(--text3); }
/* Gedaempfter Zusatz im Wert, z.B. "· Ziel ≥ 5 %". */
.sheet-kv-sub { color: var(--text3); font-weight: 400; }

/* Erklaerender Hinweis im Sheet. Ersetzt ze-sheet-hint und profils lokales
   .sheet .sheet-hint – beide meinten dasselbe. */
.sheet-hint { font-size: 11.5px; color: var(--text3); line-height: 1.45; margin: 6px 2px 0; }

/* Abgesetzte Zeile im Sheet (Stempelzeit, Schicht, Mitarbeiter, Urlaub).
   Vier Seiten hatten dafuer je eine eigene Klasse mit demselben Aussehen:
   ze-seg, sp-shift-row, sp-picker-item, url-vac-row. */
.sheet-row {
  display: flex; align-items: center; gap: 11px;
  width: 100%; text-align: left;
  /* Rahmenlos: Flaeche statt Kante trennt die Zeile ab – wie die Listenzeilen
     auf den Seiten (DESIGN.md, Tabelle "Listenzeile"). */
  background: var(--surface-sunken); border: none;
  border-radius: var(--radius-sm); padding: 13px 14px; margin-bottom: 8px;
  font-family: var(--font); font-size: 13px;
  transition: background .15s;
}
.sheet-row:last-child { margin-bottom: 0; }
.sheet-row.tap { cursor: pointer; -webkit-tap-highlight-color: transparent; }
/* Ohne Rahmen traegt die Flaeche das Feedback – vorher faerbte sich der Rand. */
.sheet-row.tap:hover  { background: var(--bg4); }
.sheet-row.tap:active { opacity: .8; }
.sheet-row-icon { width: 34px; height: 34px; border-radius: 9px; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center; }
.sheet-row-main  { flex: 1; min-width: 0; }
.sheet-row-title { font-size: 13px; font-weight: 600; color: var(--text); }
.sheet-row-sub   { font-size: 11px; color: var(--text3); margin-top: 2px; }
.sheet-row-val   { font-size: 13px; font-weight: 700; color: var(--text);
  font-variant-numeric: tabular-nums; flex-shrink: 0; }
.sheet-row-chev  { color: var(--text3); flex-shrink: 0; display: flex; }

/* Feldgruppe im Sheet – KEIN Kasten mehr, nur noch ein Abstandhalter.
   Vorher war das eine gerahmte Box mit eigener Flaeche; zusammen mit den
   seitenlokalen Klonen (.kal-form, .sp-form) ergab das Kasten-im-Kasten und war
   der Hauptgrund fuer "ueberfuellt". Getrennt wird jetzt ueber Weissraum, wie
   auf den Seiten auch (DESIGN.md Prinzip 2: Weissraum statt Linien).
   Die Klasse bleibt bestehen, damit vorhandenes Markup weiterlaeuft. */
.sheet-form { margin-bottom: 22px; }
.sheet-form:last-child { margin-bottom: 0; }
.sheet .form-label { font-size: 11px; font-weight: 600; color: var(--text-label); margin-bottom: 6px; }
/* Kein .sheet .form-input-Override mehr: die Basisregel (--bg3 / --border2) ist
   nach dem Zusammenlegen der Flaechen exakt das Richtige. Ein Eingabefeld sieht
   im Sheet jetzt aus wie ueberall sonst – per Konstruktion, nicht per Pflege. */

/* Aktionen am Fuß: gestapelt, volle Breite – Daumen-freundlich.
   Gilt auch am PC: eine Anordnung, damit "Destruktives sitzt unten" ueberall
   woertlich sichtbar bleibt. */
.sheet-actions { display: flex; flex-direction: column; gap: 10px; }

/* Fester Fuss in Scroll-Sheets: bleibt stehen, waehrend der Koerper scrollt.
   Ersetzt provisions lokales .pv-sheet-footer. */
.sheet-foot {
  flex-shrink: 0; padding-top: 12px; margin-top: 8px;
  /* Flaechenrelativ wie .sheet-kv – s. dort. */
  border-top: 1px solid color-mix(in srgb, var(--text3) 20%, transparent);
}

/* Sheet mit eigenem Scroll-Bereich (langer Inhalt, fixer Kopf/Fuß) */
.sheet--scroll { display: flex; flex-direction: column; }
.sheet--scroll .sheet-scroll { overflow-y: auto; flex: 1; margin: 0 -18px; padding: 0 18px; }

/* Am PC ist JEDES Sheet ein zentrierter Dialog – eine Position, keine Ausnahmen.
   Vorher lagen 17 Sheets als 400px-Panel unten links und 5 zentriert; welches man
   bekam, war von aussen nicht absehbar. Das Overlay verdunkelt ohnehin den ganzen
   Bildschirm ("jetzt hier hin schauen") – ein Panel in der Ecke widersprach dem.
   Am Handy bleibt alles wie es war: Bottom-Sheet, das hochfaehrt.
   Der frueher noetige Modifier .sheet--centered ist damit entfallen. */
@media (min-width: 769px) {
  .sheet {
    left: 50%; right: auto; bottom: auto; top: 50%;
    width: 560px; max-width: calc(100vw - 40px); max-height: 86vh;
    border-radius: 24px;
    /* Am PC ist der Zieh-Griff aus (kein oberer Abstand mehr) → Padding oben wie an den
       anderen Seiten, sonst klebt der Sheet-Kopf an der Oberkante. */
    padding-top: 24px;
    transform: translate(-50%, -50%) scale(.96);
    opacity: 0;
    transition: opacity .18s, transform .18s;
  }
  .sheet.show { transform: translate(-50%, -50%) scale(1); opacity: 1; }
  /* Kein Zieh-Griff am PC – dort wird nicht gewischt, der X-Button traegt das Schliessen. */
  .sheet .sheet-handle { display: none; }
}

/* ── Modal ── */
.modal-overlay {
  position: fixed; inset: 0;
  background: #00000090;
  backdrop-filter: blur(4px);
  display: flex; align-items: center; justify-content: center;
  z-index: var(--z-modal);
  opacity: 0; pointer-events: none;
  transition: opacity 0.2s;
  padding: 16px;
}
.modal-overlay.show { opacity: 1; pointer-events: all; }
/* Modal, das aus einem offenen Sheet heraus geoeffnet wird – siehe --z-modal-sheet. */
.modal-overlay.over-sheet { z-index: var(--z-modal-sheet); }

.modal {
  background: var(--bg2);
  border: 1px solid var(--border2);
  border-radius: var(--radius-lg);
  padding: 32px;
  width: 100%;
  max-width: 500px;
  max-height: 90vh;
  overflow-y: auto;
  box-shadow: var(--shadow-lg);
}

.modal h3 { font-size: 18px; font-weight: 700; margin-bottom: 24px; color: var(--text); }

.modal-footer {
  display: flex; gap: 10px; justify-content: flex-end;
  margin-top: 24px; padding-top: 20px;
  border-top: 1px solid var(--border);
}

/* ── Toasts ── */
.toast-container {
  position: fixed;
  bottom: 24px; right: 24px;
  display: flex; flex-direction: column; gap: 8px;
  z-index: var(--z-toast);
  pointer-events: none;   /* Toasts sollen nie Klicks abfangen */
}

/* Mobil über die Bottom-Nav (~96px inkl. Safe-Area) heben und über die volle
   Breite. Vorher sass der Toast auf bottom:24px – also GENAU unter der Nav.
   Seit 17.07. greift das mobil nicht mehr: showToast() ist unter 768px bewusst
   abgeschaltet (utils.js – dort steht das Warum). Die Regel bleibt trotzdem
   stehen, damit die Toasts korrekt sitzen, falls sie je zurueckkommen. */
@media (max-width: 768px) {
  .toast-container {
    bottom: calc(96px + env(safe-area-inset-bottom));
    left: 12px; right: 12px;
    align-items: stretch;
  }
}

.toast {
  display: flex; align-items: center; gap: 10px;
  padding: 12px 16px;
  border-radius: var(--radius-sm);
  font-size: 13px;
  font-weight: 500;
  min-width: 260px;
  max-width: 360px;
  box-shadow: var(--shadow-lg);
  animation: toastIn 0.25s ease;
  border: 1px solid;
  pointer-events: auto;
}

@media (max-width: 768px) {
  .toast { min-width: 0; max-width: none; }
}

@keyframes toastIn {
  from { opacity: 0; transform: translateY(12px); }
  to   { opacity: 1; transform: translateY(0); }
}

.toast.success { background: var(--green-bg); color: var(--green); border-color: var(--green-border); }
.toast.error   { background: var(--red-bg);   color: var(--red);   border-color: var(--red-border); }
.toast.info    { background: var(--accent-light); color: var(--accent); border-color: var(--accent-border); }

/* ── Page Layout ── */
.page-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  margin-bottom: 24px;
  gap: 16px;
}

.page-title { font-size: 22px; font-weight: 700; letter-spacing: -0.04em; color: var(--text); }
.page-sub   { font-size: 13px; color: var(--text3); margin-top: 3px; }

/* ── Divider ── */

/* ── Scrollbar ── */
* { scrollbar-width: none; -ms-overflow-style: none; }
*::-webkit-scrollbar { display: none; }

/* ── PWA Native Feel ── */
/* Focus-Ring entfernen */
*:focus, *:focus-visible { outline: none; }
/* Tap-Highlight (grauer Blitz auf Mobile) */
* { -webkit-tap-highlight-color: transparent; }
/* Overscroll / Rubber-Band global */
body { overscroll-behavior: none; }
/* Smooth Scrolling */
html { scroll-behavior: smooth; }
/* Double-Tap Zoom verhindern */
body, a, button, [role="button"] { touch-action: manipulation; }
/* Kein Text-Cursor auf UI-Elementen */
body { cursor: default; }
/* Kein Text-Select / iOS Look-Up / Google-Suche auf Tap */
body { -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; }
input, textarea, select, [contenteditable] { -webkit-user-select: text; user-select: text; }
/* Active-State auf Touch (hover wirkt auf Mobile nicht) */
.btn:active, button:active, .bottom-nav-center-btn:active,
.top-bubble:active, .icon-nav-link:active { opacity: 0.8; }

/* ── Boot Screen ── */
#boot { background: #0c0e13 !important; }
.boot-logo {
  animation: bootLogoIn .7s cubic-bezier(.16,1,.3,1) both,
             bootGlowSettle 1.2s ease .3s both;
}
@keyframes bootLogoIn {
  from { opacity:0; transform:scale(.78) translateY(22px); }
  to   { opacity:1; transform:scale(1) translateY(0); }
}
@keyframes bootGlowSettle {
  0%   { filter:drop-shadow(0 0 0px color-mix(in srgb, var(--accent) 0%, transparent)); }
  35%  { filter:drop-shadow(0 0 30px color-mix(in srgb, var(--accent) 52%, transparent)); }
  100% { filter:drop-shadow(0 0 14px color-mix(in srgb, var(--accent) 20%, transparent)); }
}
.boot-title {
  font-size: 15px; font-weight: 600; color: #5b7ea8;
  letter-spacing: .32em; font-family: var(--font);
  opacity: 0;
  animation: bootTitleIn .65s cubic-bezier(.16,1,.3,1) .65s both;
}
@keyframes bootTitleIn {
  from { opacity:0; letter-spacing:.6em; }
  to   { opacity:1; letter-spacing:.32em; }
}

/* ── Mobile ── */
@media (max-width: 768px) {
  body { overflow-x: hidden; }
  .form-row { grid-template-columns: 1fr; }
  .page-header { flex-direction: column; }
  .btn-primary { width: 100%; justify-content: center; }
  .search-input { width: 100%; }
  /* Alle Karten nie breiter als ihr Container */
  .card, .stat-card-new, .table-wrap, .modal, .sheet {
    max-width: 100%;
    box-sizing: border-box;
    min-width: 0;
  }
}
/* ── App Footer (geladen via footer.html) ── */
.app-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 28px;
  margin-top: 40px;
  border-top: 1px solid var(--border);
  font-size: 11px;
  color: var(--text3);
  flex-wrap: wrap;
  gap: 8px;
}
.footer-logo strong { color: var(--accent); }
@media (max-width: 768px) {
  .app-footer { flex-direction: column; align-items: center; text-align: center; padding: 16px; }
  .footer-left, .footer-right { justify-content: center; width: 100%; }
}

/* ══════════════════════════════════════════
   ShopOS · Skeleton Loading States
   ══════════════════════════════════════════ */

/* ── Shimmer Animation ── */
@keyframes shimmer {
  0%   { background-position: -600px 0; }
  100% { background-position:  600px 0; }
}

.skeleton {
  background: linear-gradient(
    90deg,
    var(--bg3) 25%,
    var(--bg4) 50%,
    var(--bg3) 75%
  );
  background-size: 600px 100%;
  animation: shimmer 1.4s ease-in-out infinite;
  border-radius: var(--radius-xs);
  display: block;
}

/* ── Basis-Blöcke ── */
.sk-line        { height: 12px; margin-bottom: 8px; }
.sk-line-sm     { height: 10px; margin-bottom: 6px; }
.sk-line-lg     { height: 18px; margin-bottom: 10px; }
.sk-line-xl     { height: 32px; margin-bottom: 12px; }
.sk-w-80  { width: 80%; }
.sk-w-60  { width: 60%; }
.sk-w-40  { width: 40%; }
.sk-w-25  { width: 25%; }

/* ── Avatar / Kreis ── */
.sk-avatar {
  border-radius: 50%;
  flex-shrink: 0;
}
.sk-avatar-lg  { width: 40px; height: 40px; }
.sk-avatar-xl  { width: 72px; height: 72px; }

/* ── Badge ── */
.sk-badge { height: 22px; width: 80px; border-radius: 20px; }

/* ── Stat-Card Skeleton ── */

/* ── Tabellen-Zeile Skeleton ── */

/* ── Chart Skeleton ── */


/* ══════════════════════════════════════════════════════════════════════════
   DESIGN-SPRACHE v2 · „luftig"  (ab 18.07. – siehe DESIGN.md)
   Zwei Teile, beide ADDITIV (brechen keine bestehende Seite):
   (1) Global: Modul-Kopf-Helfer + gemeinsamer Zeitraum-Picker
       (Logik in utils.js: openPeriodPicker/_pp*).
   (2) .ui-airy: der luftige Look als SEITEN-SCOPE. Die Basis-Komponenten
       bleiben unverändert; eine Seite bekommt den neuen Look erst, wenn sie
       beim Umbau  <main class="main ui-airy">  trägt. So bleibt der Roll-out
       seitenweise statt Big-Bang. Sind ALLE Seiten migriert, wandert das hier
       in die Basis und der Scope entfällt.
   ══════════════════════════════════════════════════════════════════════════ */

/* ── (1a) Modul-Kopf-Vertrag: Titel → Zeitraum-Navi → Segmented → Inhalt ── */
.module-head { display: flex; flex-direction: column; gap: 14px; margin-bottom: 22px; }
.module-head .toolbar { margin: 0; }
.module-head .mh-actions { display: flex; align-items: center; gap: 10px; flex-shrink: 0; }
.module-head .segmented { width: 100%; }
.module-head .segmented button { flex: 1; }

/* ── (1b) Gemeinsamer Zeitraum-Picker (Monat/Jahr) ──
   Öffnen/Schließen + DOM aus utils.js. Lebt in einer .sheet → Sheet-Tokens. */
.pp-yearnav { display: flex; align-items: center; justify-content: center; gap: 14px; margin-bottom: 14px; }
.pp-year { font-size: 16px; font-weight: 800; color: var(--text); min-width: 68px; text-align: center; font-variant-numeric: tabular-nums; }
.pp-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
.pp-cell {
  padding: 12px 4px; border-radius: var(--radius-sm);
  /* Rahmenlos wie alles im Sheet – der Picker lebt in einem Sheet. */
  border: none; background: var(--surface-sunken);
  color: var(--text); font: 600 13px var(--font); cursor: pointer;
  font-variant-numeric: tabular-nums;
  transition: background .15s, color .15s;
}
.pp-cell:hover { background: var(--accent-light); color: var(--accent); }
.pp-cell.active { background: var(--accent); color: var(--on-accent); }

/* ── (2) .ui-airy — luftiger Look, seitenweise opt-in ──
   Flächen statt Kanten: Karten rahmenlos + weicher Schatten + größerer Radius. */
.ui-airy .card,
.ui-airy .stat-card-new,
.ui-airy .list-card,
.ui-airy .table-wrap {
  border-color: transparent;
  box-shadow: var(--shadow-sm);
  border-radius: var(--radius-lg);
}
/* Segmented luftiger: getönter Track + größere Tap-Fläche. */
.ui-airy .segmented { background: var(--bg3); padding: 4px; border-radius: var(--radius); }
.ui-airy .segmented button { min-height: 40px; border-radius: var(--radius-sm); font-size: 13px; }
/* Leerzustand großzügiger. */
.ui-airy .empty-state { padding: 56px 20px; }

/* Signatur-Baustein des luftigen Looks: die freistehende Tages-/Eintrags-Karte.
   Jede Zeile ist ihre eigene rahmenlose Karte (Fläche + Schatten), Reihen per
   Gap getrennt; Status als farbiger Punkt links statt farbiger Kante; die Zeile
   selbst ist das Tap-Target (kein Button darin). Zuerst von der Zeiterfassung
   genutzt, danach überall (Anträge, Provision, …). */
.ui-airy .row-stack { display: flex; flex-direction: column; gap: 12px; }
.ui-airy .row-card {
  display: flex; align-items: center; gap: 12px; width: 100%; text-align: left;
  background: var(--bg2); border: none; border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm); padding: 16px 18px;
  font-family: var(--font); cursor: pointer;
  transition: box-shadow .15s, transform .12s;
}
.ui-airy .row-card:hover { box-shadow: var(--shadow-md); }
.ui-airy .row-card:active { transform: scale(.995); }
.ui-airy .row-card > .row-main { flex: 1; min-width: 0; }
.ui-airy .row-card .row-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--border-strong); flex-shrink: 0; }
.ui-airy .row-card.aktiv .row-dot { background: var(--green); box-shadow: 0 0 0 3px color-mix(in srgb, var(--green) 18%, transparent); }
.ui-airy .row-card.warn  .row-dot { background: var(--red); }
.ui-airy .row-card .row-chev { color: var(--text3); opacity: .55; flex-shrink: 0; display: flex; }
/* Text-Teile der row-card (geteilt: Datum/Titel · Untertitel · rechte Zahl) */
.ui-airy .row-card .row-main .row-head { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.ui-airy .row-card .row-title { font-size: 14px; font-weight: 700; color: var(--text); }
.ui-airy .row-card .row-sub { font-size: 12px; color: var(--text3); margin-top: 4px; font-variant-numeric: tabular-nums; }
.ui-airy .row-card .row-sub.live { color: var(--green); font-weight: 600; }
.ui-airy .row-card .row-val { font-size: 20px; font-weight: 800; color: var(--text); font-variant-numeric: tabular-nums; line-height: 1.1; flex-shrink: 0; }

/* Antippbares Zeitraum-Label in der Toolbar (öffnet openPeriodPicker).
   Button-Reset, KEIN Caret (Justin, 18.07.) – die ‹ ›-Pfeile tragen die Navigation,
   das Label ist ein zusätzlicher Schnellzugriff (wie in Provision). */
.toolbar-label.pick { background: none; border: none; font-family: var(--font); cursor: pointer; padding: 6px 4px; }
.toolbar-label.pick:hover { color: var(--accent); }

/* ══════════════════════════════════════════════════════════════════════════
   DESIGN v2 · „Band & Graphit"  (ab 22.07. – Mocks: .claude/design-v2/screens.html)
   Zwei Teile, beide ADDITIV:
   (1) Global: Band-Komponente + v2-Bausteine (Eyebrow, Progress, Pill, …) –
       nutzbar, sobald eine Seite das Markup trägt.
   (2) body.ui-v2: SEITEN-SCOPE für den Strukturwechsel. Eine Seite bekommt den
       v2-Aufbau erst, wenn ihr <body> die Klasse trägt: mobile Topbar weg
       (das Band übernimmt Logo/Glocke/Logout), Inhalt randlos bis zum Band.
       Rollout bleibt seitenweise; .ui-airy-Seiten laufen unverändert weiter.
   ══════════════════════════════════════════════════════════════════════════ */

/* ── (1a) Band – der farbige Modul-Kopf ──
   Markup-Vertrag (DESIGN.md): .band > .band-inner > [.band-top] + Inhalt.
   .band-top (Logo · ShopOS · Glocke · Logout) gibt es nur mobil – am Desktop
   liefert die Bubble-Topbar dieselben Funktionen. */
.band {
  background: var(--band-grad);
  border-radius: 0 0 var(--radius-xl) var(--radius-xl);
  color: var(--on-band);
}
.band-inner { padding: 10px 22px 20px; }
.band-top { display: flex; align-items: center; justify-content: space-between; padding: 6px 0 12px; }
.band-logo { display: flex; align-items: center; gap: 11px; font-size: 20px; font-weight: 800; color: var(--on-band); }
.band-logo-mark {
  width: 34px; height: 34px; border-radius: 11px;
  background: rgba(255,255,255,.18);
  display: flex; align-items: center; justify-content: center;
}
.band-actions { display: flex; gap: 8px; }
/* Icon-Kachel auf dem Band (Glocke, Logout, ‹ ›) */
.band-ico {
  width: 36px; height: 36px; border-radius: 11px;
  background: var(--band-tint); border: none;
  color: var(--on-band); cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  position: relative;
  transition: background .15s;
  -webkit-tap-highlight-color: transparent;
}
.band-ico:hover { background: var(--band-tint-strong); }
.band-ico:active { opacity: .8; }
.band-ico .notif-dot { border-color: transparent; }
/* Titelzeile: Seitentitel links, Zeitraum-Pill/Aktionen rechts */
.band-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.band-title { font-size: 28px; font-weight: 800; letter-spacing: -.02em; color: var(--on-band); }
.band-sub { font-size: 14px; font-weight: 600; color: var(--on-band-dim); }
.band-eyebrow {
  font-size: 11px; font-weight: 800; letter-spacing: .09em;
  text-transform: uppercase; color: var(--on-band-faint);
}
/* Zeitraum-Pill (‹ Juli 2026 ›) – die ganze Pille ist EIN Bedienelement-Cluster */
.band-pill {
  display: flex; align-items: center; gap: 10px;
  background: var(--band-tint); border-radius: 20px; padding: 8px 12px;
  font-size: 13px; font-weight: 800; color: var(--on-band);
  white-space: nowrap;
}
.band-pill button {
  background: none; border: none; padding: 0; margin: 0;
  color: var(--on-band); cursor: pointer; display: flex;
  -webkit-tap-highlight-color: transparent;
}
.band-pill button:active { opacity: .7; }
.band-pill .pick { background: none; border: none; font: 800 13px var(--font); color: var(--on-band); cursor: pointer; padding: 0; }
/* Kleine Text-Pill auf dem Band („Heute", Status-Chip) */
.band-chip {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 12px; font-weight: 800; color: var(--on-band);
  background: var(--band-tint); border: none; cursor: pointer;
  padding: 6px 12px; border-radius: 20px; font-family: var(--font);
  white-space: nowrap;
}
/* Trennlinie im Band (z.B. über dem Schicht-Status im Dashboard) */
.band-divider { border-top: 1px solid var(--band-line); }
/* Volle-Breite-Aktion auf dem Band (z.B. „+ Termin hinzufügen" im Kalender) */
.band-add {
  display: flex; align-items: center; justify-content: center; gap: 7px;
  width: 100%; margin-top: 12px;
  padding: 11px; border: none; border-radius: 14px;
  background: var(--band-tint); color: var(--on-band);
  font: 800 13.5px var(--font); cursor: pointer;
  -webkit-tap-highlight-color: transparent; transition: background .15s;
}
.band-add:hover { background: var(--band-tint-strong); }
.band-add:active { opacity: .8; }

/* ── (1b) v2-Bausteine ── */
/* Eyebrow-Abschnittslabel auf der Seite */
.eyebrow {
  font-size: 11px; font-weight: 800; letter-spacing: .09em;
  text-transform: uppercase; color: var(--text3);
}
/* Abschnittskopf: Eyebrow links, Link/Aktion rechts */
.sec-head { display: flex; align-items: center; justify-content: space-between; margin: 24px 2px 12px; }
.sec-head:first-child { margin-top: 0; }
.sec-link { font-size: 13px; font-weight: 700; color: var(--accent); background: none; border: none; cursor: pointer; font-family: var(--font); padding: 0; }
.sec-link:active { opacity: .7; }
/* Getönte Aktions-Pill („+ Erfassen", „+ Termin", „+ Schicht") */
.pill-action {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 12.5px; font-weight: 800; color: var(--accent);
  background: var(--accent-light); border: none; cursor: pointer;
  padding: 6px 11px; border-radius: 20px; font-family: var(--font);
  white-space: nowrap;
  -webkit-tap-highlight-color: transparent;
}
.pill-action:active { opacity: .8; }
/* Fortschrittsbalken: <div class="progress"><i style="width:X%"></i></div> */
.progress { height: 6px; background: var(--track); border-radius: 6px; overflow: hidden; }
.progress > i { display: block; height: 100%; border-radius: 6px; background: var(--accent2); }
.progress > i.g { background: var(--green-fill); }
.progress > i.y { background: var(--yellow); }
.progress > i.r { background: var(--red); }
.progress > i.p { background: var(--purple); }
.progress.lg { height: 8px; border-radius: 8px; }
/* Haarlinien-Listenzeile in v2-Karten: Karte mit padding 2–4px 18px,
   Zeilen mit padding 14px 0 + Haarlinie dazwischen. */
.hairline-row { border-bottom: 1px solid var(--hairline); }
.hairline-row:last-child { border-bottom: none; }

/* ── (2) body.ui-v2 – Strukturwechsel pro Seite ── */
/* v2-Segmented: Track = Karte, aktiver Tab = Gradient-Pill */
body.ui-v2 .segmented { display: flex; width: 100%; background: var(--bg2); border: none; padding: 5px; border-radius: 16px; }
body.ui-v2 .segmented button { flex: 1; min-width: 0; min-height: 40px; border-radius: 12px; font-size: 12.5px; font-weight: 800; color: var(--text3); white-space: nowrap; padding-left: 4px; padding-right: 4px; }
body.ui-v2 .segmented button.active {
  background: linear-gradient(150deg, var(--accent2), var(--accent-deep));
  color: var(--on-accent);
}
/* Karten in v2 immer rahmenlos (wie .ui-airy, aber ohne Extra-Klasse) */
body.ui-v2 .card, body.ui-v2 .stat-card-new, body.ui-v2 .list-card, body.ui-v2 .table-wrap {
  border-color: transparent;
  box-shadow: var(--shadow-sm);
  border-radius: var(--radius-lg);
}
/* Inhaltsbereich unter dem Band */
.v2-content { padding: 18px 22px 0; }

@media (max-width: 768px) {
  /* Das Band übernimmt die Topbar-Rolle (Logo/Glocke/Logout in .band-top) */
  body.ui-v2 .bubble-topbar { display: none; }
  /* Band bleibt oben am Screen stehen, der Inhalt scrollt darunter durch
     (Justin, 22.07.). sticky statt fixed: behaelt seinen Layout-Platz, keine
     Padding-Kompensation noetig – wichtig, weil die Bandhoehe je Seite und
     Zustand variiert (Dashboard-Hero mit/ohne Live-Balken).
     Ebene 30: ueber dem Inhalt, unter Nav(100)/Statusleisten-Streifen(60)/
     Sheets(900). Der weiche Schatten trennt Band und durchlaufenden Inhalt. */
  body.ui-v2 .band {
    position: sticky;
    top: 0;
    z-index: 30;
    box-shadow: 0 10px 30px -18px rgba(0, 0, 0, .55);
  }
  /* Statusleiste geht ins Band über: fixer Streifen in Band-Blau hinter der
     OS-Leiste (iOS: black-translucent legt die Uhr AUF die Seite – ohne den
     Streifen stuende sie beim Scrollen auf dem Inhalt). Android: Hoehe 0,
     dort faerbt das theme-color-Meta (#2f5bd8, mobile-Media) die Leiste. */
  body.ui-v2::before {
    content: "";
    position: fixed;
    top: 0; left: 0; right: 0;
    height: env(safe-area-inset-top);
    background: var(--band-top);
    z-index: 60;
    pointer-events: none;
  }
  body.ui-v2 .main {
    padding-top: 0;
    padding-left: 0;
    padding-right: 0;
  }
  body.ui-v2 .band-inner { padding-top: calc(10px + env(safe-area-inset-top)); }
  /* Statusleisten-Bereich färbt das Band, nicht die Seite */
  body.ui-v2 .band { border-radius: 0 0 var(--radius-xl) var(--radius-xl); }
}
@media (min-width: 769px) {
  /* Desktop: Bubble-Topbar liefert Logo/Glocke/Logout → Band ohne .band-top,
     dafür rundum gerundet wie eine Karte. */
  body.ui-v2 .band-top { display: none; }
  body.ui-v2 .band { border-radius: var(--radius-xl); }
  body.ui-v2 .v2-content { padding-left: 0; padding-right: 0; }
}

