/* ═══════════════════════════════════════════════════════════════════════════
   nav.css – 3-stufige Shell-Navigation (ds-app-shell + Kindkomponenten)
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── Custom-Element-Display ── */
/* Ohne explizites display sind Custom Elements inline → kein Flex-Stretch */
ds-app-shell {
  display: contents;
}

ds-nav-rail {
  display: flex;
  flex-direction: column;
  align-self: stretch;
  flex-shrink: 0;
}

ds-nav-panel {
  display: flex;
  flex-direction: column;
  align-self: stretch;
  flex-shrink: 0;
}

ds-nav-tabs {
  display: block;
  flex-shrink: 0;
}

ds-bottom-nav {
  display: block;
  flex-shrink: 0;
}

ds-app-header {
  display: block;
  flex-shrink: 0;
}

ds-tab-bar {
  display: block;
  flex-shrink: 0;
}

/* ══════════════════════════════════════════════════════
   VIEWPORT-FIX – html/body duerfen nicht scrollen
   Standalone-PWAs liefern 100dvh oft veraltet/zu gross (beobachtet:
   916px statt echten 860px sichtbaren Viewport) → .ds-shell ragt ueber
   den Rand, die Bottom-Nav (letztes Flex-Kind) wird aus dem Sichtbereich
   geschoben. html/body duerfen daher selbst NICHT scrollen – die Shell
   ist die einzige Scroll-Quelle (eigene overflow-Container innen).
   ══════════════════════════════════════════════════════ */
html, body { height: 100%; overflow: hidden; margin: 0; }

/* ══════════════════════════════════════════════════════
   SHELL – Wrapper
   ══════════════════════════════════════════════════════ */
/* .ds-shell ist seit Ticket 3.42/B68 Punkt 1 (2026-08-07) eine Flex-SPALTE:
   1. Kind = <ds-tab-bar> (volle Breite, nur Desktop + >=1 Tab, s. ds-app-shell.js),
   2. Kind = .ds-shell-row (Icon-Rail + Nav-Panel + Content-Area — die BISHERIGE
   .ds-shell-Zeile, unveraendert, nur umbenannt/eine Ebene tiefer). Die Hoehen-
   Fix-Formel (--app-height/--env-banner-h) bleibt bewusst HIER auf .ds-shell
   und UNVERAENDERT (auch die Env-Banner-Override-Regel weiter unten + die
   index.php-Inline-Kopie brauchen dadurch KEINE Anpassung) — .ds-shell-row
   bekommt ueber `flex:1;min-height:0` automatisch nur den Rest nach Abzug der
   tatsaechlich gerenderten Tab-Leisten-Hoehe. Kein hartcodierter Pixelwert
   fuer die Tab-Leisten-Hoehe noetig (und damit keine neue Fehlerquelle vom
   Schlage des historischen 100dvh-Bugs, s. Kommentar VIEWPORT-FIX oben). */
.ds-shell {
  display: flex;
  flex-direction: column;
  /* --app-height wird per JS auf window.innerHeight gesetzt (index.php,
     Inline-Script direkt nach <body>) – zuverlaessiger als 100dvh in
     Standalone-PWAs. Fallback 100dvh falls das Script mal nicht laeuft. */
  height: calc(var(--app-height, 100dvh) - var(--env-banner-h, 0px));
  margin-top: var(--env-banner-h, 0px);
  overflow: hidden;
  background: var(--bg-secondary);
}

/* Rail + Panel + Content-Area — die ehemalige .ds-shell-Zeile (s. Kommentar
   oben). flex:1 + min-height:0 lassen sie automatisch die Hoehe ausfuellen,
   die .ds-shell nach Abzug der (variablen) Tab-Leisten-Hoehe uebrig laesst. */
.ds-shell-row {
  display: flex;
  flex: 1;
  min-height: 0;
  overflow: hidden;
}

/* ══════════════════════════════════════════════════════
   L1 – ICON RAIL (Desktop)
   ══════════════════════════════════════════════════════ */
.ds-nav-rail {
  width: 56px;
  flex: 1;           /* füllt ds-nav-rail custom element */
  background: var(--bg-primary);
  border-right: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 0.5rem 0;
  z-index: 10;
  overflow: hidden;
  min-height: 0;
}

.ds-rail-logo {
  padding: 0.75rem 0;
  margin-bottom: 0.25rem;
  background: none;
  border: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  border-radius: var(--radius-sm);
  transition: opacity var(--transition);
}
.ds-rail-logo:hover { opacity: 0.85; }
.ds-rail-logo:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.ds-rail-items {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.125rem;
  width: 100%;
  padding: 0 0.375rem;
}

.ds-rail-footer {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.125rem;
  width: 100%;
  padding: 0.375rem;
  border-top: 1px solid var(--border);
}

.ds-rail-item {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border: none;
  background: none;
  border-radius: var(--radius-md);
  color: var(--text-tertiary);
  cursor: pointer;
  transition: background var(--transition), color var(--transition);
  flex-shrink: 0;
}

.ds-rail-item:hover {
  background: var(--bg-secondary);
  color: var(--text-primary);
}


.ds-rail-item.active {
  background: var(--accent-light);
  color: var(--accent);
}

.ds-rail-item svg { width: 20px; height: 20px; flex-shrink: 0; }

/* Avatar-Button im Rail */
.ds-rail-avatar-btn {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  border: none;
  cursor: pointer;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.6875rem;
  font-weight: 700;
  flex-shrink: 0;
  transition: opacity var(--transition);
}

.ds-rail-avatar-btn:hover { opacity: 0.85; }

.ds-rail-avatar {
  width: 32px;
  height: 32px;
  object-fit: cover;
  display: block;
}

/* ── Company-Switcher – Desktop Rail ─────────────────────────── */
.ds-rail-company-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border: 1.5px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--bg-secondary);
  cursor: pointer;
  margin: 0.125rem auto 0.375rem;
  overflow: hidden;
  flex-shrink: 0;
  transition: border-color var(--transition), background var(--transition);
}
.ds-rail-company-btn:hover {
  border-color: var(--accent);
  background: var(--accent-light);
}
.ds-rail-company-logo {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.ds-rail-company-initial {
  font-size: 0.875rem;
  font-weight: 700;
  color: var(--accent);
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
}

/* ── Company-Switcher – Mobile Header ────────────────────────── */
.ds-header-switcher-btn {
  width: 32px;
  height: 32px;
  border: 1.5px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg-secondary);
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  flex-shrink: 0;
}
.ds-header-switcher-btn:hover {
  border-color: var(--accent);
  background: var(--accent-light);
}
.ds-header-switcher-logo {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.ds-header-switcher-initial {
  font-size: 0.75rem;
  font-weight: 700;
  color: var(--accent);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
}

/* ══════════════════════════════════════════════════════
   L2 – SECTION PANEL (Desktop)
   ══════════════════════════════════════════════════════ */
.ds-nav-panel {
  width: 180px;
  flex: 1;           /* füllt ds-nav-panel custom element */
  background: var(--bg-primary);
  border-right: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  overflow-y: auto;
  padding: 0.5rem 0.5rem;
  gap: 0.0625rem;
  min-height: 0;
  position: relative; /* Containing Block für .ds-panel-resize-handle */
}

.ds-panel-module-title {
  font-size: 0.75rem;
  font-weight: 700;
  color: var(--text-primary);
  padding: 0.5rem 0.5rem 0.375rem;
  letter-spacing: -0.01em;
}

.ds-panel-section-title {
  font-size: 0.625rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--text-tertiary);
  padding: 0.625rem 0.5rem 0.25rem;
  margin-top: 0.125rem;
}

.ds-panel-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.375rem;
  padding: 0.4375rem 0.5rem;
  border: none;
  background: none;
  border-radius: var(--radius-md);
  color: var(--text-secondary);
  font-size: 0.8125rem;
  font-weight: 500;
  cursor: pointer;
  transition: background var(--transition), color var(--transition);
  min-height: 36px;
  width: 100%;
  text-align: left;
}

.ds-panel-item:hover {
  background: var(--bg-secondary);
  color: var(--text-primary);
}

.ds-panel-item.active {
  background: var(--accent-light);
  color: var(--accent-dark);
  font-weight: 600;
}

.ds-panel-item-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 15px;
  flex-shrink: 0;
  color: var(--text-tertiary);
}
.ds-panel-item-icon svg { width: 15px; height: 15px; }
.ds-panel-item.active .ds-panel-item-icon { color: var(--accent); }

