/* shared.css — Design-System 2.0, CSS-Variablen, Reset, globale Komponenten
   Layout-Chrome (Sidebar/Bottom-Nav/Modals) schaltet über html[data-device],
   das ein Inline-Script vor dem ersten Paint setzt. Inhaltsraster bleiben
   breitenbasiert (@media), da sie vom Platz abhängen, nicht vom Gerät. */

/* ── Design Tokens ──────────────────────────────────────────────────────── */
:root {
  /* Warme Stein-Neutrale statt reinem Grau — ruhiger, hochwertiger Grundton */
  --bg: #f6f5f1;
  --surface: #ffffff;
  --surface2: #eeece5;
  --surface3: #e4e2d9;
  --text: #161a17;
  --text2: #5d635b;
  --text3: #6d7168;   /* WCAG-AA: ≥4.5:1 auf surface/bg (vorher #9a9e95 = 2.3:1) */
  --border: #e6e4dc;
  --border-strong: #d3d1c6;
  --hairline: rgba(22,26,23,.07);   /* 1px-Kontur für Karten/Buttons */

  /* Tieferes, satteres Waldgrün — Markenkern, aber edler */
  --accent: #1d6b4f;
  --accent-hover: #155540;
  --accent-bright: #2f9469;
  --accent-light: #d3ecdd;
  --accent-bg: #eaf3ed;
  --on-accent: #ffffff;

  --night: #41618f;   /* WCAG-AA: 5.07:1 auf night-light (vorher #4a6fa5 = 4.11:1) */
  --night-light: #dce8f5;
  --sunday: #9c3a1c;   /* gemessen: #b34827 auf --sunday-light nur 4,47:1 */   /* WCAG-AA: 4.97:1 auf bg (vorher #e07a5f = 2.70:1) */
  --sunday-light: #fce8e2;
  --holiday: #96606c;  /* WCAG-AA: 5.02:1 auf surface (vorher #b5838d = 3.18:1) */
  --holiday-light: #f5e0e4;
  --danger: #a8222a;   /* gemessen: #bd282e = 4,30:1 an der Leistenkante */
  --danger-light: #fdeaea;
  --warn: #d99a10;
  --warn-light: #fdf3d7;

  /* Mehrschichtige, leicht grün getönte Schatten — Tiefe ohne Grauschleier */
  --shadow-sm: 0 1px 2px rgba(20,32,24,.04), 0 1px 3px rgba(20,32,24,.05);
  --shadow-md: 0 2px 4px rgba(20,32,24,.04), 0 6px 16px rgba(20,32,24,.06), 0 14px 32px rgba(20,32,24,.05);
  --shadow-lg: 0 4px 8px rgba(20,32,24,.06), 0 16px 40px rgba(20,32,24,.10), 0 36px 80px rgba(20,32,24,.10);
  --shadow-accent: 0 3px 10px rgba(29,107,79,.20), 0 12px 28px rgba(29,107,79,.16);
  --card-ring: inset 0 0 0 1px var(--hairline);

  /* Großzügigere, konsistente Radien */
  --radius: 20px;
  --radius-lg: 28px;
  --radius-sm: 14px;
  --radius-xs: 10px;
  --radius-pill: 999px;

  /* Abstands-Skala (4-pt-Raster) */
  --s1: 4px; --s2: 8px; --s3: 12px; --s4: 16px; --s5: 24px; --s6: 32px; --s7: 48px;

  --font: 'Manrope', -apple-system, 'Segoe UI', sans-serif;
  --font-display: 'Fraunces', Georgia, 'Times New Roman', serif;
  --safe-bottom: env(safe-area-inset-bottom, 0px);
  --safe-top: env(safe-area-inset-top, 0px);
  --nav-height: 62px;      /* Höhe der schwebenden Navigations-Kapsel */
  --nav-gap: 10px;         /* Abstand der Kapsel zum Bildschirmrand */
  --nav-total: calc(var(--nav-height) + var(--nav-gap) + var(--safe-bottom));
  --sidebar-w: 224px;

  /* ── „Liquid Glass“: transluzente Ebenen mit Blur + Lichtkante ───────────
     Native Betriebssysteme (iOS 26, One UI 7) staffeln Oberflächen nicht über
     Schatten, sondern über Material: durchscheinend, leicht übersättigt, mit
     heller Kante oben. Deshalb bewusst nur ~72 % Deckkraft. */
  --glass: color-mix(in srgb, var(--surface) 72%, transparent);
  --glass-strong: color-mix(in srgb, var(--surface) 86%, transparent);
  /* Blätter und Dialoge: deutlich durchscheinender als die Leisten, denn hier
     SOLL man die Seite darunter erkennen. Möglich wurde das erst dadurch, dass
     der Inhalt auf deckenden Karten sitzt — freistehend bleiben nur Titel und
     Rubriken in voller Textfarbe. Gemessen halten die selbst gegen Weiß und
     Schwarz noch bis 63 % Deckung; 68 % lässt Reserve. */
  --glass-sheet: color-mix(in srgb, var(--surface) 68%, transparent);
  --glass-edge: rgba(255,255,255,.62);
  --glass-border: color-mix(in srgb, var(--text) 8%, transparent);
  /* Reihenfolge zählt: Filter laufen nacheinander. Erst weichzeichnen, dann
     sättigen — sonst mittelt der Blur die schon angehobene Sättigung wieder
     weg. `saturate()` ist dabei kein Schmuck: reines `blur()` entsättigt den
     Hintergrund, das ist die technische Ursache des milchigen Looks.
     26 px waren zu teuer (Blur-Kosten wachsen quadratisch mit dem Radius —
     26 px kostet rund das Siebenfache von 10 px, bei jedem Scroll-Frame neu). */
  --glass-blur:       blur(16px) saturate(180%);
  --glass-blur-nav:   blur(12px) saturate(170%);   /* dauersichtbar → günstiger */
  --glass-blur-modal: blur(24px) saturate(190%);   /* größere Fläche = dickeres Material */

  /* Rauschen für die Korn-Ebene (siehe body::after) */
  --grain: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E");

  --grad-accent: linear-gradient(135deg, #1a6349 0%, #27805e 100%);  /* Weiss: 7.18/4.84 */
  --grad-hero:   linear-gradient(150deg, #0f3325 0%, #1d6b4f 55%, #2f9469 100%);
  --grad-sheen:  linear-gradient(180deg, rgba(255,255,255,.14) 0%, rgba(255,255,255,0) 60%);
  --trans: .18s cubic-bezier(.4,0,.2,1);
  --trans-slow: .32s cubic-bezier(.22,1,.36,1);
  --spring: .42s cubic-bezier(.34,1.36,.64,1);
}

[data-theme="dark"] {
  --bg: #0d100e;
  --surface: #161a17;
  --surface2: #1f251f;
  --surface3: #29302a;
  --text: #eef1ec;
  --text2: #a4aa9f;
  --text3: #8b9185;   /* WCAG-AA: 4.76:1 auf dark surface (vorher #6d7369 = 3.2:1) */
  --border: #262c26;
  --border-strong: #353c35;
  --hairline: rgba(255,255,255,.06);

  --accent: #52ad83;
  --accent-hover: #64bf94;
  --accent-bright: #6ec79b;
  --accent-light: #1d3a2b;
  --accent-bg: #16291d;
  --on-accent: #06110a;

  --night: #7d9fce;
  --night-light: #1b2836;
  --sunday: #f2ab97;   /* gemessen: #e9967f = 4,08:1 auf getönten Kalenderzellen */
  --sunday-light: #35211b;
  --holiday: #c9959f;
  --holiday-light: #33232a;
  --danger: #f08b8f;   /* gemessen: #e56b6f ergab 4,28:1 auf getönten Flächen */
  --danger-light: #361d1d;
  --warn: #e0b13e;
  --warn-light: #33290f;

  --shadow-sm: 0 1px 2px rgba(0,0,0,.34), 0 1px 3px rgba(0,0,0,.24);
  --shadow-md: 0 2px 6px rgba(0,0,0,.34), 0 8px 22px rgba(0,0,0,.34), 0 16px 40px rgba(0,0,0,.26);
  --shadow-lg: 0 6px 14px rgba(0,0,0,.4), 0 20px 48px rgba(0,0,0,.46), 0 40px 88px rgba(0,0,0,.4);
  --shadow-accent: 0 3px 12px rgba(0,0,0,.4), 0 12px 30px rgba(31,90,66,.34);
  --card-ring: inset 0 0 0 1px var(--hairline);

  --grad-accent: linear-gradient(135deg, #1a6349 0%, #27805e 100%);  /* identisch: absolute Farben */
  --grad-hero:   linear-gradient(150deg, #0b1f16 0%, #1a4732 55%, #2a7455 100%);
  --grad-sheen:  linear-gradient(180deg, rgba(255,255,255,.07) 0%, rgba(255,255,255,0) 60%);

  /* Glas im Dunkelmodus: dunkler, Lichtkante dezenter */
  --glass: color-mix(in srgb, var(--surface) 68%, transparent);
  --glass-strong: color-mix(in srgb, var(--surface) 84%, transparent);
  --glass-sheet: color-mix(in srgb, var(--surface) 68%, transparent);
  --glass-edge: rgba(255,255,255,.10);
  --glass-border: rgba(255,255,255,.09);
}

/* ══════════════════════════════════════════════════════════════════════════
   PERSONALISIERUNG — vom Nutzer einstellbar (Einstellungen → Darstellung)
   ──────────────────────────────────────────────────────────────────────────
   1) Akzentfarbe: sechs abgestimmte Paletten. Jede definiert Grundton, Hover,
      Aufheller und Flächen — alle Werte sind so gewählt, dass WEISSER Text auf
      dem Verlauf und die Fläche selbst die AA-Kontrastschwelle halten.
   2) Anzeigegröße: skaliert die Basis-Schriftgröße (alle rem-Maße folgen).
   3) Transparenz reduzieren: ersetzt die Glas-Ebenen durch deckende Flächen —
      hilft bei schwacher Sicht und auf langsamen Geräten.
   ══════════════════════════════════════════════════════════════════════════ */
[data-accent="ocean"] {
  --accent: #14607f; --accent-hover: #104e67; --accent-bright: #2b8fb4;
  --accent-light: #cfe8f2; --accent-bg: #e8f3f8; --on-accent: #ffffff;
  --grad-accent: linear-gradient(135deg, #15586f 0%, #217a99 100%);
  --grad-hero: linear-gradient(150deg, #0c2c39 0%, #14607f 55%, #2b8fb4 100%);
}
[data-theme="dark"][data-accent="ocean"] {
  --accent: #4fb0d4; --accent-hover: #63c0e2; --accent-bright: #6cc6e6;
  --accent-light: #123543; --accent-bg: #102a35; --on-accent: #04141b;
}
[data-accent="sunset"] {
  --accent: #a5421f;   /* WCAG-AA: 4.74:1 auf accent-light (vorher #b3492a = 4.13:1) */ --accent-hover: #963a1f; --accent-bright: #d9673f;
  --accent-light: #f7dcd2; --accent-bg: #fbeae3; --on-accent: #ffffff;
  --grad-accent: linear-gradient(135deg, #a5411f 0%, #b85327 100%);  /* Ende #c85b33 trug Weiß nur 4,18:1 — jetzt 4,88 */
  --grad-hero: linear-gradient(150deg, #3d1509 0%, #a5411f 55%, #d9673f 100%);
}
[data-theme="dark"][data-accent="sunset"] {
  --accent: #e08a68; --accent-hover: #ec9d7d; --accent-bright: #f0a98b;
  --accent-light: #3a1d12; --accent-bg: #2c160e; --on-accent: #1a0803;
}
[data-accent="violet"] {
  --accent: #6246a8; --accent-hover: #513a8c; --accent-bright: #8368c9;
  --accent-light: #e2dbf5; --accent-bg: #eee9fa; --on-accent: #ffffff;
  --grad-accent: linear-gradient(135deg, #58409a 0%, #7458bd 100%);
  --grad-hero: linear-gradient(150deg, #221542 0%, #58409a 55%, #8368c9 100%);
}
[data-theme="dark"][data-accent="violet"] {
  --accent: #a58ae0; --accent-hover: #b59ceb; --accent-bright: #bda6ef;
  --accent-light: #2b2145; --accent-bg: #221a38; --on-accent: #0d0719;
}
[data-accent="amber"] {
  --accent: #8a5a09; --accent-hover: #714a07; --accent-bright: #b8830f;
  --accent-light: #f7e6c4; --accent-bg: #fbf1dc; --on-accent: #ffffff;
  --grad-accent: linear-gradient(135deg, #7d5108 0%, #9c6a0c 100%);
  --grad-hero: linear-gradient(150deg, #3a2503 0%, #7d5108 55%, #b8830f 100%);
}
[data-theme="dark"][data-accent="amber"] {
  --accent: #d9a63f; --accent-hover: #e6b855; --accent-bright: #e8bb5c;
  --accent-light: #3b2c0d; --accent-bg: #2d210a; --on-accent: #170f02;
}
[data-accent="graphite"] {
  --accent: #414852; --accent-hover: #333941; --accent-bright: #626b78;
  --accent-light: #dfe2e6; --accent-bg: #eceef0; --on-accent: #ffffff;
  --grad-accent: linear-gradient(135deg, #3a4049 0%, #545c68 100%);
  --grad-hero: linear-gradient(150deg, #191c21 0%, #3a4049 55%, #626b78 100%);
}
[data-theme="dark"][data-accent="graphite"] {
  --accent: #9aa4b2; --accent-hover: #adb6c2; --accent-bright: #b4bdc8;
  --accent-light: #2a2f36; --accent-bg: #21252b; --on-accent: #0b0d10;
}

/* Anzeigegröße — alle rem-Maße skalieren mit */
html[data-scale="compact"] { font-size: 15px; }
html[data-scale="large"]   { font-size: 17.6px; }

/* Transparenz reduzieren: Glas → deckend (bessere Lesbarkeit, weniger Rechenlast) */
html[data-glass="off"] {
  --glass: var(--surface);
  --glass-strong: var(--surface);
  --glass-sheet: var(--surface);
  --glass-blur: none;
  --glass-blur-nav: none;
  --glass-blur-modal: none;
}
html[data-glass="off"] .bottom-nav,
html[data-glass="off"] .app-header,
html[data-glass="off"] .demo-banner,
html[data-glass="off"] .cal-batch-bar,
html[data-glass="off"] .month-label,
html[data-glass="off"] .modal-sheet,
html[data-glass="off"] .dialog-box,
html[data-glass="off"] .sheet-foot,
html[data-glass="off"] .hm-nav { backdrop-filter: none; -webkit-backdrop-filter: none; }
/* Systemeinstellung „Transparenz reduzieren“ zählt genauso — sie ist eine
   Barrierefreiheits-Angabe, keine Geschmacksfrage. */
@media (prefers-reduced-transparency: reduce) {
  :root, [data-theme="dark"] {
    --glass: var(--surface); --glass-strong: var(--surface); --glass-sheet: var(--surface);
  }
  .modal-sheet, .dialog-box, .sheet-foot, .bottom-nav, .app-header {
    backdrop-filter: none; -webkit-backdrop-filter: none;
  }
}

/* Farbauswahl: sechs Punkte, der aktive bekommt einen Ring + Häkchen-Gefühl */
.accent-picker { display: flex; gap: 12px; flex-wrap: wrap; margin-top: 10px; }
.accent-dot {
  width: 38px; height: 38px; border-radius: 50%; cursor: pointer; flex-shrink: 0;
  border: 2px solid transparent; position: relative;
  transition: transform var(--spring), box-shadow var(--trans);
  box-shadow: var(--shadow-sm), inset 0 1px 0 rgba(255,255,255,.25);
}
.accent-dot:hover  { transform: scale(1.08); }
.accent-dot:active { transform: scale(.94); }
.accent-dot.is-active { box-shadow: 0 0 0 3px var(--surface), 0 0 0 5.5px currentColor, var(--shadow-sm); }
.accent-dot[data-accent-val="forest"]   { background: linear-gradient(135deg,#1a6349,#27805e); color:#1d6b4f; }
.accent-dot[data-accent-val="ocean"]    { background: linear-gradient(135deg,#15586f,#217a99); color:#14607f; }
.accent-dot[data-accent-val="sunset"]   { background: linear-gradient(135deg,#a5411f,#c85b33); color:#b3492a; }
.accent-dot[data-accent-val="violet"]   { background: linear-gradient(135deg,#58409a,#7458bd); color:#6246a8; }
.accent-dot[data-accent-val="amber"]    { background: linear-gradient(135deg,#7d5108,#9c6a0c); color:#8a5a09; }
.accent-dot[data-accent-val="graphite"] { background: linear-gradient(135deg,#3a4049,#545c68); color:#414852; }

/* ── Reset ──────────────────────────────────────────────────────────────── */
*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }
html { font-size: 16px; -webkit-tap-highlight-color: transparent; }
body {
  font-family: var(--font);
  background: var(--bg);
  color: var(--text);
  min-height: 100dvh;
  overflow-x: hidden;
  padding-bottom: calc(var(--nav-total) + 16px);
  transition: background .3s, color .3s;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  /* Variable Achsen nutzen + Ziffern gleichbreit (Beträge springen nie) */
  font-optical-sizing: auto;
  font-feature-settings: 'tnum' 1, 'cv11' 1;
  letter-spacing: -.006em;
  text-rendering: optimizeLegibility;
}

/* ── Korn-Ebene ─────────────────────────────────────────────────────────────
   Jeder Farbkanal hat 256 Stufen. Ein flacher Verlauf über eine breite Fläche
   ändert die Farbe langsamer als eine Stufe pro Pixel — dann werden aus der
   weichen Rampe sichtbare Streifen. Eine feine Rauschebene verwischt diese
   Quantisierungsgrenze (räumliches Dithering): benachbarte Pixel landen auf
   unterschiedlichen Nachbarstufen, das Auge mittelt sie zurück. Weichzeichnen
   hilft dagegen nicht — es verschiebt dieselben Stufen nur.
   Eine einzige Ebene für die ganze App statt einer pro Karte: ein Malvorgang,
   alle Verläufe gleichzeitig entstört — und der leichte Filmkorn-Charakter,
   der Flächen wie Material statt wie Farbe wirken lässt. */
body::after {
  content: ''; position: fixed; inset: 0; z-index: 290; pointer-events: none;
  background-image: var(--grain);
  background-size: 140px 140px;
  opacity: .035; mix-blend-mode: overlay;
}
[data-theme="dark"] body::after { opacity: .05; mix-blend-mode: soft-light; }
/* „Transparenz reduzieren“ schaltet auch das Korn ab (Nutzerwunsch = weniger
   Effekte, nicht nur weniger Glas). */
html[data-glass="off"] body::after { display: none; }
@media (prefers-reduced-transparency: reduce) { body::after { display: none; } }
/* Display-Serif: optisch großzügig, aber eng gesetzt — editorialer Charakter */
.app-title, .modal-title, .dialog-title, .spane-title, h1, h2 {
  font-family: var(--font-display);
  font-optical-sizing: auto;
  font-weight: 600;
  letter-spacing: -.018em;
  font-variation-settings: 'SOFT' 0, 'WONK' 0;
}
button { font-family: var(--font); border: none; cursor: pointer; background: none; color: var(--text); }
input, select, textarea { font-family: var(--font); color: var(--text); }
::selection { background: var(--accent-light); }

@media (max-width: 340px) {
  .icon-btn { width: 36px; height: 36px; }
  .header-actions { gap: 6px; }
  .hm-nav { width: 26px; height: 26px; }
}

/* ── Icon-System (icons.js) ─────────────────────────────────────────────────
   Alle Icons erben Farbe per currentColor und Größe per Klasse — dadurch
   sitzen sie automatisch harmonisch in Buttons, Listen und Badges. */
.ic {
  width: 1.15em; height: 1.15em; flex-shrink: 0;
  vertical-align: -.18em;
  stroke: currentColor; fill: none;
}
.ic-sm { width: 1em;    height: 1em; }
.ic-lg { width: 1.4em;  height: 1.4em; }
.ic-xl { width: 1.75em; height: 1.75em; }

/* Zugänglichkeit: sichtbarer Fokus nur bei Tastaturbedienung */
:focus { outline: none; }
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px; border-radius: 6px;
  box-shadow: 0 0 0 5px color-mix(in srgb, var(--accent) 18%, transparent);
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}

/* Zahlen in Karten/Tabellen: gleichbreite Ziffern */
.stat-card .value, .dq-value, .dh-value, .ic-value, .payout-amount,
.payslip-row, .breakdown-row, .rolling-table, .shift-earn, .tc-amount,
.month-label { font-variant-numeric: tabular-nums; }

/* ── Animations ─────────────────────────────────────────────────────────── */
@keyframes fadeUp  { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: translateY(0); } }
@keyframes fadeIn  { from { opacity: 0; } to { opacity: 1; } }
@keyframes slideUp { from { transform: translateY(100%); } to { transform: translateY(0); } }
@keyframes popIn   { from { opacity: 0; transform: scale(.96) translateY(8px); } to { opacity: 1; transform: none; } }
@keyframes shimmer { 0% { background-position: -200% 0; } 100% { background-position: 200% 0; } }
@keyframes spin    { to { transform: rotate(360deg); } }

/* ── Skeleton Loading ────────────────────────────────────────────────────── */
.skeleton {
  background: linear-gradient(90deg, var(--surface2) 25%, var(--border) 50%, var(--surface2) 75%);
  background-size: 200% 100%;
  animation: shimmer 1.4s ease-in-out infinite;
  border-radius: var(--radius-sm);
}
.sk-hero  { height: 130px; border-radius: var(--radius); margin-bottom: 14px; }
.sk-row   { display: flex; gap: 10px; margin-bottom: 14px; }
.sk-card  { flex: 1; height: 72px; border-radius: var(--radius-sm); }
.sk-grid  { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.sk-stat  { height: 88px; border-radius: var(--radius); }

/* ── Pull-to-Refresh Indicator ───────────────────────────────────────────── */
#pullRefreshIndicator {
  position: fixed; top: -40px; left: 50%; z-index: 9000;
  transform: translateX(-50%);
  width: 40px; height: 40px; border-radius: 50%;
  background: var(--accent); color: var(--on-accent);
  display: flex; align-items: center; justify-content: center;
  box-shadow: var(--shadow-md); opacity: 0; pointer-events: none;
  transition: opacity .25s, transform .25s;
}
#pullRefreshIndicator svg {
  width: 18px; height: 18px; stroke: currentColor;
  transition: transform .6s linear;
}

/* ── Header ─────────────────────────────────────────────────────────────── */
.app-header {
  position: sticky; top: 0; z-index: 100;
  background: color-mix(in srgb, var(--bg) 68%, transparent);
  /* Notch-sicher: env-Insets (Fallback 0 → keine Wirkung auf Desktop/randlos) */
  padding: calc(12px + var(--safe-top)) calc(20px + env(safe-area-inset-right, 0px)) 10px calc(20px + env(safe-area-inset-left, 0px));
  display: flex; flex-direction: column; align-items: stretch; gap: 3px;
  backdrop-filter: var(--glass-blur); -webkit-backdrop-filter: var(--glass-blur);
  /* Randlos bis zum Scrollen: erst dann eine feine Trennkante (siehe app.js) */
  border-bottom: 1px solid transparent;
  transition: background .3s, border-color .3s, padding .28s cubic-bezier(.4,0,.2,1);
}
/* Beim Scrollen kondensiert der Kopf: die Markenzeile verschwindet, und die
   beiden Zeilen legen sich nebeneinander — aus großem Titel wird eine schmale
   Leiste, ohne dass etwas verloren geht. */
body.is-scrolled .app-header {
  border-bottom-color: var(--glass-border);
  padding-top: calc(7px + var(--safe-top)); padding-bottom: 6px;
  background: var(--glass-strong);
  flex-direction: row; align-items: center; gap: 10px;
}
body.is-scrolled .hdr-top { order: 2; flex: 0 0 auto; }
body.is-scrolled .hdr-month { order: 1; flex: 1 1 auto; }
/* Im zusammengeklappten Kopf teilt sich der Monat die Zeile mit den drei
   Werkzeugen — dort bleiben ihm 121 px. „September 2026“ brauchte bei 1,08 rem
   noch 130 px; 1 rem passt für jeden Monatsnamen (gemessen). */
body.is-scrolled .app-title { font-size: 1rem; }
body.is-scrolled .hm-nav { width: 26px; height: 26px; }
/* Große Titelzeile (iOS-Manier): kräftig oben, kondensiert beim Scrollen.
   Der Monat hat jetzt die volle Kopfbreite, deshalb darf er größer werden. */
.app-title {
  font-family: var(--font-display); letter-spacing: -.028em;
  font-size: clamp(1.32rem, 7vw, 1.8rem);
  transition: font-size .28s cubic-bezier(.4,0,.2,1);
}
.header-actions { display: flex; gap: 8px; flex: 0 0 auto; }

/* ── Icon Button ────────────────────────────────────────────────────────── */
.icon-btn {
  width: 40px; height: 40px; border-radius: var(--radius-sm);
  display: flex; align-items: center; justify-content: center;
  background: var(--surface); box-shadow: var(--shadow-sm), var(--card-ring);
  transition: background var(--trans), box-shadow var(--trans), transform var(--trans);
  cursor: pointer;
}
.icon-btn:hover  { background: var(--surface); box-shadow: var(--shadow-md), var(--card-ring); transform: translateY(-1px); }
.icon-btn:hover svg { stroke: var(--accent); }
.icon-btn:active { transform: scale(.94); }
.icon-btn svg {
  width: 18px; height: 18px;
  stroke: var(--text2); fill: none; stroke-width: 1.9;
  stroke-linecap: round; stroke-linejoin: round;
  transition: stroke var(--trans);
}
#btnDark .icon-sun { display: none; }
#btnDark .icon-moon { display: block; }
#btnDark[data-dark="1"] .icon-sun { display: block; }
#btnDark[data-dark="1"] .icon-moon { display: none; }

/* ── Month Navigation ───────────────────────────────────────────────────── */
/* ── Kopfzeile mit integriertem Monatswähler ────────────────────────────────
   Der Monat IST jetzt die Überschrift (nativer Kontext-vor-Marke-Ansatz), der
   Produktname sitzt als kleine Zeile darüber. Spart eine ganze Bildschirmzeile
   und macht sofort klar, welchen Zeitraum man sieht. */
.hdr-left { min-width: 0; flex: 1 1 auto; overflow: hidden; }
/* Obere Zeile: Marke links, Werkzeuge rechts — beides klein. */
.hdr-top { display: flex; align-items: center; justify-content: space-between; gap: 10px; min-width: 0; }
.hdr-brand {
  font-size: max(11px, .72rem); font-weight: 700; letter-spacing: .04em;
  color: var(--text3); text-transform: uppercase;
  transition: opacity .24s, max-height .28s, margin .28s;
}
/* Untere Zeile: der Monat über die ganze Breite — genug Platz für jeden
   Monatsnamen, und die Pfeile stehen weit genug auseinander zum Treffen. */
.hdr-month { display: flex; align-items: center; gap: 2px; margin-left: -6px; min-width: 0; }
.month-label {
  font-weight: 600; padding: 2px 6px; border-radius: var(--radius-sm);
  cursor: pointer; user-select: none; white-space: nowrap;
  min-width: 0; overflow: hidden; text-overflow: ellipsis;
  transition: background var(--trans);
}
/* Das Jahr kleiner, leichter und in der UI-Schrift — es ordnet sich dem
   Monatsnamen unter und spart dabei genug Breite für „September“. */
.month-label .ml-y {
  font-family: var(--font); font-size: .64em; font-weight: 600;
  color: var(--text2); margin-left: .34em; letter-spacing: 0;
  vertical-align: .06em;
}
.month-label:hover { background: var(--surface2); }
.hm-nav {
  width: 30px; height: 30px; border-radius: 10px; flex-shrink: 0;
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--text2); transition: background var(--trans), transform var(--spring);
}
.hm-nav:hover  { background: var(--surface2); color: var(--accent); }
.hm-nav:active { transform: scale(.9); }
.hm-nav svg { width: 17px; height: 17px; stroke: currentColor; fill: none; stroke-width: 2.4; stroke-linecap: round; }
/* Beim Scrollen verschwindet die Markenzeile — der Monat bleibt als Titel.
   Im zusammengeklappten Kopf stehen beide Zeilen NEBENeinander, deshalb muss
   die Marke auch ihre BREITE aufgeben: unsichtbar, aber 113 px breit, hätte sie
   den Monatstitel auf 12 px zusammengedrückt („J“ statt „Juli 2026“). */
body.is-scrolled .hdr-brand {
  opacity: 0; max-height: 0; max-width: 0; margin-bottom: -2px; overflow: hidden;
}
.hdr-brand { max-width: 100%; transition: opacity .24s, max-height .28s, max-width .28s, margin .28s; }
.month-label:active { transform: scale(.96); }

/* ── Bottom Nav (Mobile-Chrome, wird am Desktop zur Sidebar) ────────────── */
/* Schwebende Glas-Kapsel statt randloser Leiste — das prägendste native Merkmal
   aktueller iOS-/One-UI-Oberflächen. Löst sich vom Rand, Inhalt scheint durch. */
.bottom-nav {
  position: fixed; z-index: 200;
  left: var(--nav-gap); right: var(--nav-gap);
  bottom: calc(var(--nav-gap) + var(--safe-bottom));
  height: var(--nav-height);
  padding: 0 5px;
  border-radius: 24px;
  background: var(--glass);
  border: 1px solid var(--glass-border);
  display: flex; align-items: center; justify-content: space-around;
  backdrop-filter: var(--glass-blur-nav); -webkit-backdrop-filter: var(--glass-blur-nav);
  box-shadow: var(--shadow-lg), inset 0 1px 0 var(--glass-edge);
  transition: background .3s;
}
.nav-brand { display: none; }
.nav-item {
  display: flex; flex-direction: column; align-items: center; gap: 3px;
  flex: 1; max-width: 76px;
  padding: 8px 4px; border-radius: 17px;
  transition: color var(--trans), transform var(--spring);
  font-size: max(11px, .68rem); font-weight: 650; color: var(--text2);
  letter-spacing: -.005em;
  position: relative; isolation: isolate;   /* für die Kapsel hinter dem Inhalt */
}
.nav-item.active { color: var(--accent); }
/* Aktiver Tab: gefüllte Kapsel hinter Icon+Label (statt dünnem Strich oben) —
   klarer, größerer Trefferbereich und der Look, den iOS/One UI heute nutzen. */
.nav-item.active::before {
  content: ''; position: absolute; inset: 3px -1px;
  border-radius: 17px; z-index: -1;
  background: color-mix(in srgb, var(--accent) 15%, transparent);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--accent) 22%, transparent);
  animation: navPop var(--spring);
}
@keyframes navPop { from { transform: scale(.82); opacity: 0; } to { transform: scale(1); opacity: 1; } }
.nav-item.active svg { stroke: var(--accent); }
.nav-item:active  { transform: scale(.9); }
.nav-item svg { width: 21px; height: 21px; stroke: currentColor; fill: none; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; transition: stroke var(--trans); }
/* Eigene Navigations-Icons (icons.js): etwas kräftiger als Listen-Icons, damit
   sie auf 21 px klar bleiben; aktiver Tab bekommt zusätzlich Gewicht. */
.nav-ic { display: inline-flex; }
.nav-ic .ic { width: 22px; height: 22px; stroke-width: 1.85; }
.nav-item.active .nav-ic .ic { stroke-width: 2.3; }

/* ── Views ──────────────────────────────────────────────────────────────── */
/* Unten Luft lassen: der schwebende +-Button (FAB) saß sonst auf der letzten
   Karte und verdeckte Inhalte. */
/* Seitenabstand als Token, damit randlose Elemente (etwa die Filterzeile) ihn
   negativ zurücknehmen können, ohne dass die beiden Werte auseinanderlaufen —
   genau so war ein 4-px-Überlauf entstanden. */
.view { --view-pad: 16px; display: none; padding: 0 var(--view-pad) 84px; }
/* Der Kalender nutzt fast die ganze Breite — dadurch werden die Tageszellen
   deutlich größer und die Zahlen darin besser lesbar. */
#viewCalendar { padding-left: 8px; padding-right: 8px; }
.view.active { display: block; animation: fadeUp .28s cubic-bezier(.22,1,.36,1); }

/* ── Stat Cards ─────────────────────────────────────────────────────────── */
.stats-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-bottom: 16px; }
.stat-card {
  background: var(--surface); border-radius: var(--radius); padding: 17px;
  position: relative; overflow: hidden;
  box-shadow: var(--shadow-sm), var(--card-ring);
  transition: transform var(--trans), box-shadow var(--trans);
}
.stat-card:active { transform: scale(.97); }
.stat-card.wide { grid-column: 1/-1; }
/* Sonderkarten-Reihe: mobil verhält sie sich wie gar nicht vorhanden
   (display:contents → Karten stapeln wie bisher), am Desktop wird sie zum
   Raster. Abstände liefern die Karten mobil selbst nicht — deshalb dort gap
   über das Eltern-Grid ab 900 px und mobil ein eigener Abstand. */
.dash-wide-row { display: flex; flex-direction: column; gap: 12px; margin-bottom: 16px; }
.dash-wide-row:empty { display: none; }
.stat-card .label { font-size: .76rem; font-weight: 600; color: var(--text2); letter-spacing: -.004em; margin-bottom: 6px; }
.stat-card .value { font-family: var(--font-display); font-size: 1.6rem; line-height: 1.2; letter-spacing: -.01em; }
.stat-card .sub   { font-size: .75rem; color: var(--text2); margin-top: 4px; }
.stat-card.accent { background: var(--grad-accent); color: #fff; box-shadow: 0 8px 24px rgba(45,106,79,.28); }
.stat-card.accent .label { color: rgba(255,255,255,.72); }
.stat-card.accent .sub   { color: rgba(255,255,255,.62); }
.stat-card.night   { border-left: 3px solid var(--night); }
.stat-card.sunday  { border-left: 3px solid var(--sunday); }
.stat-card.holiday { border-left: 3px solid var(--holiday); }

/* ── Breakdown Cards ────────────────────────────────────────────────────── */
.breakdown-card { background: var(--surface); border-radius: var(--radius); padding: 18px; box-shadow: var(--shadow-sm), var(--card-ring); margin-bottom: 12px; }
.breakdown-card h3 { font-size: .92rem; font-weight: 700; letter-spacing: -.014em; color: var(--text); margin-bottom: 12px; }
.breakdown-row { display: flex; justify-content: space-between; padding: 8px 0; border-bottom: 1px solid var(--border); font-size: .85rem; }
.breakdown-row:last-child { border: none; }
.breakdown-row .br-label { color: var(--text2); }
.breakdown-row .br-value { font-weight: 650; }
.breakdown-row.night-row   .br-label::before,
.breakdown-row.sunday-row  .br-label::before,
.breakdown-row.holiday-row .br-label::before {
  content: ''; display: inline-block; width: 8px; height: 8px; border-radius: 50%; margin-right: 6px;
}
.breakdown-row.night-row   .br-label::before { background: var(--night); }
.breakdown-row.sunday-row  .br-label::before { background: var(--sunday); }
.breakdown-row.holiday-row .br-label::before { background: var(--holiday); }
.breakdown-row.total-row { font-weight: 700; font-size: .95rem; padding-top: 12px; border-top: 2px solid var(--border-strong); }

/* ── Shift List ─────────────────────────────────────────────────────────── */
.shift-list { display: flex; flex-direction: column; gap: 9px; }
.shift-item {
  background: var(--surface); border-radius: var(--radius-sm); padding: 14px 16px 14px 18px;
  box-shadow: var(--shadow-sm), var(--card-ring); display: flex; flex-direction: column; gap: 6px;
  position: relative; overflow: hidden;
  transition: transform var(--trans), box-shadow var(--trans);
}
/* ── Kantenlicht („glow-l“) ─────────────────────────────────────────────────
   Vorgänger war ein linearer Verlauf über 62 % der Kartenbreite in sRGB. Der
   wirkte wie ein schmutziger Schleier — und zwar aus einem Grund, den man der
   Farbe nicht ansieht:

   DIE TINT-FARBE WAR DER FEHLER. `--accent`, `--night`, `--sunday` sind alle
   als AA-taugliche TEXTfarben gewählt, also dunkel und wenig bunt (--accent
   hell = #1d6b4f, oklch L≈0.44). 26 % einer dunklen Farbe auf eine Fläche
   gemischt ist mathematisch eine ABDUNKLUNG bei sinkender Sättigung — exakt
   die Definition eines grauen Schleiers. Licht hebt dagegen Helligkeit UND
   Sättigung.

   Deshalb wird hier eine eigene LICHTfarbe aus der Kennfarbe abgeleitet
   (hoher L, hoher C). Die Chroma-Kurve macht die Arbeit: im Kern fast
   überstrahlt (C niedrig, L sehr hoch), im Mittelfeld der Sättigungsgipfel,
   im Ausläufer etwas kühler — so verhält sich echtes Licht. Ein Verlauf, der
   nur Alpha ändert, liest sich dagegen immer als getönte Folie.

   Weitere Regeln, die hier zusammenspielen:
   · CORE + BLOOM statt eines Verlaufs — die Summe zweier Radien mit sehr
     unterschiedlichem Radius ergibt von selbst den 1/d²-Abfall.
   · MASKE statt Verlaufs-Stopp: die Lichtebene wird vor der Textspalte
     physisch abgeschnitten. Kein Alpha über dem Text, kein Kontrastverlust.
   · BLENDMODUS nach Thema: im Dunkeln additiv (Licht), im Hellen subtraktiv
     (Farbfolie vor weißem Papier). Ohne diese Trennung sieht genau ein Thema
     immer schmutzig aus.
   · --heat (0…1) steuert die Intensität: in den Listen der Verdienst des Tages
     bzw. die Länge der Fahrt. Das Leuchten ist damit keine Dekoration, sondern
     eine Aussage — ein starker Tag leuchtet sichtbar heller.

   Verwendung: Klasse `glow-l` + `--glow: <Kennfarbe>` (Standard = Akzent). */
.glow-l {
  position: relative; overflow: hidden; isolation: isolate;
  --lit-core: oklch(from var(--glow, var(--accent)) .97 calc(c * .55)  h);
  --lit:      oklch(from var(--glow, var(--accent)) .92 calc(c * 1.55) h);
  --lit-far:  oklch(from var(--glow, var(--accent)) .84 calc(c * 1.15) calc(h - 14));
}
[data-theme="dark"] .glow-l {
  --lit-core: oklch(from var(--glow, var(--accent)) .90 calc(c * .90)  h);
  --lit:      oklch(from var(--glow, var(--accent)) .78 calc(c * 1.35) h);
  --lit-far:  oklch(from var(--glow, var(--accent)) .64 calc(c * 1.10) calc(h - 14));
}
/* „graphite“ ist praktisch unbunt — dort würde die Chroma-Rechnung nichts
   ergeben. Neutrales Licht statt gar keinem. */
[data-accent="graphite"] .glow-l {
  --lit-core: #fff; --lit: oklch(.94 .012 250); --lit-far: oklch(.88 .014 250);
}
[data-theme="dark"][data-accent="graphite"] .glow-l {
  --lit-core: oklch(.92 .008 250); --lit: oklch(.80 .014 250); --lit-far: oklch(.66 .016 250);
}
/* Ohne relative Farben (ältere Engines): auf die vorhandenen Aufheller-Token
   zurückfallen. Sie sind zwar nicht so brillant, aber nie schmutzig. */
@supports not (color: oklch(from red l c h)) {
  .glow-l { --lit-core: #fff; --lit: var(--accent-light); --lit-far: var(--accent-light); }
  .glow-l.is-night  { --lit: var(--night-light);  --lit-far: var(--night-light); }
  .glow-l.is-sunday { --lit: var(--sunday-light); --lit-far: var(--sunday-light); }
}

.glow-l::before {
  content: ''; position: absolute; inset: 0; pointer-events: none; z-index: 0;
  border-radius: inherit;
  background:
    /* CORE — schmaler, fast überstrahlter Kern direkt an der Kante */
    radial-gradient(40px 130% at 0% 50%,
      color-mix(in oklab, var(--lit-core) calc(19% + 19% * var(--heat, .5)), transparent) 0%,
      color-mix(in oklab, var(--lit)      calc(10% + 11% * var(--heat, .5)), transparent) 22%,
      color-mix(in oklab, var(--lit)      calc( 4% +  5% * var(--heat, .5)), transparent) 48%,
      transparent 100%),
    /* BLOOM — Halo, Farbtemperatur wandert nach außen. Bewusst kurz gehalten:
       ein Halo über die halbe Karte wäre wieder ein Schleier. */
    radial-gradient(150px 260% at -6% 50%,
      color-mix(in oklab, var(--lit)     calc(3% + 3.5% * var(--heat, .5)), transparent) 0%,
      color-mix(in oklab, var(--lit-far) 1.2%, transparent) 45%,
      transparent 100%);
  /* Deutlich vor der Textspalte auslaufen lassen — der Text liegt auf
     unberührter Fläche, nicht unter einem Alpha-Film. */
  /* Maske in PIXELN, nicht in Prozent: der Text beginnt bei 18 px — eine
     Prozent-Maske ließ den Schein auf breiten Karten weit unter die Schrift
     laufen. Der Volllauf über alle Paletten fand genau dort 4,26–4,33:1
     (hell/sunset/amber/violet, --text2 am Zeilenanfang). Jetzt trägt der
     Schein voll nur in der textfreien Kantenzone und ist unter dem ersten
     Buchstaben praktisch erloschen — das Kantenlicht wird dadurch sogar
     präziser: Licht an der Kante, nicht Wäsche unter dem Text. */
  -webkit-mask-image: linear-gradient(90deg, #000 0px, rgba(0,0,0,.45) 12px, rgba(0,0,0,.10) 18px, transparent 44px);
          mask-image: linear-gradient(90deg, #000 0px, rgba(0,0,0,.45) 12px, rgba(0,0,0,.10) 18px, transparent 44px);
  mix-blend-mode: multiply;
}
/* Im Dunkeln addiert sich Licht — dieselben Prozentwerte wirken dort viel
   stärker als der subtraktive Fall im Hellen. Deshalb eigene, leisere Werte. */
[data-theme="dark"] .glow-l::before {
  mix-blend-mode: screen;
  background:
    radial-gradient(40px 130% at 0% 50%,
      color-mix(in oklab, var(--lit-core) calc(11% + 13% * var(--heat, .5)), transparent) 0%,
      color-mix(in oklab, var(--lit)      calc( 6% +  8% * var(--heat, .5)), transparent) 22%,
      color-mix(in oklab, var(--lit)      calc(2.5% + 3% * var(--heat, .5)), transparent) 48%,
      transparent 100%),
    radial-gradient(150px 260% at -6% 50%,
      color-mix(in oklab, var(--lit)     calc(2% + 2.5% * var(--heat, .5)), transparent) 0%,
      color-mix(in oklab, var(--lit-far) .8%, transparent) 45%,
      transparent 100%);
}
@supports (mix-blend-mode: plus-lighter) {
  [data-theme="dark"] .glow-l::before { mix-blend-mode: plus-lighter; }
}

/* Kennmarke an der Kante als Lichtleiter: Intensitätsgipfel in der Mitte,
   an beiden Enden ins Nichts auslaufend, mit zweistufigem Spill. Ein Balken
   mit harten Enden und konstanter Helligkeit liest sich als Druckstreifen. */
.glow-l::after {
  content: ''; position: absolute; left: 0; top: 7px; bottom: 7px; width: 2.5px;
  border-radius: 0 3px 3px 0; pointer-events: none; z-index: 1;
  background: linear-gradient(180deg in oklab,
    color-mix(in oklab, var(--glow, var(--accent))     0%, transparent)   0%,
    color-mix(in oklab, var(--glow, var(--accent))    72%, transparent)  18%,
    color-mix(in oklab, var(--lit-core)               92%, transparent)  50%,
    color-mix(in oklab, var(--glow, var(--accent))    72%, transparent)  82%,
    color-mix(in oklab, var(--glow, var(--accent))     0%, transparent) 100%);
  box-shadow:
    0 0  6px color-mix(in oklab, var(--lit) calc(22% + 28% * var(--heat, .5)), transparent),
    0 0 18px color-mix(in oklab, var(--lit) calc( 8% + 12% * var(--heat, .5)), transparent);
}
/* Inhalt über dem Schein halten */
.glow-l > * { position: relative; z-index: 2; }

/* ── Wischen zum Löschen: Rückmeldung ───────────────────────────────────────
   `pan-y` lässt vertikales Scrollen beim Browser und gibt nur die horizontale
   Achse an die Geste ab. Ab der Löschschwelle bekommt die Zeile einen roten
   Innenrahmen — man sieht also vor dem Loslassen, was passieren wird. */
.shift-item, .trip-card { touch-action: pan-y; }
.shift-item.swiping, .trip-card.swiping { will-change: transform; z-index: 3; }
.shift-item.swipe-armed, .trip-card.swipe-armed {
  box-shadow: var(--shadow-md), inset 0 0 0 2px color-mix(in srgb, var(--danger) 60%, transparent);
}

/* Schichtzeilen: Kennfarbe je Art */
.shift-item { --glow: var(--accent); }
.shift-item.is-sunday  { --glow: var(--sunday); }
.shift-item.is-holiday { --glow: var(--holiday); }
.shift-item.is-night   { --glow: var(--night); }
.shift-item.is-leave   { --glow: var(--warn); }
.shift-item .shift-top   { display: flex; justify-content: space-between; align-items: center; }
.shift-item .shift-date  { font-weight: 650; font-size: .9rem; }
.shift-item .shift-times { font-size: .8rem; color: var(--text2); }
.shift-item .shift-earn  { font-weight: 700; font-size: .95rem; color: var(--accent); }
.shift-item .shift-badges { display: flex; gap: 4px; flex-wrap: wrap; }
.shift-item .shift-note  { font-size: max(11px, .72rem); color: var(--text3); font-style: italic; margin-top: 2px; }

/* ── Badges ─────────────────────────────────────────────────────────────── */
.badge { font-size: max(11px, .7rem); font-weight: 700; padding: 3px 9px; border-radius: var(--radius-pill); letter-spacing: -.002em; }
.badge.b-night   { background: var(--night-light); color: var(--night); }
.badge.b-sunday  { background: var(--sunday-light); color: var(--sunday); }
.badge.b-holiday { background: var(--holiday-light); color: var(--holiday); }
.badge.b-leave   { background: var(--warn-light); color: var(--warn); }

/* ── Shift Actions ──────────────────────────────────────────────────────── */
/* Leere Platzhalter einklappen: ohne Badges/Notiz blieb sonst Leerraum stehen
   und die Zeilen wurden unnötig hoch. */
.shift-badges:empty, .shift-note:empty { display: none; }

/* Zeilen-Aktionen: kompakte Icon-Knöpfe, rechts ausgerichtet und zurückhaltend.
   (Vorher drei Textknöpfe pro Eintrag → sehr unruhige Liste.) */
/* Bei vielen Einträgen überspringt der Browser Layout und Malen für alles, was
   außerhalb des Sichtfelds liegt. `contain-intrinsic-size` gibt ihm dafür eine
   Schätzung der Höhe, damit die Bildlaufleiste nicht springt. Kostenlos für
   kurze Listen, spürbar auf schwächeren Geräten bei langen. */
.shift-list .shift-item, .trip-card {
  content-visibility: auto;
  contain-intrinsic-size: auto 108px;
}
/* Kennzeichen und Aktionen teilen sich eine Zeile. Vorher lagen sie
   untereinander — das kostete pro Eintrag rund 34 px, bei acht Einträgen also
   fast eine ganze Bildschirmhöhe, ohne etwas zu zeigen. */
.shift-foot {
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px; margin-top: 6px; min-height: 34px;
}
.shift-foot .shift-badges { flex: 1 1 auto; min-width: 0; }
/* `margin-left: auto` statt `space-between`: hält die Aktionen auch dann rechts,
   wenn die Karte gar keine Kennzeichen trägt (sonst rutschten sie nach links). */
.shift-actions { display: flex; gap: 4px; align-items: center; flex: 0 0 auto; margin-left: auto; }
.shift-actions button {
  width: 34px; height: 34px; border-radius: 11px;
  display: inline-flex; align-items: center; justify-content: center;
  background: transparent; color: var(--text3);
  transition: background var(--trans), color var(--trans), transform var(--spring);
}
.shift-actions button .ic { width: 17px; height: 17px; stroke-width: 1.9; }
.shift-actions button:hover  { background: var(--surface2); color: var(--text); }
.shift-actions button:active { transform: scale(.9); }
.shift-actions button.del:hover { background: var(--danger-light); color: var(--danger); }
.sa-locked { font-size: max(11px, .7rem); color: var(--text3); display: inline-flex; align-items: center; gap: 5px; }

/* ── Empty State ────────────────────────────────────────────────────────── */
.empty-state { text-align: center; padding: 48px 20px 40px; color: var(--text2); }
/* Motiv im Akzentkreis — nimmt dem leeren Zustand die Kargheit und zeigt sofort,
   worum es in dieser Ansicht geht. */
.empty-state .es-art {
  width: 76px; height: 76px; margin: 0 auto 16px; border-radius: 26px;
  display: flex; align-items: center; justify-content: center;
  color: var(--accent);
  background: radial-gradient(120% 120% at 30% 20%,
    color-mix(in srgb, var(--accent) 20%, transparent) 0%,
    color-mix(in srgb, var(--accent) 8%, transparent) 60%, transparent 100%);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--accent) 18%, transparent);
}
.empty-state .es-art .ic { width: 34px; height: 34px; stroke-width: 1.7; }
.empty-state .es-title { font-size: 1rem; font-weight: 700; color: var(--text); margin-bottom: 5px; }
.empty-state .es-sub   { font-size: .82rem; color: var(--text2); line-height: 1.5; max-width: 30ch; margin: 0 auto; }
.empty-state .es-cta   { width: auto; display: inline-flex; align-items: center; gap: 7px; margin-top: 18px; padding: 12px 22px; }
.empty-state svg { fill: none; }
.empty-state p { font-size: .85rem; }

/* ── Modal (Mobile: Bottom-Sheet) ───────────────────────────────────────── */
/* ── Blätter und Dialoge als Material ──────────────────────────────────────
   Wichtig ist die Arbeitsteilung: der Überzug DIMMT nur, das Blatt selbst ist
   das Glas. Vorher zeichnete der Überzug weich UND das Blatt lag deckend
   darauf — der Weichzeichner war also gar nicht zu sehen, und hätte man dem
   Blatt zusätzlich einen gegeben, läge Glas auf Glas (das ergibt Milch, kein
   Material). Jetzt greift der Weichzeichner des Blattes direkt auf die Seite
   darunter durch: man sieht die App verschwommen durchscheinen. */
.modal-overlay {
  position: fixed; inset: 0; z-index: 300;
  background: rgba(8,12,9,.42); display: none;
  align-items: flex-end; justify-content: center;
  animation: fadeIn .2s ease;
}
.modal-overlay.open { display: flex; }
.modal-sheet {
  position: relative;
  background: var(--glass-sheet); border-radius: var(--radius-lg) var(--radius-lg) 0 0;
  backdrop-filter: var(--glass-blur-modal); -webkit-backdrop-filter: var(--glass-blur-modal);
  width: 100%; max-width: 520px; max-height: 90dvh;
  padding: 8px 20px calc(22px + var(--safe-bottom));
  overflow-y: auto; animation: slideUp .32s cubic-bezier(.22,1,.36,1);
  box-shadow: var(--shadow-lg);
}
/* Lichtkante nur an der Oberkante und den oberen Ecken — dort trifft das Licht
   auf ein Blatt, das von unten hereinfährt. `sticky` statt `absolute`, damit
   sie beim Scrollen im Blatt an der Kante bleibt. */
.modal-sheet::before {
  content: ''; position: sticky; top: 0; z-index: 5; display: block;
  height: 1px; margin: 0 -20px -1px; pointer-events: none;
  background: linear-gradient(90deg,
    transparent 0%, var(--glass-edge) 18%, var(--glass-edge) 82%, transparent 100%);
}
.modal-handle { width: 44px; height: 4px; border-radius: var(--radius-pill); background: var(--border-strong); margin: 7px auto 18px; opacity: .8; }
.modal-title { font-family: var(--font-display); font-size: 1.25rem; margin-bottom: 16px; }

/* ── Form Groups ────────────────────────────────────────────────────────── */
.form-group { margin-bottom: 14px; }
/* Feldbeschriftungen in Satzfall statt Versalien. Versalien nehmen der Schrift
   die Ober- und Unterlängen, an denen man Wortbilder erkennt — bei deutschen
   Komposita („STUNDENLOHN (€ BRUTTO)“, „NETTO-ZIEL/MONAT“) kostet das spürbar
   Lesezeit. Als kurze Rubrik über einer Kachel bleiben Versalien in Ordnung,
   als Beschriftung eines Eingabefelds nicht.
   Dafür etwas größer (.7 → .78 rem) und im Ton näher am Text — die Beschriftung
   soll gelesen werden, nicht nur da sein. */
.form-group label {
  display: block; font-size: .78rem; font-weight: 650;
  color: var(--text2); letter-spacing: -.002em; margin-bottom: 6px;
}
.form-group input,
.form-group select,
.form-group textarea {
  width: 100%; padding: 13px 15px; border-radius: var(--radius-sm);
  border: 1.5px solid var(--border); background: var(--surface2);
  font-size: .9rem; font-weight: 500;
  transition: border-color .2s, box-shadow .2s, background .2s;
  -webkit-appearance: none; min-height: 46px;
}
.form-group input:hover, .form-group select:hover, .form-group textarea:hover { border-color: var(--border-strong); }
.form-group textarea { resize: vertical; min-height: 60px; }
.form-group input:focus,
.form-group select:focus,
.form-group textarea:focus {
  outline: none;
  border-color: var(--accent);
  background: var(--surface);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--accent) 15%, transparent), var(--shadow-sm);
}
.form-row   { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.form-row-3 { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 10px; }

/* ── Buttons ────────────────────────────────────────────────────────────── */
button { cursor: pointer; }
.btn-primary {
  width: 100%; padding: 15px; border-radius: var(--radius-sm);
  background: var(--grad-accent); color: #fff; font-weight: 700; font-size: .9rem;
  letter-spacing: .004em; transition: transform var(--trans), box-shadow var(--trans), filter var(--trans);
  margin-top: 8px; position: relative; overflow: hidden;
  box-shadow: var(--shadow-accent), inset 0 1px 0 rgba(255,255,255,.16);
}
/* Feiner Lichtverlauf oben — gibt der Fläche Materialität */
.btn-primary::after { content: ''; position: absolute; inset: 0; background: var(--grad-sheen); pointer-events: none; }
.btn-primary:hover  { filter: brightness(1.06); box-shadow: var(--shadow-accent), inset 0 1px 0 rgba(255,255,255,.22); transform: translateY(-1px); }
.btn-primary:active { transform: translateY(0) scale(.985); filter: brightness(.97); }
.btn-secondary {
  width: 100%; padding: 13px; border-radius: var(--radius-sm);
  background: var(--surface2); font-weight: 600; font-size: .85rem;
  transition: background var(--trans), transform var(--trans), box-shadow var(--trans);
  margin-top: 6px; color: var(--text);
  box-shadow: var(--card-ring);
}
.btn-secondary:hover  { background: var(--surface3); box-shadow: var(--card-ring), var(--shadow-sm); }
.btn-secondary:active { transform: scale(.985); }
.btn-danger { background: var(--danger-light); color: var(--danger); }

/* ── Chips / Toggles ────────────────────────────────────────────────────── */
.template-chips { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 14px; }
.spesen-toggles { display: flex; gap: 8px; flex-wrap: wrap; }
.chip {
  padding: 9px 16px; border-radius: var(--radius-pill); background: var(--surface2);
  font-size: .78rem; font-weight: 600; transition: all var(--trans); border: 1.5px solid transparent;
  cursor: pointer; min-height: 38px;
}
.chip:hover  { background: var(--surface3); }
.chip:active { transform: scale(.96); }
.chip.active {
  border-color: color-mix(in srgb, var(--accent) 55%, transparent);
  background: var(--accent-bg); color: var(--accent); font-weight: 700;
  box-shadow: 0 2px 8px color-mix(in srgb, var(--accent) 14%, transparent);
}

/* ── Error Messages ─────────────────────────────────────────────────────── */
.error-msg { color: var(--danger); font-size: .78rem; margin-top: 4px; display: none; font-weight: 500; }
.error-msg.show { display: block; }

/* ── Settings Rows ──────────────────────────────────────────────────────── */
.setting-row { display: flex; justify-content: space-between; align-items: center; padding: 14px 0; border-bottom: 1px solid var(--border); }
.setting-row:last-child { border: none; }
.setting-label { font-size: .85rem; font-weight: 550; }

/* Aufeinanderfolgende Schalterzeilen bilden EINEN Block mit Haarlinien
   dazwischen — das ist das Ordnungsmittel, an dem man native Einstellungen
   erkennt, und es stellt die Zeilen zugleich auf eine deckende Fläche
   (freistehend auf dem Glas war ihr Beschreibungstext messbar zu schwach).
   `:has()` erkennt dabei echte Blöcke: eine Zeile, auf die keine weitere folgt,
   ist die letzte — auch wenn dazwischen andere Elemente stehen. */
.modal-sheet .setting-row {
  background: var(--surface); padding: 14px 15px;
  border-bottom: 1px solid var(--border);
}
.modal-sheet .setting-row:not(.setting-row + .setting-row) {
  border-radius: 18px 18px 0 0; margin-top: 10px;
  box-shadow: var(--card-ring);
}
.modal-sheet .setting-row:not(:has(+ .setting-row)) {
  border-radius: 0 0 18px 18px; border-bottom: none; margin-bottom: 10px;
}
/* Einzelne Zeile ohne Nachbarn: rundum gerundet */
.modal-sheet .setting-row:not(.setting-row + .setting-row):not(:has(+ .setting-row)) {
  border-radius: 18px;
}
.modal-sheet .feat-sub { color: var(--text2); }

/* ── Toggle ─────────────────────────────────────────────────────────────── */
.toggle {
  width: 50px; height: 30px; border-radius: 15px;
  background: var(--surface3); position: relative; transition: background .25s; cursor: pointer;
  flex-shrink: 0;
}
.toggle.on { background: var(--accent); }
.toggle::after {
  content: ''; position: absolute; top: 3px; left: 3px;
  width: 24px; height: 24px; border-radius: 50%;
  background: #fff; box-shadow: 0 1px 4px rgba(0,0,0,.25); transition: transform .25s cubic-bezier(.22,1,.36,1);
}
.toggle.on::after { transform: translateX(20px); }

/* ── FAB ────────────────────────────────────────────────────────────────── */
/* ── Hauptbefehl (schwebender Knopf) ────────────────────────────────────────
   Baugleich mit der Hero-Karte, nur klein: Mesh statt linearem Verlauf,
   gerichtete Lichtkante über die Doppelmaske, Glanz von oben links. Ein Knopf,
   der auf jeder Seite mitschwebt, ist das am häufigsten gesehene Element der
   App — er sollte aus demselben Material sein wie ihr Aushängeschild. */
.fab {
  position: fixed; bottom: calc(var(--nav-total) + 16px); right: 16px;
  z-index: 150; width: 58px; height: 58px; border-radius: 21px;
  background:
    radial-gradient(120% 110% at 22% 4%,
      color-mix(in oklab, var(--accent-bright, var(--accent)) 78%, white) 0%, transparent 62%),
    radial-gradient(120% 120% at 88% 96%,
      color-mix(in oklab, var(--accent) 82%, black) 0%, transparent 68%),
    var(--grad-accent);
  color: #fff;
  display: flex; align-items: center; justify-content: center;
  isolation: isolate;
  box-shadow: var(--shadow-accent);
  transition: transform var(--spring), box-shadow var(--trans), filter var(--trans);
}
/* Glanz von oben links — wie beim Hero ein Streifen, keine Kugelspiegelung */
.fab::before {
  content: ''; position: absolute; inset: 0; border-radius: inherit;
  pointer-events: none; z-index: 0;
  background: linear-gradient(140deg,
    rgba(255,255,255,.34) 0%, rgba(255,255,255,.10) 30%, rgba(255,255,255,0) 58%);
}
/* Gerichtete Lichtkante: oben hell, unten fast weg. Nur der Rahmen wird gemalt. */
.fab::after {
  content: ''; position: absolute; inset: 0; border-radius: inherit;
  pointer-events: none; z-index: 2; padding: 1px;
  background: linear-gradient(150deg,
    rgba(255,255,255,.80) 0%, rgba(255,255,255,.22) 38%,
    rgba(255,255,255,.05) 62%, rgba(255,255,255,.30) 100%);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
          mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
          mask-composite: exclude;
}
.fab svg { position: relative; z-index: 1; }
/* Der schwebende Hauptbefehl erscheint nur, wo er sinnvoll ist: Lohnzettel und
   Statistik sind reine Auswertungen — dort verdeckte er zuvor sogar Beträge. */
body[data-view="viewPayslip"] .fab,
body[data-view="viewStats"] .fab { display: none; }
/* Wo er erscheint, muss unter dem letzten Inhalt Platz für ihn bleiben. Sonst
   liegt er über der untersten Kachel — bei einer Verdienst-App verdeckt er
   dann ausgerechnet einen Betrag. Gemessen: der Knopf ist 58 px hoch und sitzt
   16 px über der Navigation. */
body[data-view="viewDashboard"] main,
body[data-view="viewTable"] main,
body[data-view="viewCalendar"] main,
body[data-view="viewTrips"] main { padding-bottom: 74px; }

/* Weicht beim Scrollen nach unten aus (siehe app.js) */
body.fab-tucked .fab { transform: translateY(96px) scale(.9); opacity: 0; pointer-events: none; }
.fab:hover  { transform: translateY(-2px) scale(1.04); filter: brightness(1.06); }
.fab:active { transform: scale(.92); }
.fab svg { width: 24px; height: 24px; stroke: currentColor; fill: none; stroke-width: 2.4; stroke-linecap: round; }

/* ── Install Banner ─────────────────────────────────────────────────────── */
.install-banner {
  display: none; position: fixed;
  bottom: calc(var(--nav-total) + 8px);
  left: 12px; right: 12px; z-index: 250;
  /* Einheitlich zur Navigation/Batch-Leiste: schwebendes Chrome = Glas-Kapsel */
  background: var(--grad-accent); color: #fff; border-radius: 22px;
  border: 1px solid rgba(255,255,255,.16);
  padding: 14px 16px; align-items: center; gap: 12px;
  box-shadow: var(--shadow-lg), inset 0 1px 0 rgba(255,255,255,.2); animation: fadeUp .4s ease;
}
.install-banner .ib-text    { flex: 1; }
.install-banner .ib-title   { font-weight: 650; font-size: .9rem; }
.install-banner .ib-sub     { font-size: max(11px, .72rem); opacity: .8; margin-top: 2px; }
.install-banner button      { padding: 8px 16px; border-radius: 9px; font-weight: 650; font-size: .78rem; flex-shrink: 0; }
.install-banner .ib-install { background: #fff; color: var(--accent); }
.install-banner .ib-dismiss { color: rgba(255,255,255,.7); }

/* ── Auth Screen ────────────────────────────────────────────────────────── */
.auth-screen {
  min-height: 100dvh; display: flex; flex-direction: column;
  align-items: center; justify-content: center; padding: 20px;
  animation: fadeIn .4s ease;
}
.auth-shell {
  width: 100%; max-width: 420px;
  background: var(--surface); border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg), var(--card-ring);
  overflow: hidden; animation: popIn .45s cubic-bezier(.22,1,.36,1);
  display: flex; flex-direction: column;
}
/* Fläche und Lichtebenen kommen aus der gemeinsamen Material-Definition
   in components.css — hier nur noch Maße. */
/* ── Kopfkarten-Material (geteilt, EINE Quelle) ─────────────────────────────
   Liegt bewusst in shared.css: die Anmelde-/Registrier-/Reset-Seiten laden nur
   diese Datei. Als der Block in components.css lag, verloren alle Auth-Seiten
   ihre Markenfläche — weiße Karte, farbloses €-Zeichen. Gefunden über das
   Audit-Bildmaterial, nicht über die App selbst: man meldet sich selten ab. */
.dash-hero,
.trip-summary,
.payout-total,
.hero-card,
.auth-brand,
.look-preview {
  background:
    /* Die helle Kuppe lag bei L .62 — weisser Text darauf ergab nur 4,02:1.
       L .55 behaelt die Tiefe des Mesh und traegt Weiss sicher. */
    /* Palettenrelativ statt festem Grün: Farbton aus var(--accent), Helligkeit
       fest (gemessen AA-sicher), Chroma gedeckelt auf die bewährten Grün-Werte.
       Vorher lagen hier vier FESTE Grüntöne — in der Ozean- oder Sonnenuntergangs-
       Palette schwebte also ein grünlicher Mesh über dem andersfarbigen Verlauf.
       min(c×…, Deckel) lässt Graphit fast unbunt (c≈0) und hält bunte Paletten
       auf dem abgestimmten Niveau. */
    /* Kuppe L .52, nicht .55: der Volllauf maß weißen Text auf der .55-Kuppe bei
       4,33–4,46:1 — haarscharf unter AA. .53 gab gemessen erst 4,54 im
       schlechtesten Zustand (320px/groß); .52 hebt auf ≥4,7 mit echter Reserve. */
    radial-gradient(120% 90% at 12% -10%,  oklch(from var(--accent) .52 min(calc(c * 1.4), .13) h / .95) 0%, transparent 58%),
    radial-gradient(90% 80% at 100% 8%,    oklch(from var(--accent) .52 min(calc(c * 1.2), .11) calc(h + 25) / .80) 0%, transparent 62%),
    radial-gradient(110% 120% at 78% 108%, oklch(from var(--accent) .34 min(c, .09) calc(h - 7) / .92) 0%, transparent 66%),
    radial-gradient(140% 110% at -10% 96%, oklch(from var(--accent) .28 min(calc(c * 0.8), .07) calc(h + 7) / .88) 0%, transparent 70%),
    var(--grad-hero);
  color: #fff;
  position: relative; overflow: hidden; isolation: isolate;
}
/* Glanzband: ein breiter, sehr flacher Lichtstreifen von oben links. Er ersetzt
   die früheren Kreise — ein Streifen liest sich als Lichteinfall, ein Kreis als
   gezeichnete Form. */
.dash-hero::before,
.trip-summary::before,
.payout-total::before,
.hero-card::before,
.auth-brand::before,
.look-preview::before {
  content: ''; position: absolute; inset: 0; pointer-events: none; z-index: 0;
  width: auto; height: auto; top: 0; right: 0; border-radius: 0;
  background: linear-gradient(128deg,
    rgba(255,255,255,.20) 0%,
    rgba(255,255,255,.07) 22%,
    rgba(255,255,255,0)   48%);
}
/* Umlaufende Lichtkante mit Richtung: oben links hell, unten rechts fast weg.
   Die Doppelmaske stanzt die Fläche heraus, sodass wirklich nur der ein Pixel
   breite Rahmen gemalt wird — das ist der Unterschied zwischen „Karte mit
   Rand“ und „Kante, auf die Licht fällt“. */
.dash-hero::after,
.trip-summary::after,
.payout-total::after,
.hero-card::after,
.auth-brand::after,
.look-preview::after {
  content: ''; position: absolute; inset: 0; z-index: 2; pointer-events: none;
  width: auto; height: auto; bottom: auto; left: 0;
  border-radius: inherit; padding: 1px;
  background: linear-gradient(135deg,
    rgba(255,255,255,.72) 0%,
    rgba(255,255,255,.16) 34%,
    rgba(255,255,255,.04) 58%,
    rgba(255,255,255,.30) 100%);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
          mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
          mask-composite: exclude;
}
.auth-brand { padding: 30px 28px 26px; }
.auth-brand .ab-logo {
  width: 44px; height: 44px; border-radius: 14px;
  background: rgba(255,255,255,.14); backdrop-filter: blur(4px);
  display: flex; align-items: center; justify-content: center;
  font-family: var(--font-display); font-size: 1.5rem;
  margin-bottom: 14px; position: relative; z-index: 1;
}
.auth-brand h1 { font-family: var(--font-display); font-size: 1.7rem; font-weight: 400; letter-spacing: -.01em; position: relative; z-index: 1; }
.auth-brand p  { font-size: .82rem; opacity: .75; margin-top: 5px; position: relative; z-index: 1; }
.auth-features { list-style: none; margin-top: 18px; display: flex; flex-direction: column; gap: 8px; position: relative; z-index: 1; }
.auth-features li { font-size: .78rem; opacity: .85; display: flex; align-items: center; gap: 9px; }
.auth-features li::before {
  content: ''; width: 5px; height: 5px; border-radius: 50%;
  background: rgba(255,255,255,.85); flex-shrink: 0;
}
.auth-form-side { padding: 26px 28px 24px; }

/* Legacy-Auth-Karte (Fallback) */
.auth-card {
  background: var(--surface); border-radius: var(--radius-lg);
  padding: 32px 24px; box-shadow: var(--shadow-lg), var(--card-ring);
  width: 100%; max-width: 380px; animation: popIn .5s cubic-bezier(.22,1,.36,1);
}
.auth-card .auth-logo { font-family: var(--font-display); font-size: 2rem; text-align: center; margin-bottom: 4px; color: var(--accent); }
.auth-card .auth-sub  { text-align: center; font-size: .8rem; color: var(--text2); margin-bottom: 24px; }

.auth-tabs { display: flex; margin-bottom: 20px; border-radius: var(--radius-xs); overflow: hidden; background: var(--surface2); padding: 4px; gap: 4px; }
.auth-tabs button { flex: 1; padding: 9px; font-weight: 650; font-size: .82rem; background: transparent; border-radius: 8px; transition: all .2s; color: var(--text2); }
.auth-tabs button.active { background: var(--surface); color: var(--text); box-shadow: var(--shadow-sm); }
.auth-footer { text-align: center; font-size: max(11px, .68rem); color: var(--text3); margin-top: 18px; line-height: 1.5; }
.auth-forgot { text-align: center; margin-top: 14px; }
.auth-forgot a { font-size: .78rem; color: var(--text2); text-decoration: none; }
.auth-forgot a:hover { color: var(--accent); }
.auth-or { display: flex; align-items: center; gap: 12px; margin: 16px 0 12px; color: var(--text3); font-size: max(11px, .72rem); }
.auth-or::before, .auth-or::after { content: ''; flex: 1; height: 1px; background: var(--border); }
.auth-demo-btn { display: block; text-align: center; text-decoration: none; }
.auth-demo-hint { text-align: center; font-size: max(11px, .68rem); color: var(--text3); margin-top: 8px; line-height: 1.4; }

/* Demo-Modus-Banner (oben in der App) */
/* Schwebende Status-Pille statt randloser Leiste (Anmutung der „Now Bar“) */
.demo-banner {
  display: flex; align-items: center; justify-content: center; gap: 9px; flex-wrap: wrap;
  margin: calc(8px + var(--safe-top)) 12px 0; padding: 9px 16px;
  font-size: .76rem; font-weight: 600; text-align: center;
  border-radius: var(--radius-pill);
  background: color-mix(in srgb, var(--accent) 13%, var(--glass-strong));
  border: 1px solid color-mix(in srgb, var(--accent) 26%, transparent);
  backdrop-filter: var(--glass-blur); -webkit-backdrop-filter: var(--glass-blur);
  box-shadow: var(--shadow-sm), inset 0 1px 0 var(--glass-edge);
  color: var(--text);
}
.demo-banner a { color: var(--accent); text-decoration: none; font-weight: 700; white-space: nowrap; }
.demo-banner a:hover { text-decoration: underline; }

/* Offline-/Sync-Banner (dynamisch von offline.js eingefügt, oberste Body-Zeile) */
.vp-offline-banner {
  display: flex; align-items: center; justify-content: center; gap: 10px; flex-wrap: wrap;
  padding: 7px 14px; font-size: .78rem; font-weight: 600;
  background: color-mix(in srgb, var(--accent) 16%, var(--surface));
  color: var(--text); border-bottom: 1px solid color-mix(in srgb, var(--accent) 30%, transparent);
}
.vp-offline-banner.vp-ob-offline {
  background: color-mix(in srgb, var(--text2) 16%, var(--surface));
  border-bottom-color: color-mix(in srgb, var(--text2) 28%, transparent);
}
.vp-offline-banner.vp-ob-warn {
  background: color-mix(in srgb, var(--warn) 16%, var(--surface));
  border-bottom-color: color-mix(in srgb, var(--warn) 35%, transparent);
}
.vp-offline-banner a { color: var(--accent); text-decoration: none; font-weight: 700; white-space: nowrap; }
.vp-offline-banner a:hover { text-decoration: underline; }
.vp-offline-banner button {
  background: transparent; border: 1px solid color-mix(in srgb, var(--text) 26%, transparent);
  color: var(--text); border-radius: 8px; padding: 3px 10px; font-size: .74rem; font-weight: 700; cursor: pointer;
}
.vp-offline-banner button:hover { background: color-mix(in srgb, var(--text) 9%, transparent); }
.success-msg { padding: 10px 13px; border-radius: 11px; font-size: .82rem; font-weight: 600;
  background: color-mix(in srgb, var(--accent) 14%, transparent); color: var(--accent); }

/* Rettungs-Codes (Recovery Codes) */
.rc-warn { font-size: .8rem; line-height: 1.5; color: var(--text); margin-bottom: 16px;
  padding: 11px 13px; border-radius: 11px;
  background: color-mix(in srgb, var(--warn) 14%, transparent);
  border: 1px solid color-mix(in srgb, var(--warn) 35%, transparent); }
.rc-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-bottom: 16px; }
.rc-code { font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  font-size: .95rem; font-weight: 600; letter-spacing: .06em; text-align: center;
  padding: 11px 6px; border-radius: 10px; background: var(--surface2);
  border: 1.5px solid var(--border); color: var(--text); user-select: all; }
.rc-actions { display: flex; gap: 10px; margin-bottom: 18px; }
.rc-actions button { flex: 1; margin: 0; }
.rc-confirm { display: flex; align-items: center; gap: 9px; font-size: .82rem;
  color: var(--text2); margin-bottom: 14px; cursor: pointer; }
.rc-confirm input { width: 18px; height: 18px; accent-color: var(--accent); flex-shrink: 0; }

/* Login: Zwei-Faktor-Schritt */
.auth-step-title { font-size: 1.25rem; font-weight: 700; margin: 0 0 4px; color: var(--text); }
.auth-step-sub { font-size: .85rem; color: var(--text2); margin: 0 0 18px; line-height: 1.45; }

/* Einstellungen: 2FA-Einrichtung */
.twofa-setup { margin-top: 12px; padding: 14px; border-radius: 12px;
  background: var(--surface2); border: 1px solid var(--border); }
.twofa-secret { display: inline-block; cursor: pointer; margin: 8px 0; }
.twofa-input { width: 100%; text-align: center; letter-spacing: .3em; font-size: 1.2rem;
  font-weight: 600; padding: 10px; border-radius: 10px; border: 1.5px solid var(--border);
  background: var(--surface); color: var(--text); margin-top: 4px; }

/* ── Mini-Tour (Kurzeinführung für neue Nutzer) ───────────────────────────── */
.tour-overlay { position: fixed; inset: 0; z-index: 3000; }
.tour-spot { position: fixed; border-radius: 14px; pointer-events: none;
  box-shadow: 0 0 0 9999px rgba(0,0,0,.55), 0 0 0 2px var(--accent);
  transition: top .28s cubic-bezier(.4,0,.2,1), left .28s cubic-bezier(.4,0,.2,1),
              width .28s cubic-bezier(.4,0,.2,1), height .28s cubic-bezier(.4,0,.2,1); }
.tour-card { position: fixed; z-index: 3001; width: min(310px, calc(100vw - 24px));
  background: var(--surface); border: 1px solid var(--border); border-radius: 16px;
  padding: 16px 16px 14px; box-shadow: 0 16px 48px rgba(0,0,0,.28);
  transition: top .28s ease, left .28s ease; }
.tour-title { font-size: 1rem; font-weight: 700; color: var(--text); margin-bottom: 5px; }
.tour-text { font-size: .84rem; line-height: 1.5; color: var(--text2); margin-bottom: 14px; }
.tour-foot { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.tour-dots { display: flex; gap: 6px; }
.tour-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--border-strong); }
.tour-dot.on { background: var(--accent); }
.tour-btns { display: flex; gap: 8px; }
.tour-btns button { margin: 0; padding: 7px 14px; font-size: .82rem; width: auto; }
@media (prefers-reduced-motion: reduce) { .tour-spot, .tour-card { transition: none; } }

/* ── Onboarding-Wizard ──────────────────────────────────────────────────── */
.ob-progress { display: flex; gap: 7px; margin-bottom: 20px; }
.ob-dot { flex: 1; height: 5px; border-radius: 3px; background: var(--surface2); transition: background .3s; }
.ob-dot.active { background: var(--accent); }
.ob-step { display: none; animation: fadeIn .25s ease; }
.ob-step.active { display: block; }
.ob-h { font-family: var(--font-display); font-size: 1.35rem; margin-bottom: 4px; }
.ob-sub { font-size: .82rem; color: var(--text2); margin-bottom: 18px; line-height: 1.45; }
.ob-cards { display: flex; flex-direction: column; gap: 10px; }
.ob-card {
  display: flex; flex-direction: column; align-items: flex-start; gap: 2px; text-align: left;
  padding: 14px 16px; border-radius: var(--radius-sm); border: 1.5px solid var(--border);
  background: var(--surface2); transition: all var(--trans); position: relative;
}
.ob-card:active { transform: scale(.99); }
.ob-card.sel { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 8%, var(--surface2)); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 12%, transparent); }
.ob-card.sel::after { content: '✓'; position: absolute; top: 12px; right: 14px; color: var(--accent); font-weight: 800; }
.ob-ic { font-size: 1.4rem; }
.ob-ct { font-weight: 700; font-size: .92rem; }
.ob-cd { font-size: .74rem; color: var(--text2); line-height: 1.35; }
.ob-feats { display: flex; flex-direction: column; gap: 8px; }
.ob-feat {
  display: flex; align-items: center; justify-content: space-between; padding: 13px 15px;
  border-radius: var(--radius-sm); border: 1.5px solid var(--border); background: var(--surface2);
  font-weight: 600; font-size: .88rem; color: var(--text2); transition: all var(--trans);
}
.ob-feat.on { border-color: var(--accent); color: var(--text); background: color-mix(in srgb, var(--accent) 7%, var(--surface2)); }
.ob-feat .ob-check { opacity: 0; color: var(--accent); font-weight: 800; transition: opacity .2s; }
.ob-feat.on .ob-check { opacity: 1; }
.ob-nav { display: flex; gap: 10px; margin-top: 22px; }
.ob-nav .ob-btn { flex: 1; margin: 0; }
.ob-skip-form { margin-top: 12px; text-align: center; }
.ob-skip { font-size: .74rem; color: var(--text3); background: transparent; padding: 6px; }
.ob-skip:hover { color: var(--text2); }
input.shake { animation: obShake .35s; border-color: var(--danger) !important; }
@keyframes obShake { 0%,100%{transform:translateX(0)} 25%{transform:translateX(-5px)} 75%{transform:translateX(5px)} }
.account-list { display: flex; flex-direction: column; gap: 8px; margin-bottom: 16px; }
.account-item { display: flex; align-items: center; justify-content: space-between; padding: 12px 14px; background: var(--surface2); border-radius: var(--radius-xs); cursor: pointer; transition: all var(--trans); }
.account-item:active { transform: scale(.98); }
.account-item .ai-name { font-weight: 650; font-size: .9rem; }

/* ── Filter Bar ─────────────────────────────────────────────────────────── */
/* Filter umbrechen statt horizontal abschneiden: vorher endete die Reihe mitten
   im letzten Chip und die hinteren Filter waren praktisch unsichtbar. */
/* ── Filterzeile: scrollbar, aber ohne harte Schnittkante ──────────────────
   Chips einfach abzuschneiden sieht nach Fehler aus. Stattdessen läuft die
   Zeile an den Rändern weich aus — und zwar nur auf der Seite, auf der es
   tatsächlich weitergeht. Das erledigt eine scrollgesteuerte Animation ohne
   eine Zeile JavaScript: der Fortschritt der Animation IST die Scrollposition.
   `@property` ist nötig, damit die Maskenstopps als Längen interpolierbar
   sind — ohne Registrierung wären es reine Zeichenketten und würden springen. */
@property --fade-l { syntax: '<length>'; inherits: false; initial-value: 0px; }
@property --fade-r { syntax: '<length>'; inherits: false; initial-value: 0px; }

.filter-bar {
  display: flex; gap: 8px; margin: 0 calc(-1 * var(--view-pad, 16px)) 12px;
  padding-inline: var(--view-pad, 16px);
  flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none;
  overscroll-behavior-x: contain; scroll-snap-type: x proximity;
  scroll-padding-inline: var(--view-pad, 16px);
  /* Grundzustand = nichts ausblenden. Genau dieser Zustand gilt, wenn die
     Zeile ohne Überlauf hineinpasst: dann hat die Scroll-Zeitleiste keinen
     Bereich, ist inaktiv, und die Animation greift gar nicht. */
  --fade-l: 0px; --fade-r: 0px;
  -webkit-mask-image: linear-gradient(90deg,
    transparent 0, #000 var(--fade-l),
    #000 calc(100% - var(--fade-r)), transparent 100%);
          mask-image: linear-gradient(90deg,
    transparent 0, #000 var(--fade-l),
    #000 calc(100% - var(--fade-r)), transparent 100%);
}
.filter-bar .chip { flex: 0 0 auto; scroll-snap-align: start; }
@supports (animation-timeline: scroll(self inline)) {
  .filter-bar {
    animation: filter-fade linear both;
    animation-timeline: scroll(self inline);
  }
  /* Gibt es Überlauf, ist die Zeitleiste aktiv: ganz links nur rechts weich,
     in der Mitte beidseitig, ganz rechts nur links weich. Die Kante zeigt
     damit immer an, auf welcher Seite es weitergeht. */
  @keyframes filter-fade {
    0%   { --fade-l:  0px; --fade-r: 28px; }
    4%   { --fade-l: 28px; --fade-r: 28px; }
    96%  { --fade-l: 28px; --fade-r: 28px; }
    100% { --fade-l: 28px; --fade-r:  0px; }
  }
}
/* Suchzeile trägt rechts die Werkzeuge: Symbole = Aktionen, Chips = Filter.
   Vorher sahen beide gleich aus und „Rotation ausrollen“ stand neben „Nacht“. */
.list-row { display: flex; align-items: center; gap: 8px; margin-bottom: 12px; }
.list-row .list-search-wrap { flex: 1 1 auto; margin-bottom: 0; }
.list-tool {
  flex: 0 0 auto; width: 44px; height: 44px; border-radius: 13px;
  display: grid; place-items: center;
  background: var(--surface2); border: 1.5px solid var(--border);
  color: var(--text2); transition: background var(--trans), color var(--trans), transform var(--trans);
}
.list-tool:hover { background: var(--surface); color: var(--text); }
.list-tool:active { transform: scale(.94); }
.list-tool svg { width: 19px; height: 19px; }
.list-search-wrap { position: relative; margin-bottom: 12px; }
.list-search-ico { position: absolute; left: 12px; top: 50%; transform: translateY(-50%); font-size: .85rem; opacity: .6; pointer-events: none; }
.list-search {
  width: 100%; padding: 11px 13px 11px 36px; border-radius: 12px;
  border: 1.5px solid var(--border); background: var(--surface2);
  font-size: .88rem; font-family: var(--font); color: var(--text);
  min-height: 44px; -webkit-appearance: none;
}
.list-search:focus {
  outline: none; border-color: var(--accent); background: var(--surface);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 14%, transparent);
}

/* Gestylte Dialoge (confirm/prompt-Ersatz) — zentrierte Karte */
.dialog-overlay { align-items: center; padding: 20px; }
.dialog-box {
  position: relative; isolation: isolate;
  background: var(--glass-sheet); border-radius: 24px; width: 100%; max-width: 400px;
  backdrop-filter: var(--glass-blur-modal); -webkit-backdrop-filter: var(--glass-blur-modal);
  padding: 22px; box-shadow: var(--shadow-lg); animation: dlgPop .22s cubic-bezier(.22,1,.36,1);
}
/* Umlaufende Lichtkante wie beim Hero — der Dialog schwebt frei, also bekommt
   er sie ringsum statt nur oben. */
.dialog-box::before {
  content: ''; position: absolute; inset: 0; border-radius: inherit;
  pointer-events: none; z-index: 2; padding: 1px;
  background: linear-gradient(140deg,
    var(--glass-edge) 0%, color-mix(in srgb, var(--glass-edge) 30%, transparent) 40%,
    transparent 62%, color-mix(in srgb, var(--glass-edge) 55%, transparent) 100%);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
          mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
          mask-composite: exclude;
}
@keyframes dlgPop { from { opacity: 0; transform: scale(.94) translateY(8px); } to { opacity: 1; transform: none; } }
.dialog-title { font-size: 1.1rem; font-weight: 700; margin-bottom: 8px; }
.dialog-msg { font-size: .9rem; color: var(--text2); line-height: 1.5; margin-bottom: 16px; white-space: pre-line; }
.dialog-input {
  width: 100%; padding: 11px 13px; border-radius: 11px; border: 1.5px solid var(--border);
  background: var(--surface); font-size: .95rem; font-family: var(--font); color: var(--text);
  margin-bottom: 16px; -webkit-appearance: none;
}
.dialog-input:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 14%, transparent); }
.dialog-actions { display: flex; gap: 10px; }
.dialog-actions button { flex: 1; margin: 0; }
.dialog-actions .btn-primary.btn-danger { background: var(--danger); border-color: var(--danger); color: #fff; }
.filter-bar::-webkit-scrollbar { display: none; }

/* ── Bar Chart ──────────────────────────────────────────────────────────── */
.bar-chart { display: flex; flex-direction: column; gap: 8px; }
/* Flache Zeile für Monate ohne jede Daten: Beschriftung und Strich, keine
   leere Balkenbahn — die Liste atmet, statt Leere zu inszenieren. */
.bar-row.bar-leer { justify-content: space-between; min-height: 20px; opacity: .75; }
.bar-row   { display: flex; align-items: center; gap: 10px; }
.bar-clickable { cursor: pointer; border-radius: 10px; padding: 2px 2px; margin: -2px -2px; transition: background var(--trans); }
.bar-clickable:active { background: var(--surface2); }
.bar-label { font-size: .78rem; color: var(--text2); min-width: 54px; text-align: right; }
.bar-track { position: relative; flex: 1; height: 20px; background: var(--surface2); border-radius: 10px; overflow: hidden; }
.bar-ghost { position: absolute; top: 0; left: 0; height: 100%; background: var(--text3); opacity: .22; border-radius: 10px; }
.bar-fill  { position: relative; z-index: 1; height: 100%; border-radius: 10px; transition: width .6s cubic-bezier(.22,1,.36,1); }
.bar-val   { font-size: max(11px, .72rem); font-weight: 650; min-width: 65px; font-variant-numeric: tabular-nums; }
.bar-val small { font-size: .74rem; color: var(--text2); font-weight: 500; margin-left: 2px; }
.yoy { font-size: max(11px, .6rem); font-weight: 700; margin-left: 4px; }
.yoy.up { color: var(--accent); }
.yoy.down { color: var(--danger); }
/* `display` schlägt das hidden-Attribut (UA-Regel hat niedrigere Spezifität) — ohne die
   folgende Zeile stehen ALLE Monats-Details dauerhaft offen. */
.bar-detail[hidden] { display: none !important; }
.bar-detail {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(72px, 1fr)); gap: 6px 12px;
  padding: 8px 10px; margin: 2px 0 2px 60px; background: var(--surface2);
  border-radius: 10px; font-size: max(11px, .72rem);
}
.bar-detail > div { display: flex; flex-direction: column; }
.bar-detail span { color: var(--text2); font-size: .74rem; }
.bar-detail b { font-variant-numeric: tabular-nums; }
.comp-bar { display: flex; height: 24px; border-radius: 8px; overflow: hidden; margin-bottom: 12px; }
.comp-seg { height: 100%; transition: width .5s ease; }
.comp-legend { display: flex; flex-wrap: wrap; gap: 7px 15px; font-size: .78rem; }
.comp-leg { display: inline-flex; align-items: center; gap: 5px; color: var(--text2); }
.comp-dot { width: 9px; height: 9px; border-radius: 3px; flex-shrink: 0; }
.comp-leg small { color: var(--text2); font-size: .74rem; }
.stats-bar-legend { display: flex; gap: 10px; flex-wrap: wrap; font-size: .78rem; font-weight: 600; color: var(--text2); letter-spacing: -.004em; margin-bottom: 10px; }

/* ── Payslip ────────────────────────────────────────────────────────────── */
.payslip { background: var(--surface); border-radius: var(--radius); padding: 22px; box-shadow: var(--shadow-sm), var(--card-ring); margin-bottom: 12px; }
.payslip-header { text-align: center; margin-bottom: 16px; border-bottom: 2px solid var(--border); padding-bottom: 12px; }
.payslip-header h2 { font-family: var(--font-display); font-size: 1.1rem; }
.payslip-header p  { font-size: .75rem; color: var(--text2); }
.payslip-section   { margin-bottom: 12px; }
.payslip-section h4 { font-size: .84rem; font-weight: 700; letter-spacing: -.01em; color: var(--text2); margin-bottom: 9px; }
.payslip-row { display: flex; justify-content: space-between; padding: 4px 0; font-size: .82rem; }
.payslip-row.bold { font-weight: 700; border-top: 1.5px solid var(--border-strong); padding-top: 8px; margin-top: 4px; }
.payslip-row .neg { color: var(--danger); }

/* ── Disclaimer ─────────────────────────────────────────────────────────── */
.disclaimer {
  background: var(--surface2); border-radius: var(--radius-sm);
  padding: 12px 14px; font-size: max(11px, .72rem); color: var(--text2); line-height: 1.5; margin-top: 12px;
}

/* ── Section Title ──────────────────────────────────────────────────────── */
.section-title {
  font-size: 1rem; font-weight: 750; letter-spacing: -.017em;
  color: var(--text); margin: 26px 0 12px; padding-left: 2px;
  display: flex; align-items: center; gap: 12px;
}
.section-title::after { content: ''; flex: 1; height: 1px; background: var(--border); }

/* ── Toast Notifications ────────────────────────────────────────────────── */
@keyframes toastIn  { from { opacity:0; transform:translateY(16px) scale(.95); } to { opacity:1; transform:none; } }
@keyframes toastOut { from { opacity:1; } to { opacity:0; transform:translateY(-8px); } }

#toastContainer {
  position: fixed; bottom: calc(var(--nav-total) + 80px);
  left: 50%; transform: translateX(-50%); z-index: 9999;
  display: flex; flex-direction: column; align-items: center; gap: 8px;
  pointer-events: none; width: min(90vw, 360px);
}
.toast {
  width: 100%; padding: 13px 17px; border-radius: 20px;
  font-size: .82rem; font-weight: 600; color: #fff;
  box-shadow: var(--shadow-lg), inset 0 1px 0 rgba(255,255,255,.14);
  animation: toastIn var(--spring);
  pointer-events: auto;
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
}
.toast-action {
  flex-shrink: 0; background: rgba(255,255,255,.22); color: #fff;
  padding: 6px 13px; border-radius: 9px; font-weight: 700; font-size: .78rem;
  transition: background .15s, transform .1s;
}
.toast-action:active { transform: scale(.94); background: rgba(255,255,255,.35); }
.toast.warn .toast-action { color: #221a02; background: rgba(0,0,0,.12); }
.toast.success { background: #2d6a4f; }
.toast.error   { background: #c73e43; }
.toast.info    { background: #46689b; }
.toast.warn    { background: #d99a10; color: #221a02; }
.toast.out     { animation: toastOut .25s ease forwards; }

/* ── Shift Preview ──────────────────────────────────────────────────────── */
/* ── Mitlaufende Fußleiste im Eingabe-Sheet ────────────────────────────────
   Das Ergebnis der Eingabe muss sichtbar bleiben, während man eingibt —
   sonst tippt man blind und prüft erst nach dem Speichern. Deshalb kleben
   Vorschau und Hauptknopf am unteren Rand des scrollenden Sheets; der Rest
   des Formulars läuft darunter durch.
   Die negativen Ränder heben das Sheet-Padding auf, damit die Leiste bis an
   die Kanten reicht (das Sheet hat 20 px seitlich, unten 22 px + Safe-Area). */
.sheet-foot {
  position: sticky; bottom: calc(-22px - var(--safe-bottom)); z-index: 3;
  margin: 14px -20px calc(-22px - var(--safe-bottom));
  padding: 12px 20px calc(16px + var(--safe-bottom));
  background: var(--glass-strong);
  backdrop-filter: var(--glass-blur); -webkit-backdrop-filter: var(--glass-blur);
  border-top: 1px solid var(--glass-border);
}
.sheet-foot .btn-secondary { margin-bottom: 0; }

.shift-preview {
  background: var(--accent-bg); border: 1.5px solid var(--accent-light);
  border-radius: var(--radius-xs); padding: 12px 14px; margin: 0 0 10px;
  font-size: .82rem; display: none;
}
.shift-preview.visible { display: block; animation: fadeIn .2s ease; }
.shift-preview .sp-row { display: flex; justify-content: space-between; padding: 3px 0; }
.shift-preview .sp-key { color: var(--text2); }
.shift-preview .sp-val { font-weight: 650; color: var(--accent); }
.shift-preview .sp-net { font-size: 1rem; font-weight: 700; color: var(--accent); padding-top: 6px; border-top: 1px solid var(--accent-light); margin-top: 4px; }

/* ── Heatmap ────────────────────────────────────────────────────────────── */
.heatmap { display: flex; flex-direction: column; gap: 6px; margin-top: 4px; }
.heatmap-row { display: flex; align-items: center; gap: 5px; }
.heatmap-year { font-size: .76rem; font-weight: 650; color: var(--text2); min-width: 36px; text-align: right; }
.hm-cell {
  flex: 1; aspect-ratio: 1; border-radius: 4px; cursor: pointer;
  background: var(--surface2); transition: transform .15s, opacity .15s;
  position: relative;
}
.hm-cell:active { transform: scale(.9); }
.hm-cell.hm-0  { background: var(--surface2); }
.hm-cell.hm-1  { background: var(--accent-bg); }
.hm-cell.hm-2  { background: color-mix(in srgb, var(--accent) 30%, var(--surface)); }
.hm-cell.hm-3  { background: color-mix(in srgb, var(--accent) 55%, var(--surface)); opacity:.9; }
.hm-cell.hm-4  { background: var(--accent); opacity:.8; }
.hm-cell.hm-5  { background: var(--accent); opacity:1; }
.hm-cell.hm-future { opacity: .25; cursor: default; }
.hm-cell.hm-current { outline: 2px solid var(--accent); outline-offset: 1px; }
.hm-months { display: flex; gap: 5px; padding-left: 37px; margin-bottom: 2px; }
.hm-months span { flex: 1; font-size: max(11px, .7rem); font-weight: 600; color: var(--text2); text-align: center; }

/* ── Vacation Progress ──────────────────────────────────────────────────── */
.vacation-bar-wrap { margin-top: 8px; }
.vacation-bar-track { height: 6px; background: var(--surface2); border-radius: 3px; overflow: hidden; }
.vacation-bar-fill  { height: 100%; border-radius: 3px; background: var(--warn); transition: width .5s ease; }
.vacation-bar-fill.ok { background: var(--accent); }

/* ── Rolling Hour Table ─────────────────────────────────────────────────── */
.rolling-table { font-size: .78rem; width: 100%; border-collapse: collapse; }
.rolling-table td { padding: 5px 0; border-bottom: 1px solid var(--border); }
.rolling-table td:last-child { text-align: right; font-weight: 650; }
.rolling-table tr:last-child td { border: none; }
.rt-pos { color: var(--accent); }
.rt-neg { color: var(--danger); }

/* ════════════════════════════════════════════════════════════════════════
   BREITENBASIERTE RASTER (Platz, nicht Gerät)
   ════════════════════════════════════════════════════════════════════════ */
@media (min-width: 500px) {
  .stats-grid   { grid-template-columns: repeat(3, 1fr); }
}
@media (min-width: 900px) {
  main        { max-width: 1160px; margin: 0 auto; }
  /* Rasterpass (Audit): die Bento-Reihe war am Desktop ein gestreckter
     Mobilscreen — 7 Kacheln brachen als 5+2. Vier Spalten, „Heute" doppelt
     breit → 2+1+1+1+1+1+1 = 8 Einheiten = zwei saubere Reihen. */
  .dq-row { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .dq-row > .dq-card:last-child:nth-child(odd) { grid-column: auto; }
  .dash-wide-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); }
  .view       { --view-pad: 32px; }
  #viewCalendar { padding-left: 32px; padding-right: 32px; }   /* breite Schirme: normale Ränder */
  .stats-grid { grid-template-columns: repeat(4, 1fr); }
  .insight-row  { overflow-x: visible; flex-wrap: wrap; }
  .insight-card { flex: 1 1 200px; }
}

/* ════════════════════════════════════════════════════════════════════════
   DESKTOP-CHROME  — html[data-device="desktop"]
   Sidebar mit Beschriftung, zentrierte Dialoge, Hover-Zustände,
   Toasts oben rechts. Wird per Geräteerkennung geschaltet.
   ════════════════════════════════════════════════════════════════════════ */
html[data-device="desktop"] body {
  padding-left: var(--sidebar-w);
  padding-bottom: 40px;
}

html[data-device="desktop"] .app-header { padding: 14px 40px 12px; }

/* Bottom-Nav → Sidebar mit Labels */
html[data-device="desktop"] .bottom-nav {
  top: 0; bottom: 0; left: 0; right: auto;
  width: var(--sidebar-w); height: 100dvh;
  flex-direction: column;
  justify-content: flex-start;
  align-items: stretch;
  padding: 20px 12px 24px;
  border-right: 1px solid var(--border);
  border-top: none;
  gap: 3px;
  overflow-y: auto;
  background: var(--surface);
}
html[data-device="desktop"] .nav-brand {
  display: flex; align-items: center; gap: 11px;
  padding: 6px 10px 22px;
}
html[data-device="desktop"] .nav-brand .nb-mark {
  width: 38px; height: 38px; border-radius: 12px;
  background: var(--grad-accent); color: #fff;
  display: flex; align-items: center; justify-content: center;
  font-family: var(--font-display); font-size: 1.2rem;
  box-shadow: 0 4px 12px rgba(45,106,79,.3);
  flex-shrink: 0;
}
html[data-device="desktop"] .nav-brand .nb-name {
  font-family: var(--font-display); font-size: 1.05rem; line-height: 1.15;
}
html[data-device="desktop"] .nav-brand .nb-sub {
  font-size: max(11px, .68rem); color: var(--text2); margin-top: 1px;
}
html[data-device="desktop"] .nav-item {
  flex-direction: row; justify-content: flex-start; gap: 12px;
  max-width: none; flex: 0 0 auto;
  padding: 11px 14px; border-radius: 12px;
  font-size: .84rem; font-weight: 550; color: var(--text2);
}
html[data-device="desktop"] .nav-item.active::before {
  top: 50%; left: 0; transform: translateY(-50%);
  width: 3px; height: 20px; border-radius: 0 3px 3px 0;
}
html[data-device="desktop"] .nav-item svg { width: 20px; height: 20px; }
html[data-device="desktop"] .nav-item.active { background: var(--accent-bg); color: var(--accent); font-weight: 650; }
html[data-device="desktop"] .nav-item:hover:not(.active) { background: var(--surface2); color: var(--text); }
html[data-device="desktop"] .nav-item:active { transform: none; }

/* Buttons → Inhaltsbreite */
html[data-device="desktop"] .btn-primary   { width: auto; min-width: 180px; }
html[data-device="desktop"] .btn-secondary { width: auto; min-width: 140px; }
html[data-device="desktop"] .modal-sheet .btn-primary,
html[data-device="desktop"] .modal-sheet .btn-secondary { margin-right: 8px; }

/* Modal → zentrierter Dialog */
html[data-device="desktop"] .modal-overlay { align-items: center; padding: 24px; }
html[data-device="desktop"] .modal-sheet {
  border-radius: var(--radius-lg);
  margin: 0;
  max-width: 540px;
  max-height: 86dvh;
  padding: 26px 28px 26px;
  animation: popIn .28s cubic-bezier(.22,1,.36,1);
}
html[data-device="desktop"] .modal-handle { display: none; }

/* FAB */
html[data-device="desktop"] .fab { bottom: 36px; right: 36px; }
html[data-device="desktop"] .fab:hover { transform: scale(1.07); box-shadow: 0 10px 28px rgba(45,106,79,.48); }

/* Install-Banner sidebar-bewusst */
html[data-device="desktop"] .install-banner { left: calc(var(--sidebar-w) + 16px); bottom: 24px; right: 24px; max-width: 480px; }

/* Toast → oben rechts */
html[data-device="desktop"] #toastContainer {
  bottom: auto; top: 76px;
  right: 28px; left: auto;
  transform: none;
  align-items: flex-end;
}

/* Hover-Zustände (nur Desktop) */
html[data-device="desktop"] .icon-btn:hover         { background: var(--surface2); }
html[data-device="desktop"] .icon-btn:hover svg     { stroke: var(--text); }
html[data-device="desktop"] .btn-primary:hover      { filter: brightness(1.07); box-shadow: 0 6px 20px rgba(45,106,79,.32); }
html[data-device="desktop"] .btn-secondary:hover    { background: var(--surface3); }
html[data-device="desktop"] .chip:hover:not(.active){ background: var(--surface3); }
html[data-device="desktop"] .stat-card:hover        { transform: translateY(-2px); box-shadow: var(--shadow-md), var(--card-ring); }
html[data-device="desktop"] .shift-item:hover       { transform: translateY(-1px); box-shadow: var(--shadow-md), var(--card-ring); }
html[data-device="desktop"] .trip-card:hover        { transform: translateY(-1px); box-shadow: var(--shadow-md); }
html[data-device="desktop"] .payout-card:hover      { transform: translateY(-1px); box-shadow: var(--shadow-md); }
html[data-device="desktop"] .insight-card:hover     { transform: translateY(-2px); box-shadow: var(--shadow-md), var(--card-ring); }
html[data-device="desktop"] .trip-summary-card:hover{ transform: translateY(-2px); box-shadow: var(--shadow-md); }
html[data-device="desktop"] .hm-cell:hover          { opacity: .75; transform: scale(1.15); }
html[data-device="desktop"] .cal-day:not(.empty):hover { box-shadow: var(--shadow-sm); background: var(--surface2); }
html[data-device="desktop"] .month-label:hover      { background: var(--surface2); }
html[data-device="desktop"] .mlb-btn:hover          { filter: brightness(1.1); }
html[data-device="desktop"] .shift-actions button:hover { background: var(--surface3); color: var(--text); }
html[data-device="desktop"] .shift-actions button.del:hover { background: var(--danger-light); color: var(--danger); }
html[data-device="desktop"] .toggle:hover:not(.on)  { background: var(--border-strong); }

/* ── Einstellungen 2.0: Untermenüs ──────────────────────────────────────
   Mobil: Drilldown (Kategorienliste → Pane mit Zurück-Knopf).
   Desktop (html[data-device=desktop]): Seitenleiste + Pane nebeneinander. */
.settings-shell { display: flex; flex-direction: column; min-height: 0; }
.settings-nav { display: flex; flex-direction: column; gap: 5px; }
.settings-nav .modal-title { margin-bottom: 12px; }
.settings-search {
  width: 100%; padding: 10px 13px; margin-bottom: 8px;
  border-radius: 11px; border: 1.5px solid var(--border);
  background: var(--surface2); font-size: .85rem; font-family: var(--font);
  color: var(--text); min-height: 42px; -webkit-appearance: none;
}
.settings-search:focus {
  outline: none; border-color: var(--accent); background: var(--surface);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 14%, transparent);
}
.snav-item {
  display: flex; align-items: center; gap: 11px;
  padding: 13px 14px; border-radius: 13px;
  font-size: .88rem; font-weight: 550; color: var(--text);
  background: var(--surface2); text-align: left; width: 100%;
  transition: all var(--trans);
}
.snav-item::after { content: '›'; margin-left: auto; color: var(--text3); font-size: 1.05rem; }
.snav-item:active { transform: scale(.98); }
/* Icon-Container in Listen/Bannern: zentriert, erbt die Textfarbe */
.snav-ico, .ic-wrap {
  width: 24px; flex-shrink: 0;
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--text2);
}
.snav-ico .ic { width: 18px; height: 18px; }
.snav-item.active .snav-ico { color: var(--accent); }
.ic-wrap .ic { width: 17px; height: 17px; }
.snav-group {
  font-size: .78rem; font-weight: 700; letter-spacing: -.006em;
  color: var(--text2); padding: 14px 14px 5px; margin-top: 2px;
}
.snav-group:first-of-type { margin-top: 0; padding-top: 4px; }
.feat-sub { font-size: max(11px, .72rem); color: var(--text3); margin-top: 2px; }
.snav-close { margin-top: 14px; }
.settings-panes { display: none; }
.settings-shell.pane-open .settings-nav   { display: none; }
.settings-shell.pane-open .settings-panes { display: block; }
.spane-header { display: flex; align-items: center; gap: 10px; margin-bottom: 14px; }
.spane-back {
  width: 38px; height: 38px; border-radius: 12px; flex-shrink: 0;
  background: var(--surface2); font-size: 1.15rem; transition: all var(--trans);
}
.spane-back:active { transform: scale(.92); }
.spane-title { font-family: var(--font-display); font-size: 1.18rem; }
.spane-subtitle {
  font-size: .74rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: .06em; color: var(--text2); margin: 18px 0 10px;
}
.settings-pane { display: none; }
.settings-pane.active { display: block; animation: fadeUp .22s cubic-bezier(.22,1,.36,1); }

/* ── Einstellungen als gruppierte Blöcke ───────────────────────────────────
   Zwei Gründe für diesen Umbau:

   1) LESBARKEIT. Das Blatt ist jetzt Glas. Text direkt darauf hängt in seinem
      Kontrast davon ab, was zufällig darunter liegt — gemessen fielen die
      Feldbeschriftungen dabei auf bis zu 2,9 : 1. Auf einer deckenden Karte
      sind es wieder gesicherte 6,2 : 1, unabhängig vom Untergrund.
   2) ORDNUNG. Genau so bauen iOS und One UI ihre Einstellungen: durchscheinendes
      Material als Untergrund, der Inhalt in ruhigen Blöcken darauf. Das Glas
      zeigt sich in den Zwischenräumen — dort, wo es hingehört.

   Nebeneinanderliegende Felder (form-row) bilden EINEN Block, damit
   Zusammengehöriges auch zusammen aussieht. */
.modal-sheet .form-group,
.modal-sheet .form-row,
.modal-sheet .form-row-3 {
  background: var(--surface); border-radius: 18px;
  padding: 14px 15px; margin-bottom: 10px;
  box-shadow: var(--card-ring);
}
.modal-sheet .form-row,
.modal-sheet .form-row-3 { display: grid; gap: 12px; }
.modal-sheet .form-row   { grid-template-columns: 1fr 1fr; }
.modal-sheet .form-row-3 { grid-template-columns: repeat(3, 1fr); }
/* Innerhalb eines Blocks kein zweiter Block */
.modal-sheet .form-row .form-group,
.modal-sheet .form-row-3 .form-group,
.modal-sheet .kind-fields .form-group,
.modal-sheet .kind-fields .form-row {
  background: none; border-radius: 0; padding: 0; margin-bottom: 0; box-shadow: none;
}
.modal-sheet .form-group:last-child { margin-bottom: 0; }
/* Freistehende Rubriken auf dem Glas bekommen vollen Textkontrast — Sekundär-
   grau hing dort messbar vom Zufall des Untergrunds ab. */
.snav-group, .spane-subtitle { color: var(--text); }

/* Erklärtexte gehören zum Block darüber — deshalb rücken sie an ihn heran und
   bekommen eine eigene, leicht abgesetzte Fläche statt frei auf dem Glas zu
   schweben (dort war ihr Kontrast am schwächsten). */
.field-hint {
  font-size: max(11px, .74rem); color: var(--text2); line-height: 1.5;
  background: var(--surface2); border-radius: 14px;
  padding: 10px 13px; margin: -4px 0 12px;
}
.settings-pane > .field-hint:first-child { margin-top: 0; }
/* Querverweis-Notiz zwischen verwandten Einstellungen (klickbar) */
.xref-note {
  font-size: .74rem; color: var(--text2); line-height: 1.45; cursor: pointer;
  margin: 4px 0 16px; padding: 11px 13px; border-radius: var(--radius-sm);
  background: color-mix(in srgb, var(--accent) 7%, var(--surface2));
  border: 1px solid color-mix(in srgb, var(--accent) 20%, transparent);
  transition: background var(--trans);
}
.xref-note:hover { background: color-mix(in srgb, var(--accent) 12%, var(--surface2)); }
.xref-note:active { transform: scale(.99); }

/* Vorlagen-Verwaltung (Karten mit Zeiten, Pause, Spesen/Zulage, Titel) */
.tmpl-card {
  background: var(--surface2); border-radius: var(--radius-sm);
  padding: 12px; margin-bottom: 10px; box-shadow: var(--card-ring);
}
.tmpl-r1 { display: flex; gap: 8px; align-items: center; margin-bottom: 10px; }
.tmpl-name { flex: 1; font-weight: 650; }
.tmpl-grid { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 8px; margin-bottom: 8px; }
/* Kleiner Rechner direkt im Feld: Eingabe, Einheit, Knopf, Ergebniszeile.
   Er gehört in den Block des Feldes, das er füllt — nicht daneben. */
.inline-calc {
  margin-top: 12px; padding-top: 12px;
  border-top: 1px solid var(--border);
}
.inline-calc > label { font-size: max(11px, .74rem); font-weight: 600; color: var(--text2); margin-bottom: 7px; }
.ic-row { display: flex; align-items: center; gap: 8px; }
.ic-row input { flex: 1 1 auto; min-width: 0; }
.ic-unit { flex: 0 0 auto; font-size: max(11px, .76rem); color: var(--text2); white-space: nowrap; }
.ic-btn  { flex: 0 0 auto; margin: 0; width: auto; padding: 10px 14px; font-size: .82rem; }
.ic-out  { font-size: max(11px, .74rem); color: var(--accent); margin-top: 8px; line-height: 1.45; }
.ic-out:empty { display: none; }

/* Pausen-Hinweis: neutral, solange der Wert reicht — deutlich, wenn er unter
   der gesetzlichen Mindestpause liegt. */
.pause-hint { font-weight: 500; color: var(--accent); }
.pause-hint.is-warn { color: var(--warn); font-weight: 650; }

/* Wie die übrigen Feldbeschriftungen: Satzfall statt Versalien, und nicht
   unter 11 px (bei .64 rem waren es 10,2 px). */
.tmpl-card label {
  display: flex; flex-direction: column; gap: 4px;
  font-size: max(11px, .74rem); font-weight: 650;
  letter-spacing: -.002em; color: var(--text2);
}
.tmpl-full { margin-top: 8px; }
.tmpl-hint { font-weight: 400; letter-spacing: 0; color: var(--text2); }
.tmpl-card input, .tmpl-card select {
  padding: 9px 10px; border-radius: 9px; border: 1.5px solid var(--border);
  background: var(--surface); font-size: .82rem; min-height: 40px; width: 100%;
  font-family: var(--font); color: var(--text); font-weight: 500; -webkit-appearance: none;
}
.tmpl-card input:focus, .tmpl-card select:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 14%, transparent); }
.tmpl-del { width: 40px; height: 40px; flex-shrink: 0; border-radius: 9px; background: var(--danger-light); color: var(--danger); font-size: .9rem; transition: all var(--trans); }
.tmpl-del:active { transform: scale(.92); }

/* Schichtarten-Verwaltung: zweispaltiges Grid (Zuschlag/Spesen) + steuerfrei-Zeile */
.tmpl-grid-2 { grid-template-columns: 1fr 1fr; }
.tmpl-card label.kind-tf {
  flex-direction: row; align-items: center; gap: 9px;
  text-transform: none; letter-spacing: normal; font-size: .8rem;
  font-weight: 500; color: var(--text2); cursor: pointer;
}
.tmpl-card label.kind-tf input[type="checkbox"] { width: auto; min-height: 0; flex-shrink: 0; }

/* Schichtart-Auswahl im Schichtformular */
#shiftKindSelect {
  width: 100%; padding: 11px 12px; border-radius: 11px; border: 1.5px solid var(--border);
  background: var(--surface); font-size: .9rem; font-family: var(--font); color: var(--text);
  font-weight: 500; min-height: 44px; -webkit-appearance: none;
}
#shiftKindSelect:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 14%, transparent); }
.kind-fields {
  margin-top: 10px; padding: 12px; border-radius: var(--radius-sm);
  background: var(--surface2); box-shadow: var(--card-ring);
}
.kind-fields .form-row { margin-bottom: 4px; }
.kind-tf-row {
  display: flex; align-items: center; gap: 9px; margin: 4px 0 8px;
  font-size: .85rem; font-weight: 500; color: var(--text2); cursor: pointer;
}
.kind-tf-row input[type="checkbox"] { width: 18px; height: 18px; flex-shrink: 0; accent-color: var(--accent); }

/* Klickbare Schnellübersichts-Karte (z. B. Zielrechner) */
/* Aktions-Kachel (z. B. Ziel setzen): gefüllt statt gestrichelt — gestrichelte
   Rahmen lesen sich wie „unfertiger Platzhalter", gefüllt wirkt es wie ein
   bewusstes Angebot (native Muster für „Hinzufügen"-Kacheln). */
.dq-action {
  cursor: pointer; border: none;
  background: color-mix(in srgb, var(--accent) 7%, var(--surface));
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--accent) 16%, transparent);
}
.dq-action:active { transform: scale(.96); }
html[data-device="desktop"] .dq-action:hover { border-color: var(--accent); background: var(--accent-bg); }

/* Rotationsmuster-Sequenz */
.rot-seq {
  display: flex; flex-wrap: wrap; gap: 6px;
  min-height: 40px; padding: 8px; border-radius: var(--radius-xs);
  border: 1.5px dashed var(--border-strong); background: var(--surface2);
  align-items: center;
}
.rot-slot {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 5px 10px; border-radius: 16px;
  background: var(--surface); box-shadow: var(--shadow-sm), var(--card-ring);
  font-size: .76rem; font-weight: 550;
}
.rot-slot b { color: var(--text2); font-size: max(11px, .68rem); font-weight: 700; }

/* Sperren-Liste */
.lock-row { display: flex; justify-content: space-between; align-items: center; padding: 11px 2px; border-bottom: 1px solid var(--border); font-size: .88rem; font-weight: 550; }
.lock-row:last-child { border-bottom: none; }
.lock-row .btn-secondary { width: auto; margin: 0; padding: 8px 15px; min-width: 0; font-size: .78rem; }

/* Desktop-Layout */
html[data-device="desktop"] .settings-sheet { max-width: 880px; width: 92vw; }
html[data-device="desktop"] .settings-shell { flex-direction: row; gap: 24px; align-items: stretch; }
html[data-device="desktop"] .settings-nav {
  width: 252px; flex-shrink: 0;
  border-right: 1px solid var(--border); padding-right: 18px;
}
html[data-device="desktop"] .snav-item { background: transparent; padding: 10px 12px; }
html[data-device="desktop"] .snav-item::after { content: ''; }
html[data-device="desktop"] .snav-item:hover { background: var(--surface2); }
html[data-device="desktop"] .snav-item.active { background: var(--accent-bg); color: var(--accent); font-weight: 650; }
html[data-device="desktop"] .snav-close { margin-top: auto; width: 100%; }
html[data-device="desktop"] .settings-panes { display: block; flex: 1; min-width: 0; }
html[data-device="desktop"] .settings-shell.pane-open .settings-nav { display: flex; }
html[data-device="desktop"] .spane-back { display: none; }
html[data-device="desktop"] .settings-pane .btn-secondary { width: 100%; margin-right: 0; }

/* Auth: Split-Layout am Desktop */
html[data-device="desktop"] .auth-shell {
  max-width: 780px; flex-direction: row; min-height: 480px;
}
html[data-device="desktop"] .auth-brand {
  flex: 1 1 46%; padding: 40px 36px;
  display: flex; flex-direction: column; justify-content: flex-end;
}
html[data-device="desktop"] .auth-brand .ab-logo { position: absolute; top: 36px; left: 36px; margin: 0; }
html[data-device="desktop"] .auth-brand h1 { font-size: 2rem; }
html[data-device="desktop"] .auth-form-side {
  flex: 1 1 54%; padding: 44px 40px;
  display: flex; flex-direction: column; justify-content: center;
}
html[data-device="desktop"] .auth-form-side .btn-primary,
html[data-device="desktop"] .auth-form-side .btn-secondary { width: 100%; }