.ds-panel-item-label {
  flex: 1;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.ds-panel-badge {
  font-size: 0.625rem;
  font-weight: 700;
  background: var(--coral);
  color: #fff;
  border-radius: 99px;
  padding: 0 0.3125rem;
  min-width: 16px;
  height: 16px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  line-height: 1;
}

/* ── Sub-Items (Kinder eines aktiven Panel-Items) ─────────────────────────── */
.ds-panel-sub-list {
  margin: 0.125rem 0 0.25rem 0;
  padding-left: 2rem;
  display: flex;
  flex-direction: column;
  gap: 1px;
}

.ds-panel-sub-item {
  display: block;
  width: 100%;
  text-align: left;
  background: none;
  border: none;
  padding: 0.3125rem 0.625rem;
  border-radius: var(--radius-sm);
  font-size: 0.8125rem;
  color: var(--text-secondary);
  cursor: pointer;
  transition: background var(--transition), color var(--transition);
}

.ds-panel-sub-item:hover {
  background: var(--bg-tertiary);
  color: var(--text-primary);
}

.ds-panel-sub-item.active {
  color: var(--accent);
  font-weight: 600;
  background: var(--accent-light);
}

/* ── Resize-Griff (ziehbare Spaltenbreite, core/sidebar-resize.js,
   Ticket 3.220.1) ────────────────────────────────────────────────
   Absolut positioniert innerhalb von .ds-nav-panel (braucht dafür
   dessen position:relative, s.o.) — top:0/bottom:0/right:0 bleiben
   dabei INNERHALB der Padding-Box (kein negativer Offset), sonst
   würde overflow-y:auto (berechnet damit auch overflow-x:auto) den
   Griff anschneiden. Dadurch bleibt er beim Scrollen der Liste an
   fester Bildschirmposition stehen (der Griff selbst scrollt nicht
   mit, nur der Inhalt darunter). Kein sichtbarer Strich im Ruhe-
   zustand (bewusst zurückhaltend, wie VSCode/Browser-Devtools) —
   Cursor + Hover-/Fokus-Akzentlinie sind die Entdeckungs-Hinweise.
   Nur Desktop: ds-nav-panel.js rendert den Griff gar nicht wenn
   isMobile (die Komponente selbst wird auf Mobile ohnehin nicht
   gemountet, s. ds-app-shell.js) — @media-Sperre unten zusätzlich
   als zweite Absicherung. */
.ds-panel-resize-handle {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  width: 6px;
  cursor: col-resize;
  touch-action: none;
  z-index: 2;
  background: transparent;
}

.ds-panel-resize-handle::after {
  content: '';
  position: absolute;
  top: 0;
  bottom: 0;
  right: 2px;
  width: 2px;
  border-radius: var(--radius-pill);
  background: transparent;
  transition: background var(--transition);
}

.ds-panel-resize-handle:hover::after,
.ds-panel-resize-handle.is-dragging::after {
  background: var(--accent);
}

.ds-panel-resize-handle:focus-visible {
  outline: none; /* Fokus-Feedback läuft über die verstärkte ::after-Akzentlinie */
}

.ds-panel-resize-handle:focus-visible::after {
  background: var(--accent);
  width: 3px;
}

/* Während des Ziehens app-weit Cursor + Textauswahl sperren — bei
   schnellen Bewegungen verlässt der Zeiger den 6px schmalen Griff
   ständig, Pointer-Capture hält zwar die Events fest, aber ohne
   diese Klasse würde der sichtbare Cursor zwischendurch zur
   normalen Pfeilform zurückspringen. */
body.ds-sidebar-resizing {
  cursor: col-resize;
  user-select: none;
}
body.ds-sidebar-resizing * {
  user-select: none;
}

@media (max-width: 900px) {
  .ds-panel-resize-handle { display: none; }
}

/* ══════════════════════════════════════════════════════
   CONTENT AREA
   ══════════════════════════════════════════════════════ */
.ds-content-area {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

/* ══════════════════════════════════════════════════════
   WORKSPACE-TAB-LEISTE (Desktop, Ticket 3.42 / Backlog B68)
   Fensterrahmen-Optik im Marken-Blau (--tabbar-bg): grenzt sich damit
   bewusst deutlich von der flachen L3-Filter-Leiste (.tab-filter, hell/
   neutral) UND von der darunterliegenden .ds-tabs-bar (--bg-primary) ab.
   Der aktive Tab ist eine helle Karte in --bg-primary — dieselbe Farbe wie
   .ds-tabs-bar direkt darunter, dadurch wirkt er optisch "verbunden" mit
   dem Inhalt (klassische Browser-Tab-Metapher: Fensterrahmen dunkel,
   aktiver Tab hell). Nur ab 900px + nur ab 1 Tab gerendert (JS-Gate in
   ds-app-shell.render(), hier zusätzlich als Fail-safe per Media-Query;
   die Grenze war urspruenglich "ab 2 Tabs", Domenico hat das 2026-08-07
   explizit aufgehoben, s. Kommentar in ds-app-shell.js). Seit .ds-shell
   selbst Flex-Spalte ist (s.o.), spannt diese Leiste die VOLLE Breite ueber
   Icon-Rail + Nav-Panel + Content-Area (vorher nur innerhalb .ds-content-area,
   Punkt 1 Nutzer-Feedback).
   ══════════════════════════════════════════════════════ */
.ds-tab-bar {
  display: flex;
  align-items: flex-end;
  gap: 2px;
  background: var(--tabbar-bg);
  padding: 6px 8px 0;
  overflow: hidden;
}

/* flex:0 1 auto (NICHT flex:1) — die Scroll-Region soll sich an ihren Inhalt
   anschmiegen und NICHT die verbleibende Breite der (jetzt viel breiteren,
   volle-Breite) Leiste auffressen. Mit flex:1 wurde der "+"-Knopf bei wenigen
   Tabs an den rechten Rand der GESAMTEN Leiste gedrueckt statt direkt neben
   dem letzten Tab zu stehen (Punkt 2 Nutzer-Feedback). Bei vielen Tabs greift
   weiterhin overflow-x:auto (einzelne Items bleiben flex-shrink:0). */
.ds-tab-bar-scroll {
  display: flex;
  align-items: flex-end;
  gap: 2px;
  flex: 0 1 auto;
  min-width: 0;
  overflow-x: auto;
  scrollbar-width: none;
}
.ds-tab-bar-scroll::-webkit-scrollbar { display: none; }

.ds-tab-bar-item {
  display: flex;
  align-items: center;
  position: relative; /* Anker fuer den Drop-Indikator (::before), s.u. */
  min-width: 132px;
  max-width: 220px;
  flex-shrink: 0;
  border-radius: var(--radius-sm) var(--radius-sm) 0 0;
  /* Eigene, dezente Flaeche im Ruhezustand — ohne sie "schwebt" ein
     inaktiver Tab ohne erkennbare Form auf --tabbar-bg (Nutzer-Feedback
     2026-08-07: "sehen so fliegend aus"). Drei Stufen: Ruhe (hier) <
     Hover (unten) < Aktiv (--bg-primary, unveraendert) — Werte je Theme in
     base.css kalibriert (Light hat mehr Kontrast-Spielraum als Dark). */
  background: var(--tabbar-item-bg);
  transition: background var(--transition);
}

.ds-tab-bar-item:not(.active):hover {
  background: var(--tabbar-item-bg-hover);
}

.ds-tab-bar-item.active {
  background: var(--bg-primary);
}

/* Ziehen zum Umsortieren (Session 4, Punkt 11) — Optik 1:1 vom Vorbild
   ds-todo-project-nav.js uebernommen (P-5), nur die Indikator-Achse gedreht:
   dort ein horizontaler Balken UEBER der Zeile (vertikale Liste), hier ein
   vertikaler Balken LINKS vom Tab (horizontale Leiste) — zeigt an, wo der
   gezogene Tab beim Loslassen eingefuegt wird. */
.ds-tab-bar-item.is-dragging {
  opacity: 0.45;
  cursor: grabbing;
}
.ds-tab-bar-item.is-drop-target::before {
  content: '';
  position: absolute;
  top: 4px;
  bottom: 4px;
  left: -1px;
  width: 2px;
  border-radius: 2px;
  background: var(--tabbar-fg-hover);
}

.ds-tab-bar-item-main {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  border: none;
  background: none;
  cursor: pointer;
  padding: 0.5rem 0.375rem 0.5rem 0.75rem;
  font-size: 0.8125rem;
  font-weight: 500;
  color: var(--tabbar-fg);
  text-align: left;
}
.ds-tab-bar-item-main:hover { color: var(--tabbar-fg-hover); }
.ds-tab-bar-item.active .ds-tab-bar-item-main {
  color: var(--text-primary);
  cursor: default;
}
.ds-tab-bar-item.active .ds-tab-bar-item-main:hover { color: var(--text-primary); }

.ds-tab-bar-item-label {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.ds-tab-bar-item-close {
  flex-shrink: 0;
  width: 20px;
  height: 20px;
  margin-right: 0.375rem;
  display: flex;
  align-items: center;
  justify-content: center;
  border: none;
  border-radius: 50%;
  background: transparent;
  color: var(--tabbar-fg);
  cursor: pointer;
  transition: background var(--transition), color var(--transition);
}
.ds-tab-bar-item-close:hover { background: rgba(255,255,255,.22); color: var(--tabbar-fg-hover); }
.ds-tab-bar-item.active .ds-tab-bar-item-close { color: var(--text-tertiary); }
.ds-tab-bar-item.active .ds-tab-bar-item-close:hover {
  background: var(--bg-tertiary);
  color: var(--text-primary);
}

.ds-tab-bar-add {
  flex-shrink: 0;
  width: 26px;
  height: 26px;
  margin: 0 0.375rem 6px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: none;
  border-radius: 50%;
  background: transparent;
  color: var(--tabbar-fg);
  cursor: pointer;
  transition: background var(--transition), color var(--transition);
}
.ds-tab-bar-add:hover { background: rgba(255,255,255,.18); color: var(--tabbar-fg-hover); }

/* Fokus-Ringe eigens gesetzt statt der globalen :focus-visible-Regel (base.css):
   ein --accent-farbener Ring auf der --tabbar-bg (Light: selbst Marken-Blau)
   wäre unsichtbar. Weiß funktioniert auf BEIDEN Varianten der Leiste (Light
   volles Blau, Dark gedämpftes Navy — beide ausreichend dunkel). */
.ds-tab-bar-item-main:focus-visible,
.ds-tab-bar-item-close:focus-visible,
.ds-tab-bar-add:focus-visible {
  outline: 2px solid var(--tabbar-fg-hover);
  outline-offset: -2px;
  border-radius: var(--radius-sm);
}
.ds-tab-bar-item.active .ds-tab-bar-item-main:focus-visible,
.ds-tab-bar-item.active .ds-tab-bar-item-close:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

@media (max-width: 900px) {
  .ds-tab-bar { display: none; }
}

/* ══════════════════════════════════════════════════════
   L3 – HORIZONTAL TABS
   ══════════════════════════════════════════════════════ */
ds-nav-tabs {
  display: block;
  flex-shrink: 0;
}

.ds-tabs-bar {
  display: flex;
  align-items: stretch;
  background: var(--bg-primary);
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
  min-height: 44px;
}

.ds-tabs-scroll {
  display: flex;
  align-items: center;
  flex: 1;
  overflow-x: auto;
  scrollbar-width: none;
  padding: 0 0 0 1.25rem;
  gap: 0;
  min-width: 0;
}

.ds-tabs-scroll::-webkit-scrollbar { display: none; }

.ds-tabs-actions {
  display: flex;
  align-items: center;
  flex-shrink: 0;
  padding: 0 0.5rem;
  border-left: 1px solid var(--border);
}

.ds-tabs-search-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border: none;
  background: none;
  color: var(--text-tertiary);
  cursor: pointer;
  border-radius: var(--radius-md);
  transition: background var(--transition), color var(--transition);
}

.ds-tabs-search-btn:hover {
  background: var(--bg-secondary);
  color: var(--text-primary);
}

.ds-tabs-search-btn svg { width: 18px; height: 18px; }

/* Auf Mobile: Suche und Avatar bereits im ds-app-header – hier ausblenden */
@media (max-width: 900px) {
  .ds-tabs-actions { display: none; }
}

/* ── Avatar-Button in der Tabs-Bar ── */
.ds-tabs-avatar-wrap {
  position: relative;
}

.ds-tabs-avatar-btn {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  border: 2px solid transparent;
  cursor: pointer;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  background: none;
  padding: 0;
  transition: border-color var(--transition);
  flex-shrink: 0;
}

.ds-tabs-avatar-btn:hover,
.ds-tabs-avatar-btn.open {
  border-color: var(--accent);
}

.ds-tabs-avatar-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  border-radius: 50%;
}

.ds-tabs-avatar-initials {
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.6875rem;
  font-weight: 700;
  border-radius: 50%;
}

/* ── Avatar-Menü Backdrop (schließt Menü bei Außen-/iframe-Klick) ── */
.ds-tabs-menu-backdrop {
  position: fixed;
  inset: 0;
  z-index: 199; /* unter .ds-tabs-user-menu (200) → Menü bleibt klickbar */
  background: transparent;
}

/* ── User-Dropdown-Menü ── */
.ds-tabs-user-menu {
  position: absolute;
  top: calc(100% + 0.5rem);
  right: 0;
  min-width: 220px;
  background: var(--bg-primary);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  z-index: 200;
  overflow: hidden;
}

.ds-tabs-user-info {
  padding: 0.875rem 1rem;
  display: flex;
  flex-direction: column;
  gap: 0.125rem;
}

.ds-tabs-user-name {
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--text-primary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.ds-tabs-user-email {
  font-size: 0.75rem;
  color: var(--text-tertiary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.ds-tabs-menu-divider {
  height: 1px;
  background: var(--border);
  margin: 0;
}

.ds-tabs-menu-item {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  width: 100%;
  padding: 0.625rem 1rem;
  border: none;
  background: none;
  color: var(--text-primary);
  font-size: 0.875rem;
  font-weight: 500;
  cursor: pointer;
  text-align: left;
  transition: background var(--transition);
}

.ds-tabs-menu-item:hover {
  background: var(--bg-secondary);
}

/* „Neu laden"-Eintrag im Avatar-Menü nur auf Mobile zeigen (Caching-Workaround). */
@media (min-width: 901px) {
  .ds-tabs-menu-item--mobile-only { display: none; }
}

.ds-tabs-menu-item svg {
  flex-shrink: 0;
  color: var(--text-tertiary);
}

.ds-tabs-menu-item--danger { color: var(--danger); }
.ds-tabs-menu-item--danger svg { color: var(--danger); }
.ds-tabs-menu-item--danger:hover { background: var(--danger-light); }

.ds-tabs-menu-item--update { color: var(--amber); flex-wrap: wrap; gap: 0.25rem 0.5rem; }
.ds-tabs-menu-item--update svg { color: var(--amber); flex-shrink: 0; }
.ds-tabs-menu-item--update:hover { background: var(--amber-light); }

/* Versions-Label unter dem Menü-Eintrag */
.ds-tabs-menu-subtext {
  display: block;
  width: 100%;
  font-size: 0.7rem;
  font-weight: 400;
  color: var(--text-tertiary);
  line-height: 1.3;
  padding-left: calc(15px + 0.5rem); /* Icon-Breite + gap */
}

/* Update-Dot am Avatar (obere rechte Ecke) */
.ds-update-dot {
  position: absolute;
  top: 0;
  right: 0;
  width: 9px;
  height: 9px;
  background: var(--amber);
  border-radius: 50%;
  border: 2px solid var(--bg-primary);
  pointer-events: none;
}

/* Badge-Zähler rechts in einem Menü-Item */
.ds-tabs-menu-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 18px;
  height: 18px;
  padding: 0 4px;
  border-radius: 99px;
  background: var(--accent);
  color: #fff;
  font-size: 0.6875rem;
  font-weight: 700;
  line-height: 1;
  margin-left: auto;
}

/* Offene-Einladungen: Section-Header (uppercase, small, icon + badge) */
.ds-tabs-menu-invite-header {
  display: flex;
  align-items: center;
  gap: 0.375rem;
  padding: 0.375rem 0.75rem 0.25rem;
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.05em;
  color: var(--teal);
  text-transform: uppercase;
  pointer-events: none;
}
.ds-tabs-menu-invite-header svg {
  flex-shrink: 0;
  color: var(--teal);
}
.ds-tabs-menu-invite-header .ds-tabs-menu-badge {
  background: var(--teal);
  margin-left: auto;
}

/* Einladungs-Item: Titel + Datum/Zeit zweizeilig */
.ds-tabs-menu-invite-item {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.125rem;
  padding: 0.375rem 0.75rem;
  min-height: 44px; /* Touch-Target Pflicht */
  justify-content: center;
}
.ds-tabs-menu-invite-item:hover {
  background: var(--teal-light);
}
.ds-tabs-menu-invite-title {
  font-size: 0.875rem;
  color: var(--text-primary);
  font-weight: 500;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
}
.ds-tabs-menu-invite-time {
  font-size: 0.75rem;
  color: var(--teal);
}

/* „+N weitere" Hinweis (nicht klickbar) */
.ds-tabs-menu-invite-more {
  padding: 0.25rem 0.75rem 0.375rem;
  font-size: 0.75rem;
  color: var(--text-tertiary);
}

/* Offene-Einladungen Menü-Item (teal-Akzent) — Legacy single-item */
.ds-tabs-menu-item--invites {
  color: var(--teal);
}
.ds-tabs-menu-item--invites:hover {
  background: var(--teal-light);
  color: var(--teal);
}
.ds-tabs-menu-item--invites svg {
  color: var(--teal);
}
.ds-tabs-menu-item--invites .ds-tabs-menu-badge {
  background: var(--teal);
}

/* Theme-Toggle innerhalb eines Menü-Items */
.ds-tabs-menu-item .ds-theme-toggle {
  flex-shrink: 0;
  margin-left: auto;
  pointer-events: none; /* Klick geht an den parent button */
}

/* ══════════════════════════════════════════════════════
   NOTIFICATION-CENTER (Glocke + Dropdown-Panel)
   Spec 20260714 Push-/Benachrichtigungs-System, Schritt 8.
   Geteilt zwischen ds-app-header.js (Mobile) + ds-nav-tabs.js (Desktop)
   via core/_notification-center.js.
   ══════════════════════════════════════════════════════ */

/* Anker-Wrapper — trägt sowohl Glocke als auch Dropdown-Panel, analog
   .ds-tabs-avatar-wrap. Panel positioniert sich relativ dazu. */
.ds-notif-wrap {
  position: relative;
}

/* Glocken-Button erbt Größe/Hover vom mitgegebenen btnClass
   (.ds-header-btn mobil, .ds-tabs-search-btn desktop) — hier nur
   Positionierungs-Kontext für den Badge + aktiver Zustand. */
.ds-notif-bell-btn {
  position: relative;
}

.ds-notif-bell-btn.open {
  background: var(--bg-secondary);
  color: var(--text-primary);
}

/* Numerischer Unread-Badge oben rechts an der Glocke */
.ds-notif-badge {
  position: absolute;
  top: 2px;
  right: 2px;
  min-width: 16px;
  height: 16px;
  padding: 0 3px;
  border-radius: 99px;
  background: var(--coral);
  color: #fff;
  font-size: 0.625rem;
  font-weight: 700;
  line-height: 16px;
  text-align: center;
  border: 2px solid var(--bg-primary);
  pointer-events: none;
}

/* Dropdown-Panel (Desktop: rechtsbündig unter der Glocke) */
.ds-notif-panel {
  position: absolute;
  top: calc(100% + 0.5rem);
  right: 0;
  width: 340px;
  max-width: calc(100vw - 2rem);
  max-height: 70vh;
  display: flex;
  flex-direction: column;
  background: var(--bg-primary);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  z-index: 200;
  overflow: hidden;
}

.ds-notif-panel-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  padding: 0.75rem 1rem;
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}

.ds-notif-panel-title {
  font-size: 0.875rem;
  font-weight: 700;
  color: var(--text-primary);
}

.ds-notif-mark-all {
  border: none;
  background: none;
  color: var(--accent);
  font-size: 0.75rem;
  font-weight: 600;
  cursor: pointer;
  padding: 0.25rem 0.375rem;
  border-radius: var(--radius-sm);
  transition: background var(--transition);
  flex-shrink: 0;
}
.ds-notif-mark-all:hover { background: var(--accent-light); }

.ds-notif-panel-body {
  overflow-y: auto;
  flex: 1;
  min-height: 0;
}

.ds-notif-item {
  display: flex;
  align-items: flex-start;
  gap: 0.5rem;
  width: 100%;
  padding: 0.625rem 1rem;
  border: none;
  border-bottom: 1px solid var(--border);
  background: none;
  text-align: left;
  cursor: pointer;
  transition: background var(--transition);
  min-height: 44px; /* Touch-Target Pflicht */
}
.ds-notif-item:last-child { border-bottom: none; }
.ds-notif-item:hover { background: var(--bg-secondary); }
.ds-notif-item.unread { background: var(--accent-light); }
.ds-notif-item.unread:hover { filter: brightness(0.97); }

.ds-notif-item-dot {
  flex-shrink: 0;
  width: 8px;
  height: 8px;
  margin-top: 0.375rem;
  border-radius: 50%;
  background: var(--accent);
}

.ds-notif-item-body {
  display: flex;
  flex-direction: column;
  gap: 0.125rem;
  min-width: 0;
  flex: 1;
}

.ds-notif-item-title {
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--text-primary);
}

.ds-notif-item-text {
  font-size: 0.75rem;
  color: var(--text-secondary);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.ds-notif-item-time {
  font-size: 0.6875rem;
  color: var(--text-tertiary);
  margin-top: 0.125rem;
}

.ds-notif-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  padding: 2.5rem 1rem;
  color: var(--text-tertiary);
  font-size: 0.8125rem;
  text-align: center;
}
.ds-notif-empty svg { opacity: 0.6; }

/* Mobile: Panel wird ein bodennahes Bottom-Sheet statt Dropdown
   (Fingerreichweite + volle Breite) */
@media (max-width: 900px) {
  .ds-notif-panel {
    position: fixed;
    top: auto;
    bottom: 0;
    left: 0;
    right: 0;
    width: auto;
    max-width: none;
    max-height: 75vh;
    border-radius: var(--radius-lg) var(--radius-lg) 0 0;
    padding-bottom: env(safe-area-inset-bottom);
  }
}

/* ── Avatar-Menu: Profil-Sektion ─────────────────────────── */
.ds-avatar-menu-profile-section {
  padding: 0.375rem 0;
}

/* Aktives Profil – Read-only, kein Hover */
.ds-avatar-menu-profile-active {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  padding: 0.5rem 1rem;
  cursor: default;
  min-height: 40px;
}

/* Wechselbares Profil – klickbarer Button */
.ds-avatar-menu-profile-item {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  width: 100%;
  padding: 0.5rem 1rem;
  border: none;
  background: none;
  color: var(--text-primary);
  font-size: 0.875rem;
  font-weight: 400;
  cursor: pointer;
  text-align: left;
  transition: background var(--transition);
  min-height: 40px;
}
.ds-avatar-menu-profile-item:hover {
  background: var(--bg-secondary);
}

/* Profil-Logo / Initial im Menü */
.ds-avatar-menu-profile-logo {
  flex-shrink: 0;
  width: 22px;
  height: 22px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  background: var(--bg-secondary);
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
}
.ds-avatar-menu-profile-logo-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.ds-avatar-menu-profile-initial {
  font-size: 0.6875rem;
  font-weight: 700;
  color: var(--accent);
}

/* Name des Profils */
.ds-avatar-menu-profile-name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 0.875rem;
  color: var(--text-primary);
}
.ds-avatar-menu-profile-active .ds-avatar-menu-profile-name {
  font-weight: 600;
  color: var(--accent);
}

/* Aktiv-Checkmark */
.ds-avatar-menu-profile-check {
  flex-shrink: 0;
  color: var(--accent);
  margin-left: auto;
}

/* „+ Neues Profil" */
.ds-avatar-menu-profile-add {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  width: 100%;
  padding: 0.4375rem 1rem;
  border: none;
  background: none;
  color: var(--text-tertiary);
  font-size: 0.8125rem;
  font-weight: 400;
  cursor: pointer;
  text-align: left;
  transition: background var(--transition), color var(--transition);
  min-height: 36px;
}
.ds-avatar-menu-profile-add:hover {
  background: var(--bg-secondary);
  color: var(--accent);
}
.ds-avatar-menu-profile-add svg {
  flex-shrink: 0;
  color: inherit;
}

/* ── L2-Panel: Profil-Header (Finance-Modul) ──────────────── */
.ds-nav-panel-profile-header {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.5rem 0.625rem 0.5rem 0.5rem;
  margin: 0.25rem 0 0.25rem;
  border-radius: var(--radius-md);
  border: 1px solid var(--border);
  background: var(--bg-secondary);
  cursor: pointer;
  transition: border-color var(--transition), background var(--transition);
  min-height: 44px;
}
.ds-nav-panel-profile-header:hover {
  border-color: var(--accent);
  background: var(--accent-light);
}

.ds-nav-panel-profile-avatar {
  flex-shrink: 0;
  width: 28px;
  height: 28px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  background: var(--bg-primary);
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
}
.ds-nav-panel-profile-avatar-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.ds-nav-panel-profile-avatar-initial {
  font-size: 0.75rem;
  font-weight: 700;
  color: var(--accent);
}

.ds-nav-panel-profile-info {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 0.0625rem;
}

.ds-nav-panel-profile-label {
  font-size: 0.5625rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--text-tertiary);
  line-height: 1;
}

.ds-nav-panel-profile-name {
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--text-primary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  line-height: 1.2;
}

.ds-nav-panel-profile-switch {
  flex-shrink: 0;
  width: 26px;
  height: 26px;
  border: none;
  background: none;
  color: var(--text-tertiary);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-sm);
  transition: background var(--transition), color var(--transition);
  padding: 0;
}
.ds-nav-panel-profile-switch:hover {
  background: var(--border);
  color: var(--accent);
}

/* ── Theme-Toggle Switch (page-app-settings) ── */
.ds-theme-toggle {
  position: relative;
  width: 44px;
  height: 26px;
  border-radius: 99px;
  border: none;
  background: var(--border);
  cursor: pointer;
  flex-shrink: 0;
  transition: background var(--transition);
  padding: 0;
}

.ds-theme-toggle.active {
  background: var(--accent);
}

.ds-theme-toggle-thumb {
  position: absolute;
  top: 3px;
  left: 3px;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: #fff;
  transition: transform var(--transition);
  display: block;
}

.ds-theme-toggle.active .ds-theme-toggle-thumb {
  transform: translateX(18px);
}

/* Gated Zustand (z.B. Modul-/Typ-Toggle solange der übergeordnete
   Master-Schalter aus ist) — Spec 20260714 Notification-Settings. */
.ds-theme-toggle:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

.ds-tab {
  display: inline-flex;
  align-items: center;
  padding: 0.75rem 0.875rem;
  border: none;
  background: none;
  color: var(--text-secondary);
  font-size: 0.875rem;
  font-weight: 500;
  cursor: pointer;
  white-space: nowrap;
  transition: color var(--transition);
  border-bottom: 2px solid transparent;
  margin-bottom: -1px; /* Überlappung mit .ds-tabs-bar border-bottom */
  min-height: 44px;
}

.ds-tab:hover { color: var(--text-primary); }

.ds-tab.active {
  color: var(--accent);
  border-bottom-color: var(--accent);
  font-weight: 600;
}

/* Badge-Zähler innerhalb eines Tab-Buttons (Kanal-Tabs im Messaging) */
.ds-tab-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 16px;
  height: 16px;
  padding: 0 4px;
  margin-left: 0.375rem;
  border-radius: 99px;
  background: var(--accent);
  color: #fff;
  font-size: 0.625rem;
  font-weight: 700;
  line-height: 1;
  vertical-align: middle;
}

/* Gear-/Settings-Icon am rechten Ende der Tab-Leiste */
.ds-tabs-trailing-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 100%;
  min-height: 44px;
  flex-shrink: 0;
  border: none;
  background: none;
  color: var(--text-tertiary);
  cursor: pointer;
  border-radius: 0;
  transition: color var(--transition), background var(--transition);
  text-decoration: none;
  border-left: 1px solid var(--border);
  padding: 0 0.5rem;
}

.ds-tabs-trailing-btn:hover {
  color: var(--text-primary);
  background: var(--bg-secondary);
}

.ds-tabs-trailing-btn.active {
  color: var(--accent);
  background: var(--accent-light);
}

.ds-tabs-trailing-btn svg { width: 16px; height: 16px; }

/* Mobile: Gear-Icon klebt am rechten Rand auch beim horizontalen Scrollen */
@media (max-width: 900px) {
  .ds-tabs-trailing-btn {
    position: sticky;
    right: 0;
    z-index: 2;
    background: var(--bg-primary);
    border-left: 1px solid var(--border);
  }

  /* Bug-Fix 2026-06-12: Das sticky-Zahnrad blutet sonst über ein geöffnetes
     Slide-in-Panel (eigener Stacking-Context von position:sticky). Während ein
     ds-cal-panel offen ist, Zahnrad ausblenden. */
  body:has(.ds-cal-panel.open) .ds-tabs-trailing-btn { display: none; }
}

/* ══════════════════════════════════════════════════════
   CONTENT BODY (scrollbarer Seiteninhalt)
   ══════════════════════════════════════════════════════ */
.ds-content-body {
  flex: 1;
  overflow-y: auto;
  overflow-x: hidden;
  /* overflow-x:hidden verhindert dass position:fixed slide-in-panels (ds-cal-panel)
     mit right:-100% den scrollWidth des content-body aufblaehen — sichtbarer
     horizontaler Scroll am unteren Rand. */
  overscroll-behavior: contain;
  padding: 1.5rem;
  /* pageIn Animation von base.css greift automatisch */
}

/* Mail und Messaging brauchen kein Padding und keinen äußeren Scroll */
.ds-content-body:has(page-mail),
.ds-content-body:has(page-messaging),
.ds-content-body:has(ds-mail-shell) {
  padding: 0;
  overflow: hidden;
}

/* Form-Builder hat eigenen 3-Spalter mit interner Scroll-Logik —
   kein zusätzliches Body-Padding/Scroll. display:flex + flex-direction:column
   ist Pflicht (analog page-calendar/page-todos oben): page-form-builder ist ein
   Flex-Kind mit flex:1 (_core.css) — ohne den Flex-Kontext hier wirkt dessen
   flex:1 nicht und der page-header wird nicht zuverlaessig fixiert (Bug 2026-07-09,
   verifiziert: .form-builder-layout's frueherer 100vh-Calc ignorierte die reale
   Hoehe von .page-header → staendiges Clipping am unteren Rand, unabhaengig von
   Content-Groesse). */
.ds-content-body:has(page-form-builder) {
  padding: 0;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

/* Mobile: Form-Builder stapelt die 3 Bereiche (siehe _core.css @media 900px)
   und will normalen Dokument-Scroll statt interner Flex-Clip-Logik — sonst
   waeren CRM-Feldtypen/Formular-Einstellungen unterhalb der ersten Bildschirm-
   hoehe unerreichbar (verifiziert: ohne diese Regel klemmt overflow:hidden
   bereits im Ausgangszustand ~58px Content ab). */
@media (max-width: 900px) {
  .ds-content-body:has(page-form-builder) {
    display: block;
    overflow-y: auto;
    overflow-x: hidden;
  }
}

/* Kalender: kein Padding, kein äußerer Scroll, Flex-Container damit
   page-calendar via flex: 1 die volle Höhe korrekt ausfüllen kann */
.ds-content-body:has(page-calendar) {
  padding: 0;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

/* Todos: L2-Sidebar (.todos-sidebar) soll ohne Spalt direkt an die
   L1-Icon-Rail anschließen. Fix 3A aus drich_suite_project_views_fixes_r1.md. */
.ds-content-body:has(page-todos) {
  padding: 0;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}
.ds-content-body > page-todos {
  display: block;
  flex: 1;
  min-height: 0;
  min-width: 0;
}

/* Notizen: L2-Sidebar (.notes-sidebar) dockt ohne Spalt direkt an die
   L1-Icon-Rail an und füllt die volle Höhe — analog page-todos.
   Nur Desktop (min-width:901px): auf Mobile nutzt Notizen normalen
   Dokument-Scroll mit Standard-Body-Padding (kein Full-Height-Andocken). */
@media (min-width: 901px) {
  .ds-content-body:has(page-notes) {
    padding: 0;
    overflow: hidden;
    display: flex;
    flex-direction: column;
  }
  .ds-content-body > page-notes {
    display: block;
    flex: 1;
    min-height: 0;
    min-width: 0;
  }
}

/* Notizen Mobile: die "≡ Notizbücher"-Navbar (_renderWorkspaceDrawerToggle,
   analog Todos' _renderMobileNavBar) soll buendig an der weissen App-Leiste
   haengen statt mit grauem Spalt darueber zu schweben. Nur padding-top:0
   (nicht das gesamte Body-Padding wie bei page-todos) — der uebrige Mobile-
   Content (Suchleiste, Karten) behaelt sein seitliches/unteres Polster.
   Die Border-volle-Breite trotz .notes-main-Innenpolster loest ein negativer
   Rand in _notes.css (.notes-main > .ds-mobile-navbar). */
@media (max-width: 900px) {
  .ds-content-body:has(page-notes) {
    padding-top: 0;
  }
}

/* Notizen-Editor (eigene Route seit B38, /#/notes/edit) — schliesst die
   Hoehen-Kette analog zu page-todos oben. 🔒 GILT AUCH AUF MOBILE (anders
   als page-notes darueber, das bewusst normalen Dokument-Scroll behaelt) —
   die Editor-Kopf-/Formatierungsleiste soll beim Lesen/Schreiben langer
   Notizen auf JEDER Breite sichtbar bleiben, nicht nur am Desktop
   (Ticket 3.196.1). Ohne diese Regel hat .notes-editor-page-body
   (_notes.css) keine begrenzte Hoehe — dessen overflow:hidden wirkt dann
   nicht, die GANZE Seite scrollt statt nur .ql-container, und der
   Seiten-Navigator (.ds-note-nav) kann "+ Seite" nie ans Ende seiner
   eigenen, hoehenbeschraenkten Spalte pinnen (beide Symptome, eine
   Ursache — s. Spec-Kommentar in _notes.css). Innenabstand liefert
   .notes-editor-page-body SELBST (padding:1.5rem, _notes.css) — daher
   hier bewusst padding:0, analog page-todos/page-notes. */
.ds-content-body:has(page-note-editor) {
  padding: 0;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}
.ds-content-body > page-note-editor {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-height: 0;
  min-width: 0;
}

/* Web-Lesemodus (Web-Format, NICHT A4/A5) will weiterhin normalen
   Dokument-Scroll — s. _notes.css "Web-Read: Dokument-Scroll" fuer die
   komplette darunterliegende Kette (.notes-editor-page-body bis
   .ql-container). .ds-content-body ist dort wieder der Scroll-Container
   wie auf jeder anderen Nicht-Full-Bleed-Seite (identisch zur generischen
   Basisregel oben) — sonst wuerde das neue overflow:hidden hier den
   Web-Read-Inhalt schlicht abschneiden. Padding bleibt bei 0 (kein
   Doppel-Innenabstand — .notes-editor-page-body liefert ihn ohnehin in
   JEDEM Modus einheitlich, s. Kommentar dort). */
.ds-content-body:has(.ds-note-editor-wrap.ds-note-editor--read:not(.ds-note-page-mode)) {
  overflow-y: auto;
  overflow-x: hidden;
  display: block;
}

/* ══════════════════════════════════════════════════════
   MOBILE HEADER (ds-app-header)
   ══════════════════════════════════════════════════════ */
ds-app-header {
  display: block;
  flex-shrink: 0;
}

.ds-app-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.75rem 1rem;
  background: var(--bg-primary);
  border-bottom: 1px solid var(--border);
  min-height: 56px;
  gap: 0.75rem;
}

.ds-header-left {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  min-width: 0;
  flex: 1;
}

.ds-header-right {
  display: flex;
  align-items: center;
  gap: 0.25rem;
  flex-shrink: 0;
}

.ds-header-title {
  font-size: 1rem;
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.ds-header-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  min-height: 44px;
  border: none;
  background: none;
  color: var(--text-secondary);
  cursor: pointer;
  border-radius: var(--radius-md);
  transition: background var(--transition), color var(--transition);
  padding: 0.5rem;
}

.ds-header-btn:hover {
  background: var(--bg-secondary);
  color: var(--text-primary);
}

.ds-header-logo {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  background: none;
  border: none;
  cursor: pointer;
  padding: 0;
  border-radius: var(--radius-sm);
  color: inherit;
  transition: opacity var(--transition);
}
.ds-header-logo:hover { opacity: 0.85; }
.ds-header-logo:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* ══════════════════════════════════════════════════════
   MOBILE L2-PANEL (vollbreite Liste)
   ══════════════════════════════════════════════════════ */
.ds-mobile-panel-wrap {
  flex: 1;
  overflow-y: auto;
  overscroll-behavior: contain;
}

.ds-mobile-panel-wrap .ds-nav-panel {
  width: 100%;
  border-right: none;
  padding: 0.5rem 0;
  gap: 0;
}

/* Mobile Panel-Zeile (vollbreite Tap-Target) */
.ds-panel-row {
  display: flex;
  align-items: center;
  gap: 0.875rem;
  padding: 0.875rem 1rem;
  border: none;
  background: none;
  color: var(--text-primary);
  font-size: 0.9375rem;
  font-weight: 500;
  cursor: pointer;
  transition: background var(--transition);
  min-height: 56px;
  width: 100%;
  text-align: left;
  border-bottom: 1px solid var(--border);
}

.ds-panel-row:hover   { background: var(--bg-secondary); }
.ds-panel-row.active  { color: var(--accent); }

.ds-panel-row-icon {
  color: var(--text-tertiary);
  display: flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  flex-shrink: 0;
}
.ds-panel-row-icon svg { width: 20px; height: 20px; }

.ds-panel-row-label { flex: 1; }

.ds-panel-row-chevron {
  color: var(--text-tertiary);
  display: flex;
  align-items: center;
}
.ds-panel-row-chevron svg { width: 16px; height: 16px; }

/* Section-Header in Mobile-Panel */
.ds-mobile-panel-wrap .ds-panel-section-title {
  padding: 1rem 1rem 0.375rem;
  background: var(--bg-secondary);
  border-bottom: 1px solid var(--border);
}

/* ══════════════════════════════════════════════════════
   BOTTOM NAVIGATION (Mobile L1)
   ══════════════════════════════════════════════════════ */
ds-bottom-nav {
  display: block;
  flex-shrink: 0;
}

.ds-bottom-nav {
  background: var(--bg-primary);
  border-top: 1px solid var(--border);
  padding-bottom: env(safe-area-inset-bottom);
}

.ds-bottom-nav-items {
  display: flex;
  justify-content: space-around;
  align-items: stretch;
}

.ds-bottom-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.125rem;
  padding: 0.375rem 0.25rem 0.5rem;
  flex: 1;
  border: none;
  background: none;
  cursor: pointer;
  color: var(--text-tertiary);
  font-size: 0.625rem;
  font-weight: 500;
  min-height: 56px;
  transition: color var(--transition);
  -webkit-tap-highlight-color: transparent;
}

.ds-bottom-item.active {
  color: var(--accent);
  font-weight: 600;
}

.ds-bottom-icon-wrap {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* Pill-Hintergrund für aktive Icons */
.ds-bottom-icon-pill {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 28px;
  border-radius: 14px;
  transition: background var(--transition), color var(--transition);
}
.ds-bottom-icon-pill.active {
  background: var(--accent-light);
}
.ds-bottom-item svg { width: 22px; height: 22px; }

/* Dot-Badge */
.ds-bottom-dot {
  position: absolute;
  top: 0;
  right: -2px;
  width: 8px;
  height: 8px;
  background: var(--coral);
  border-radius: 50%;
  border: 2px solid var(--bg-primary);
}

/* Zähler-Badge für Einzelpunkt-Slots (Anzahl statt reinem Punkt) */
.ds-bottom-badge-count {
  position: absolute;
  top: -4px;
  right: -10px;
  min-width: 15px;
  height: 15px;
  padding: 0 3px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--coral);
  color: #fff;
  border-radius: 99px;
  font-size: 0.5625rem;
  font-weight: 700;
  line-height: 1;
  border: 1.5px solid var(--bg-primary);
}

.ds-bottom-label { line-height: 1; }

/* ══════════════════════════════════════════════════════
   DESKTOP-LAYOUT (>900px)
   ══════════════════════════════════════════════════════ */
@media (min-width: 901px) {
  /* Rail + Panel immer sichtbar – display:flex beibehalten damit flex:1 in den Kindelementen greift */
  .ds-shell.desktop ds-nav-rail   { display: flex; }
  .ds-shell.desktop ds-nav-panel  { display: flex; }

  /* Mobile-spezifische Elemente ausblenden */
  .ds-shell.desktop ds-app-header  { display: none; }
  .ds-shell.desktop ds-bottom-nav  { display: none !important; }
  .ds-shell.desktop .ds-mobile-panel-wrap { display: none; }
}

/* ══════════════════════════════════════════════════════
   MOBILE-LAYOUT (≤900px)
   ══════════════════════════════════════════════════════ */
@media (max-width: 900px) {
  /* Rail und Desktop-Panel ausblenden */
  .ds-shell.mobile ds-nav-rail  { display: none; }

  /* Das Desktop-Panel (direkt im ds-shell) ausblenden.
     Nur das Mobile-Panel (in .ds-mobile-panel-wrap) ist sichtbar.
     🔒 Ticket 3.42/B68 Punkt 1: .ds-content-area steckt seit der Workspace-
     Tab-Leisten-Umstrukturierung eine Ebene tiefer in .ds-shell-row — der
     Direkt-Kind-Pfad hier ist entsprechend nachgezogen. */
  .ds-shell.mobile > .ds-shell-row > .ds-content-area > ds-nav-panel:not(.mobile) { display: none; }

  .ds-content-body {
    padding: 1rem;
    /* Kein extra padding-bottom nötig – ds-bottom-nav sitzt im normalen Flow */
  }

  /* Env-Banner-Offset */
  body.has-env-banner .ds-app-header {
    top: 28px;
  }

  /* Bug-Fix 2026-07-14: die Bottom-Nav sitzt im normalen Flow (kein position:fixed)
     und blutet daher unter ein offenes Slide-in-Panel (ds-cal-panel, position:fixed
     mit eigenem Stacking-Context) — Nav-Icons ragen in den Panel-Content, der
     Speichern-Footer liegt teils hinter/über der Nav und ist nicht zuverlässig
     klickbar. Solange ein Primär- oder Sekundär-Panel offen ist, Bottom-Nav
     komplett ausblenden (analog dem Zahnrad-Fix ds-tabs-trailing-btn oben) —
     sowie der Todos-Off-Canvas-Drawer (.ds-drawer.is-open) und das Todos-
     Detail-Panel (.todos-detail-panel, page-todos.js — kein <ds-cal-panel>,
     eigenes Markup, traegt im geschlossenen Zustand die Klasse .closed, daher
     :not(.closed) statt einer eigenen offen-Klasse), die aus demselben Grund
     (tief im Baum gerenderter position:fixed-Layer) unter der Bottom-Nav
     landen. Diese Liste ist gepflegt -- ein neues Vollbild-Panel gehoert hier
     hinein, nicht in eine zweite, JS-verwaltete Loesung (P-5).
     Ticket 3.214 (2026-08-17): Mail-Modul ergaenzt -- .mail-att-preview-backdrop
     ist der EINE geteilte fixed-Backdrop fuer drei Vollbild-Panels (Anhang-
     Vorschau, "Kontakt aus Mail anlegen" + "Als Aufgabe anlegen" -- beide
     rendern als .mail-cc-panel INNERHALB derselben Backdrop-Klasse, s.
     pages/mail.js/design-system.md "Mail: Kontakt-Anlegen-Panel"), daher reicht
     ein Selektor fuer alle drei. .mail-compose-panel (Neu/Antworten/Weiterleiten)
     wird erst auf Mobile zu einem eigenen position:fixed;inset:0-Layer
     (_core.css "Mobile overrides") und war bislang ebenfalls nicht in der Liste.
     Ticket 3.258 (2026-08-17): App-weiter Vollbild-Overlay-Audit (Beleg: per
     elementFromPoint gemessen, echtes Chrome, kein Theorie-Blick in den Code).
     Ergebnis: NUR Panels, deren sichtbarer Inhalt auf Mobile EDGE-TO-EDGE ist
     (top:0 UND bottom:0/height:100% -- kein Rand irgendwo) sind betroffen. Ein
     Bottom-Sheet mit Rand oben (Modal.confirm/.modal, ds-more-sheet, ds-bundle-
     sheet, .cal-poll-slot-picker-popover, .cal-dp-dropdown, .ds-note-nav-sheet --
     alle max-height/bottom:0 OHNE top:0) blutet NICHT -- gemessen, nicht
     angenommen. .cal-booking-overlay-panel (Buchungs-Stornierung/-Verschiebung,
     Gegenvorschlag/Counter-Overlay UND Aenderungsverlauf-Overlay -- alle drei
     reusen dieselbe Klasse, calendar.js) ist auf Mobile top:0;bottom:0;width:100%
     -- echtes Edge-to-edge, per Test bestaetigt betroffen. .receipts-scanner-wrap
     (Beleg-Scanner) ist ebenfalls edge-to-edge, rendert aber IMMER innerhalb eines
     bereits gelisteten .ds-cal-panel/-secondary (receipts.js + bookkeeping.js) --
     daher ohne eigenen Eintrag bereits abgedeckt.
     Ticket 3.252 (2026-08-21): dieselbe Selektorliste blendet zusaetzlich
     .ios-install-banner aus (layout.css) -- SIEHE den ungegateten Block
     weiter unten in dieser Datei (nach dem @media max-width:900px-Ende),
     NICHT hier mit reingemischt, weil der Banner auch im Desktop-Shell-
     Modus auftreten kann (iPad Querformat >900px ist noch iOS, triggert
     aber .ds-shell.desktop) -- die Bottom-Nav-Regel hier bleibt bewusst
     mobile-only gegated. */
  body:has(.ds-cal-panel.open) ds-bottom-nav,
  body:has(.ds-cal-panel-secondary.open) ds-bottom-nav,
  body:has(.ds-drawer.is-open) ds-bottom-nav,
  body:has(.todos-detail-panel:not(.closed)) ds-bottom-nav,
  body:has(.ds-time-quick-bar-sheet.is-open) ds-bottom-nav,
  body:has(.mail-att-preview-backdrop) ds-bottom-nav,
  body:has(.mail-compose-panel) ds-bottom-nav,
  body:has(.cal-booking-overlay-backdrop) ds-bottom-nav {
    display: none;
  }

  /* FAB bei offenem Vollbild-Layer (Mobile) ausblenden -- der (+)-Knopf liegt
     sonst ueber dem Panel-Inhalt. #fab (ID-Selektor) reicht ohne !important,
     um .fab.visible zu schlagen. Ticket 3.163.16-Nachtrag (2026-08-10): das
     Todos-Detail-Panel (.todos-detail-panel, z-index:300, s. page-todos.js)
     ergaenzt -- war beim urspruenglichen Bottom-Nav-Fix (s.o.) uebersehen
     worden. Diese Liste ist ebenfalls gepflegt (analog zur Bottom-Nav-Liste
     oben) -- ein neues Vollbild-Panel das den FAB verdeckt gehoert HIER
     hinein, keine zweite JS-verwaltete Loesung (P-5).
     Ticket 3.354.9 (2026-08-24): .ds-cal-panel.open + .ds-cal-panel-secondary.open
     + .ds-drawer.is-open ergaenzt -- notes.js (Notizbuecher-Drawer + dessen
     Workspace-Formular-Sekundaerpanel) sowie driver-log.js UND die eigene
     Fahrzeug-Liste driver-log-vehicles.js (#/driver-log/vehicles, beide nutzen
     dasselbe ds-cal-panel fuer ihre Formulare) riefen window.FAB.hide() beim
     Panel-Oeffnen nie auf (anders als mail.js/calendar.js, die den FAB selbst
     per JS ausblenden) -- der Knopf blieb ueber dem Panel sichtbar UND
     anklickbar. Alle drei Selektoren sind bereits Teil der oben auditierten
     Bottom-Nav-Liste (Ticket 3.258: nur Panels mit echtem Edge-to-edge
     top:0+bottom:0 sind betroffen) -- hier dieselben drei uebernommen, nicht
     neu erfunden. */
  body:has(.ds-cal-panel.open) #fab,
  body:has(.ds-cal-panel-secondary.open) #fab,
  body:has(.ds-drawer.is-open) #fab,
  body:has(.ds-time-quick-bar-sheet.is-open) #fab,
  body:has(.todos-detail-panel:not(.closed)) #fab {
    display: none;
  }
}

@media (max-width: 600px) {
  .ds-content-body {
    padding: 0.75rem;
  }
}

/* ── PWA-Install-Banner bei offenem Vollbild-Panel ausblenden (Ticket 3.252) ──
   .ios-install-banner (layout.css, position:fixed, z-index:950, bottom:0) liegt
   ueber dem unteren Rand JEDES Slide-in-Panels (.ds-cal-panel z-index:401 usw.)
   -- der Banner ist z-index-hoeher als jedes Panel, verdeckt dessen Fusszeile.
   Statt den Panel-z-index ueber 950 zu heben (gewachsene Schichtung, siehe
   layout.css-Kommentar oben .ios-install-banner: Toast/ContextMenu/Drawer/
   Command-Palette haengen an diesem Verhaeltnis), wird stattdessen der Banner
   ausgeblendet -- exakt dieselbe Selektorliste + dasselbe body:has()-Muster wie
   bei ds-bottom-nav oben (P-5, siehe Querverweis-Kommentar dort).

   BEWUSST OHNE @media (max-width: 900px)-Gate (Unterschied zur Bottom-Nav-
   Regel oben): .ios-install-banner ist rein Userscript-Agent-gated (app.js
   zeigt ihn nur auf iOS/!standalone, unabhaengig vom Shell-Mobile/Desktop-
   Modus). Ein iPad im Querformat (>900px) laeuft in .ds-shell.desktop, ist
   aber weiterhin iOS und zeigt den Banner -- die Regel muss daher AUCH im
   Desktop-Breakpoint greifen, sonst blutet der Banner dort weiterhin ins
   Panel. nav.css laedt nach layout.css (app/index.php) -- diese Regel
   gewinnt bei gleicher Spezifitaet (0,0,2,1 beidseitig) durch Ladereihenfolge,
   unabhaengig vom @media-Kontext. */
body:has(.ds-cal-panel.open) .ios-install-banner,
body:has(.ds-cal-panel-secondary.open) .ios-install-banner,
body:has(.ds-drawer.is-open) .ios-install-banner,
body:has(.todos-detail-panel:not(.closed)) .ios-install-banner,
body:has(.ds-time-quick-bar-sheet.is-open) .ios-install-banner,
body:has(.mail-att-preview-backdrop) .ios-install-banner,
body:has(.mail-compose-panel) .ios-install-banner,
body:has(.cal-booking-overlay-backdrop) .ios-install-banner {
  display: none;
}

/* ══════════════════════════════════════════════════════
   ANIMATIONEN
   ══════════════════════════════════════════════════════ */
@media (prefers-reduced-motion: no-preference) {
  /* Content-Bereich Fade bei L2-Wechsel.
     contentIn = opacity-only — kein transform, sonst Containing-Block fuer fixed
     Slide-In-Panels (ds-cal-panel). Siehe base.css @keyframes contentIn.
     MUSS synchron mit ds-app-shell.js _mountPage gehalten werden (P-5). */
  .ds-content-body {
    animation: contentIn 150ms ease forwards;
  }

  /* Mobile Ebene 2 → 3 */
  .ds-mobile-l3-enter {
    animation: slideInRight 200ms ease-out forwards;
  }

  /* Mobile Zurück Ebene 3 → 2 */
  .ds-mobile-l3-leave {
    animation: slideOutRight 200ms ease-out forwards;
  }
}

/* `to`/`from`-Ruhezustand ist `transform: none` statt `translateX(0)` — analog
   `contentIn` (base.css:257-263): ein `forwards`-gehaltener transform-Endwert
   (auch translateX(0)) erzeugt einen Containing-Block für position:fixed-
   Nachfahren (ds-cal-panel u.a. Slide-In-Panels) → Panel wird geclippt statt
   viewport-fixed. `none` erzeugt KEINEN Containing-Block. MUSS synchron mit
   base.css:257 gehalten werden (P-5). */
@keyframes slideInRight {
  from { transform: translateX(100%); opacity: 0; }
  to   { transform: none;             opacity: 1; }
}

@keyframes slideOutRight {
  from { transform: none;             opacity: 1; }
  to   { transform: translateX(100%); opacity: 0; }
}

/* ══════════════════════════════════════════════════════
   DARK MODE – keine Anpassungen nötig: alle Werte nutzen
   CSS-Variablen die bereits Dark-Mode-Varianten haben.
   ══════════════════════════════════════════════════════ */

/* ══════════════════════════════════════════════════════
   ENV-BANNER OFFSET
   ══════════════════════════════════════════════════════ */
body.has-env-banner .ds-shell {
  height: calc(var(--app-height, 100dvh) - 28px);
  margin-top: 28px;
}

/* ══════════════════════════════════════════════════════
   ds-bundle-sheet – Popover-Sheet für Bundle-Slots in der Bottom Nav
   Erscheint direkt über dem getippten Bottom-Nav-Slot.
   ══════════════════════════════════════════════════════ */

/* Wrapper: nimmt kein Platz ein; ermöglicht Positionierung relativ zu fixed */
.ds-bundle-sheet {
  position: fixed;
  inset: 0;
  z-index: 490;
  pointer-events: none;
}
.ds-bundle-sheet.open {
  pointer-events: all;
}

/* Transparenter Backdrop: schließt Sheet bei Tap */
.ds-bundle-sheet-backdrop {
  position: absolute;
  inset: 0;
  background: transparent;
  pointer-events: none;
}
.ds-bundle-sheet.open .ds-bundle-sheet-backdrop {
  pointer-events: all;
}

/* Sheet-Inhalt: positioniert über Bottom-Nav, zentriert auf Slot */
.ds-bundle-sheet-content {
  position: absolute;
  /* Über Bottom Nav (56px) + safe-area + 8px Abstand */
  bottom: calc(56px + env(safe-area-inset-bottom) + 8px);
  width: 180px;
  background: var(--bg-primary);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-lg);
  overflow: hidden;
  /* Slide-up-Animation */
  transform: translateY(8px);
  opacity: 0;
  transition: transform 180ms ease, opacity 180ms ease;
  pointer-events: none;
}
.ds-bundle-sheet.open .ds-bundle-sheet-content {
  transform: translateY(0);
  opacity: 1;
  pointer-events: all;
}

/* Einzelne Einträge im Bundle-Sheet */
.ds-bundle-sheet-item {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  width: 100%;
  padding: 0.75rem 1rem;
  border: none;
  background: none;
  color: var(--text-primary);
  font-size: 0.9375rem;
  font-weight: 500;
  cursor: pointer;
  text-align: left;
  min-height: 44px;
  transition: background var(--transition);
  -webkit-tap-highlight-color: transparent;
}
.ds-bundle-sheet-item + .ds-bundle-sheet-item {
  border-top: 1px solid var(--border);
}
.ds-bundle-sheet-item:active,
.ds-bundle-sheet-item:hover {
  background: var(--bg-secondary);
}
.ds-bundle-sheet-item.active {
  color: var(--accent);
}

.ds-bundle-sheet-item-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  color: var(--text-tertiary);
  width: 20px;
}
.ds-bundle-sheet-item.active .ds-bundle-sheet-item-icon {
  color: var(--accent);
}
.ds-bundle-sheet-item-icon svg {
  width: 20px;
  height: 20px;
}

.ds-bundle-sheet-item-label { flex: 1; }

/* Amber-Dot Variante für Bundle-Badge-Aggregation */
.ds-bottom-dot--amber {
  background: var(--amber);
  border-color: var(--bg-primary);
}

/* ds-bundle-sheet auf Desktop nie zeigen */
@media (min-width: 901px) {
  .ds-bundle-sheet { display: none !important; }
}

/* ══════════════════════════════════════════════════════
   ds-more-sheet – Bottom Sheet (Mobile)
   ══════════════════════════════════════════════════════ */
ds-more-sheet {
  /* Außerhalb .ds-content-area damit z-index korrekt überlappt */
  position: fixed;
  inset: 0;
  z-index: 500;
  pointer-events: none; /* Kein Blocking wenn geschlossen */
}

/* Backdrop */
.ds-more-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0);
  transition: background var(--transition-slow);
  pointer-events: none;
}
.ds-more-backdrop.visible {
  background: rgba(0, 0, 0, 0.45);
  pointer-events: all;
}

/* Sheet */
.ds-more-sheet {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  background: var(--bg-primary);
  border-radius: var(--radius-xl) var(--radius-xl) 0 0;
  box-shadow: 0 -4px 32px rgba(0, 0, 0, 0.12);
  transform: translateY(100%);
  transition: transform 280ms cubic-bezier(0.25, 0.46, 0.45, 0.94);
  pointer-events: none;
  padding-bottom: env(safe-area-inset-bottom);
  max-height: 85dvh;
  overflow-y: auto;
  overscroll-behavior: contain;
}
.ds-more-sheet.open {
  transform: translateY(0);
  pointer-events: all;
}

/* Handle-Zeile (Tap zum Schließen) */
.ds-more-handle-row {
  display: flex;
  justify-content: center;
  padding: 0.625rem 0 0.375rem;
  cursor: pointer;
}
.ds-more-handle {
  width: 36px;
  height: 4px;
  background: var(--border);
  border-radius: 2px;
}

/* Divider zwischen Gruppen */
.ds-more-divider {
  height: 1px;
  background: var(--border);
  margin: 0.25rem 0;
}

/* Modul-Ueberschrift (voller Desktop-Spiegel, 2026-07-19) — ein Block pro
   L1-Modul, analog .ds-panel-module-title (Desktop-L2-Panel), nur groesser
   skaliert fuer die 1rem/56px-Mobile-Item-Groesse. */
.ds-more-module-header {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.75rem 1.25rem 0.25rem;
  font-size: 0.9rem;
  font-weight: 700;
  color: var(--text-primary);
}
.ds-more-sheet > .ds-more-module-header:first-of-type { padding-top: 0.375rem; }
.ds-more-module-header-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--text-tertiary);
}
.ds-more-module-header-icon svg { width: 18px; height: 18px; }

/* Sektionstitel innerhalb eines Moduls — analog .ds-panel-section-title
   (Desktop-L2-Panel), nur groesser skaliert. */
.ds-more-section-title {
  font-size: 0.7rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--text-tertiary);
  padding: 0.5rem 1.25rem 0.125rem;
}

/* Item-Zeile */
.ds-more-item {
  display: flex;
  align-items: center;
  gap: 0.875rem;
  width: 100%;
  padding: 0.875rem 1.25rem;
  border: none;
  background: none;
  color: var(--text-primary);
  font-size: 1rem;
  font-weight: 500;
  cursor: pointer;
  text-align: left;
  transition: background var(--transition);
  min-height: 56px;
  -webkit-tap-highlight-color: transparent;
}
.ds-more-item:active { background: var(--bg-secondary); }
.ds-more-item.active { color: var(--accent); }

.ds-more-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  flex-shrink: 0;
  color: var(--text-tertiary);
}
.ds-more-item.active .ds-more-icon { color: var(--accent); }
.ds-more-icon svg { width: 22px; height: 22px; }

.ds-more-label { flex: 1; }

.ds-more-badge {
  font-size: 0.6875rem;
  font-weight: 700;
  background: var(--coral);
  color: #fff;
  border-radius: 99px;
  padding: 0.125rem 0.375rem;
  min-width: 20px;
  text-align: center;
  flex-shrink: 0;
}

/* ── Mobiles „Mehr" — Drilldown (Spec 20260719_mobile_more_drilldown) ────────
   Ebene 1 bleibt flach (Haupt-Items + Vertrieb/Erfassung sichtbar); nur
   "einstellungs-/verwaltungs-artige" Sektionen (settingsSections + explizit
   mobileDrill:true) verstecken sich hinter einem Chevron und öffnen Ebene 2. */

/* Split-Tap-Zeile für self-titled Module (Nachrichten/Kalender/Notizen):
   Modul-Navigate-Button (.ds-more-item, flex:1) + Chevron-Button als
   Geschwister nebeneinander — kein Button-in-Button (ungültiges HTML). */
.ds-more-item-row {
  display: flex;
  align-items: stretch;
}
.ds-more-item-row .ds-more-item {
  flex: 1;
  width: auto;
}

/* Split-Tap-Chevron: eigener Tap-Target (≥44px in beide Richtungen), analog
   dem Desktop-Profil-Picker-Zeilen-Gear (ds-app-shell.js _gotoProfileSettings). */
.ds-more-item-chevron {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 3rem;
  min-height: 56px;
  flex-shrink: 0;
  border: none;
  background: none;
  color: var(--text-tertiary);
  cursor: pointer;
  transition: color var(--transition), background var(--transition);
  -webkit-tap-highlight-color: transparent;
}
.ds-more-item-chevron:hover,
.ds-more-item-chevron:active {
  color: var(--accent);
  background: var(--bg-secondary);
}
.ds-more-item-chevron svg { width: 16px; height: 16px; }

/* Drill-Trigger-Zeile (Gruppen-Modul, z.B. "Verwaltung"/"Admin"/"Plattform"/
   "Einstellungen"): wie .ds-more-item, aber Chevron rechts mit eigenem
   margin-left:auto + gedämpfter Farbe statt Icon links. */
.ds-more-drill-row {
  display: flex;
  align-items: center;
  gap: 0.875rem;
  width: 100%;
  padding: 0.875rem 1.25rem;
  border: none;
  background: none;
  color: var(--text-primary);
  font-size: 1rem;
  font-weight: 500;
  cursor: pointer;
  text-align: left;
  transition: background var(--transition);
  min-height: 56px;
  -webkit-tap-highlight-color: transparent;
}
.ds-more-drill-row:hover,
.ds-more-drill-row:active { background: var(--bg-secondary); }
.ds-more-drill-row-label { flex: 1; }
.ds-more-drill-row-chevron {
  display: flex;
  align-items: center;
  margin-left: auto;
  color: var(--text-secondary);
  flex-shrink: 0;
}
.ds-more-drill-row-chevron svg { width: 16px; height: 16px; }

/* Ebene-2-Kopf: Zurück-Pfeil (chevron-left) + Kontext-Label (Modul-Name). */
.ds-more-drill-head {
  display: flex;
  align-items: center;
  padding: 0.5rem 0.75rem 0.375rem;
}
.ds-more-drill-back {
  display: flex;
  align-items: center;
  gap: 0.375rem;
  border: none;
  background: none;
  color: var(--text-primary);
  font-size: 1rem;
  font-weight: 700;
  cursor: pointer;
  padding: 0.5rem;
  min-height: 44px;
  border-radius: var(--radius-md);
  transition: background var(--transition);
  -webkit-tap-highlight-color: transparent;
}
.ds-more-drill-back:hover,
.ds-more-drill-back:active { background: var(--bg-secondary); }
.ds-more-drill-back svg { width: 20px; height: 20px; flex-shrink: 0; color: var(--text-tertiary); }
.ds-more-drill-title {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.ds-more-safe-area {
  height: 0.5rem;
}

/* ds-more-sheet auf Desktop nie zeigen */
@media (min-width: 901px) {
  ds-more-sheet { display: none !important; }
}

/* Mobile Header: User-Menü klappt nach unten auf (Header ist ganz oben) */
.ds-header-user-menu {
  top: calc(100% + 0.5rem);
  right: 0;
  left: auto;
}

/* ══════════════════════════════════════════════════════
   HEADER BACK BUTTON
   ══════════════════════════════════════════════════════ */
.ds-header-back-btn {
  gap: 0.125rem;
  padding-left: 0.25rem;
  min-width: 0;
  flex-shrink: 1;
}
.ds-header-back-label {
  font-size: 0.9375rem;
  font-weight: 500;
  color: var(--accent);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 160px;
}

/* ══════════════════════════════════════════════════════
   DS-DEBUG-BAR — Globale Debug-Leiste (Platform-Admin)
   z-index 480 = über Slide-in-Panels (401–403),
   unter ds-more-sheet/Booking-Overlays (500+) + ContextMenu (1100)
   ══════════════════════════════════════════════════════ */

ds-debug-bar {
  display: contents;
}

.ds-debug-bar {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 480;
  display: flex;
  align-items: center;
  gap: 0.625rem;
  min-height: 40px;
  padding: 0.25rem 0.875rem;
  padding-bottom: calc(0.25rem + env(safe-area-inset-bottom));
  background: var(--bg-primary);
  border-top: 2px solid var(--teal);
  box-shadow: var(--shadow-md);
}

.ds-debug-bar-badge {
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--teal);
  background: var(--teal-light);
  border-radius: 999px;
  padding: 0.125rem 0.5rem;
  flex-shrink: 0;
}

.ds-debug-bar-expiry {
  font-size: 0.75rem;
  color: var(--text-tertiary);
  flex-shrink: 0;
}

.ds-debug-bar-spacer {
  flex: 1;
}

/* analog .btn .btn-ghost .btn-sm */
.ds-debug-bar-btn {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  padding: 0.25rem 0.625rem;
  font-size: 0.8125rem;
  font-weight: 500;
  min-height: 30px;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: transparent;
  color: var(--text-secondary);
  cursor: pointer;
  transition: background var(--transition), color var(--transition), border-color var(--transition);
  white-space: nowrap;
}

.ds-debug-bar-btn:hover {
  background: var(--bg-secondary);
  color: var(--text-primary);
}

.ds-debug-bar-btn.is-active {
  background: var(--teal-light);
  color: var(--teal);
  border-color: var(--teal);
}

.ds-debug-bar-btn.is-active:hover {
  background: var(--teal-light);
  color: var(--teal);
}

/* ── Sheet (Log-Overlay direkt über der Leiste) ── */
.ds-debug-bar-sheet {
  position: fixed;
  left: 0;
  right: 0;
  /* Desktop: direkt über der 40px Bar + safe-area */
  bottom: calc(40px + env(safe-area-inset-bottom));
  height: 45vh;
  z-index: 479;
  background: var(--bg-primary);
  border-top: 1px solid var(--border);
  box-shadow: var(--shadow-lg);
  display: flex;
  flex-direction: column;
}

.ds-debug-bar-sheet-header {
  display: flex;
  align-items: center;
  gap: 0.375rem;
  padding: 0.375rem 0.875rem;
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
  background: var(--bg-secondary);
}

.ds-debug-bar-sheet-title {
  flex: 1;
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--text-primary);
}

.ds-debug-bar-sheet-body {
  flex: 1;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding: 0.625rem 0.875rem;
}

/* ── Log-Ausgabe ── */
.ds-debug-bar-log {
  font-family: ui-monospace, 'Cascadia Code', 'Fira Code', Consolas, monospace;
  font-size: 0.72rem;
  line-height: 1.5;
  white-space: pre-wrap;
  word-break: break-all;
  color: var(--text-primary);
  margin: 0;
}

/* ── Mail-Log Zeilen ── */
.ds-debug-bar-mailrow {
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
  padding: 0.3125rem 0;
  border-bottom: 1px solid var(--border);
  font-size: 0.78rem;
  flex-wrap: wrap;
}

.ds-debug-bar-mailrow:last-child {
  border-bottom: none;
}

.ds-debug-bar-mailrow-time {
  color: var(--text-tertiary);
  white-space: nowrap;
  flex-shrink: 0;
}

.ds-debug-bar-mailrow-type {
  color: var(--text-secondary);
  flex-shrink: 0;
  white-space: nowrap;
}

.ds-debug-bar-mailrow-to {
  color: var(--text-secondary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 18rem;
  flex-shrink: 1;
}

.ds-debug-bar-mailrow-subject {
  color: var(--text-primary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  flex: 1;
  min-width: 0;
}

/* ── DB-Fehlerlog-Zeilen (error_log_db) ── */
.ds-debug-bar-dbrow {
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
  padding: 0.3125rem 0;
  border-bottom: 1px solid var(--border);
  font-size: 0.78rem;
  flex-wrap: wrap;
}

.ds-debug-bar-dbrow:last-child {
  border-bottom: none;
}

.ds-debug-bar-dbrow-time {
  color: var(--text-tertiary);
  white-space: nowrap;
  flex-shrink: 0;
}

.ds-debug-bar-dbrow-path {
  color: var(--text-secondary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 16rem;
  flex-shrink: 1;
  font-family: ui-monospace, 'Cascadia Code', Consolas, monospace;
  font-size: 0.72rem;
}

.ds-debug-bar-dbrow-msg {
  color: var(--coral);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  flex: 1;
  min-width: 0;
  font-family: ui-monospace, 'Cascadia Code', Consolas, monospace;
  font-size: 0.72rem;
}

.ds-debug-bar-dbsection {
  margin-bottom: 0.75rem;
  padding-bottom: 0.5rem;
  border-bottom: 2px solid var(--border);
}

.ds-debug-bar-dbsection-label {
  font-size: 0.6875rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-tertiary);
  margin-bottom: 0.25rem;
}

/* ── Mobile: über der Bottom-Nav (56px) ── */
@media (max-width: 900px) {
  .ds-debug-bar {
    bottom: calc(56px + env(safe-area-inset-bottom));
    padding-bottom: 0.25rem;
  }

  .ds-debug-bar-sheet {
    /* Bar: 40px + Bottom-Nav: 56px + safe-area */
    bottom: calc(56px + env(safe-area-inset-bottom) + 40px);
    height: 50vh;
  }

  .ds-debug-bar-mailrow-to {
    max-width: 12rem;
  }
}

/* ── Handlungsbedarf-Alert-Banner (generisch, Spec 20260729_actionable_alerts.md) ──
   Ersetzt den frueheren migrations-only Migrations-Banner (eigene Klasse, nur amber).
   Farbe kommt ausschliesslich aus dem --warning/--error/--info-Modifier (severity vom
   Server, s. GET /user-alerts) — die Basisklasse traegt nur Layout. Mehrere Alerts
   stapeln sich als eigene Balken (jeder mit eigenem border-bottom + Farbflaeche),
   kein zusaetzlicher Trenner noetig. */
.ds-alert-banner {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.5rem 1rem;
  font-size: 0.875rem;
  font-weight: 500;
  flex-shrink: 0;
}

.ds-alert-banner--warning {
  background: var(--amber-light);
  color: var(--amber);
  border-bottom: 1px solid var(--amber);
}
.ds-alert-banner--error {
  background: var(--coral-light);
  color: var(--coral);
  border-bottom: 1px solid var(--coral);
}
.ds-alert-banner--info {
  background: var(--accent-light);
  color: var(--accent);
  border-bottom: 1px solid var(--accent);
}

.ds-alert-banner-icon {
  flex-shrink: 0;
  display: flex;
  align-items: center;
}

.ds-alert-banner-text {
  flex: 1;
  min-width: 0;
}

.ds-alert-banner-link {
  flex-shrink: 0;
  white-space: nowrap;
}
.ds-alert-banner--warning .ds-alert-banner-link { color: var(--amber); border-color: var(--amber); }
.ds-alert-banner--error   .ds-alert-banner-link { color: var(--coral); border-color: var(--coral); }
.ds-alert-banner--info    .ds-alert-banner-link { color: var(--accent); border-color: var(--accent); }
.ds-alert-banner--warning .ds-alert-banner-link:hover { background: color-mix(in srgb, var(--amber) 12%, transparent); }
.ds-alert-banner--error   .ds-alert-banner-link:hover { background: color-mix(in srgb, var(--coral) 12%, transparent); }
.ds-alert-banner--info    .ds-alert-banner-link:hover { background: color-mix(in srgb, var(--accent) 12%, transparent); }

.ds-alert-banner-close {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border: none;
  background: none;
  border-radius: var(--radius-sm);
  cursor: pointer;
  opacity: 0.7;
  transition: opacity var(--transition), background var(--transition);
  padding: 0;
}
.ds-alert-banner--warning .ds-alert-banner-close { color: var(--amber); }
.ds-alert-banner--error   .ds-alert-banner-close { color: var(--coral); }
.ds-alert-banner--info    .ds-alert-banner-close { color: var(--accent); }
.ds-alert-banner--warning .ds-alert-banner-close:hover { background: color-mix(in srgb, var(--amber) 12%, transparent); }
.ds-alert-banner--error   .ds-alert-banner-close:hover { background: color-mix(in srgb, var(--coral) 12%, transparent); }
.ds-alert-banner--info    .ds-alert-banner-close:hover { background: color-mix(in srgb, var(--accent) 12%, transparent); }
.ds-alert-banner-close:hover { opacity: 1; }
.ds-alert-banner--warning .ds-alert-banner-close:focus-visible { outline: 2px solid var(--amber); outline-offset: 2px; }
.ds-alert-banner--error   .ds-alert-banner-close:focus-visible { outline: 2px solid var(--coral); outline-offset: 2px; }
.ds-alert-banner--info    .ds-alert-banner-close:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

@media (max-width: 600px) {
  .ds-alert-banner {
    flex-wrap: wrap;
    font-size: 0.8rem;
    padding: 0.5rem 0.75rem;
  }
  .ds-alert-banner-text {
    flex: 1 1 100%;
    order: -1;
  }
}
