/* ═══════════════════════════════════════════════════════════════════════════════
 * ViCORE — EIN Overlay-System für Dialoge, Popovers, Menüs und Drawer
 * ───────────────────────────────────────────────────────────────────────────────
 * Bis 21.08.2026 hatte ViCORE vier konkurrierende Pop-up-Welten nebeneinander:
 * das Singleton `#modal-overlay`, 29 handgebaute `.modal-overlay`-Instanzen in
 * app.js, den Modifier `.vi-dlg` (modern, aber nur an 11 Stellen) und acht
 * modul-eigene Dialograhmen. Ergebnis: der Standarddialog war grau statt weiß,
 * hatte KEINE Abdunklung (die Regel in style.css war syntaktisch kaputt), lag mit
 * `z-index: 100` unter jedem Menü und jedem Drawer, und in den Masken standen
 * VIERZEHN verschiedene Feldoptiken mit sieben Fokusringen — zwei davon blau.
 *
 * Diese Datei ist die EINE Optik für alles, was schwebt. Sie definiert KEINE
 * neuen Farben, Größen oder Abstände: jeder Wert kommt aus den kanonischen Tokens
 * in public/css/design-system.css. Eigene Tokens tragen das Präfix `--vdlg-` und
 * sagen damit, wem sie gehören (Regel 1a in scripts/check-design.cjs).
 *
 * VERWENDUNG — ausschließlich über public/vi-dialog.js:
 *     VIDialog.open({ title, size: 'm', bodyHtml, buttons: [...] })
 *     VIDialog.drawer({ title, bodyHtml, buttons: [...] })
 *     VIDialog.menu(anchor, items, 'Weitere Aktionen')     → VIUI.menu
 *     VIDialog.confirm({ ... }) / VIDialog.prompt({ ... })  → viConfirm/viPrompt
 * Kein Modul baut ein eigenes Overlay-Markup. Doku: docs/DIALOG_STANDARD.md
 *
 * WANN WAS (verbindlich, siehe docs/DIALOG_STANDARD.md §2):
 *   Popover  kleine kontextbezogene Entscheidung am Auslöser (Mehr-Menü, Auswahl)
 *   Dialog   fokussierte Eingabe oder Bestätigung (Aufgabe erstellen, Termin)
 *   Drawer   umfangreiche Bearbeitung, bei der der Seitenkontext sichtbar bleibt
 *
 * Die alten Klassen (`.modal-overlay`, `.modal-content`, `.vi-dlg`) bleiben
 * unangetastet — sie tragen 117 Bestandsdialoge. Migration erfolgt Dialog für
 * Dialog auf `.vi-dlg-ov` (CLAUDE.md · UI-Regeln: App-Klassen nie hart überschreiben).
 * ═══════════════════════════════════════════════════════════════════════════════ */

:root {
  /* ── DIE STAPELORDNUNG (verbindlich) ──────────────────────────────────────
     Vorher: ~90 hart kodierte z-index-Werte zwischen 100 und 2147483000, dazu
     eine ungenutzte Token-Skala. Ab hier gibt es EINE Leiter. Wer schwebt,
     nimmt einen dieser Werte — niemand erfindet einen eigenen.
       Inhalt/Sticky      < 100      (unverändert im Bestand)
       Drawer/Sidepanel   4600       über Kontextmenüs und Vorschauen
       Dialog             6000       über dem Drawer, aus dem er geöffnet wird
       Menü/Popover       9000       IMMER über dem Dialog, aus dem es aufklappt
       Tooltip            9600       vi-overlay.css (unverändert)
       Toast              9999       style.css (unverändert)
       Vollbildebene     11000       Kamera (vi-photo.css) — verdeckt die Seite ganz
       Vollbildauswahl   11200       Auswahldialog DIESER Ebene
       Verarbeitung      11500       Uploadstatus — bleibt sichtbar, wenn die Ebene schließt
       Bestätigung       12000       darf über allem liegen, auch über Dialogen
       Auswahlliste      12500       ganz oben — Begründung unten
     Verschachtelte Dialoge erhöht vi-dialog.js je Ebene um 2.

     WARUM DIE AUSWAHLLISTE GANZ OBEN LIEGT: `search-select.js` ersetzt JEDES
     <select> der Anwendung durch ein Popover, das als Portal am <body> hängt.
     Sie gehört damit immer dem gerade fokussierten Feld — und muss über JEDER
     Fläche liegen, die ein Feld enthalten kann. Das ist nicht nur der Dialog:
     auch die Vollbildmaske der mobilen Schnellmeldung (`#tk-mobile-overlay`,
     z 12000) trägt Auswahlfelder. Läge die Liste darunter, wäre das Feld dort
     unbedienbar — das native Aufklappen ist unterdrückt. Der frühere Wert
     2147483000 war die Kapitulation vor einer fehlenden Ordnung; 12500 ist die
     Ordnung. Über 12500 liegen nur Dinge OHNE Eingabefelder (Sprungmarke 14000,
     mobiler Aktionsknopf 13000, Übergangsschleier 13000). */
  --vdlg-z-drawer:  4600;
  --vdlg-z-dialog:  6000;
  --vdlg-z-pop:     9000;
  /* Vollbildebenen (Kamera, public/vi-photo.css): sie ERSETZEN die Seite und
     liegen daher über Dialog und Menü — aber unter der Rückfrage, damit
     „Fotos verwerfen?" auch dort sichtbar bleibt. */
  --vdlg-z-fullscreen: 11000;
  --vdlg-z-fullscreen-sheet: 11200;
  --vdlg-z-progress: 11500;
  --vdlg-z-confirm: 12000;
  --vdlg-z-select:  12500;

  /* ── GRÖSSENSTUFEN statt Pixelbreiten je Modul ───────────────────────────
     S  kurze Bestätigung, ein bis zwei Felder
     M  Standardmaske (Regelfall — CLAUDE.md: „Formular/Modal einspaltig")
     L  Maske mit Nebeninformation (z. B. Aufgabe + Bezug)
     XL nur für Listen/Vergleiche im Dialog; im Zweifel ist es ein Drawer */
  --vdlg-w-s:  440px;
  --vdlg-w-m:  640px;
  --vdlg-w-l:  860px;
  --vdlg-w-xl: 1120px;

  /* ── EIN Abstandsraster für alle Overlays ────────────────────────────────
     Kopf und Fuß tragen dieselbe seitliche Ruhezone wie der Inhalt; nur die
     Höhe unterscheidet sie. Damit steht der Titel exakt über dem ersten Label
     und der Primärknopf exakt unter dem letzten Feld. */
  --vdlg-pad-x:   var(--space-5);
  --vdlg-pad-y:   var(--space-5);
  --vdlg-head-y:  var(--space-4);
  --vdlg-foot-y:  var(--space-3);
  --vdlg-gap:     var(--space-4);   /* zwischen Feldern */
  --vdlg-gap-grp: var(--space-5);   /* zwischen Feldgruppen */
  --vdlg-drawer-w: 460px;
}

/* ═══════════════════════════════════════════════════════════════════════════
   1 · DIALOG
   ═══════════════════════════════════════════════════════════════════════════ */

/* Die Abdunklung. Sie gehört dem Overlay, nicht dem Dialog — deshalb liegt hier
   auch die Zentrierung. `display:none` bis `is-open`: vi-dialog.js hängt das
   Element vor dem Öffnen ein und entfernt es beim Schließen, die Klasse trägt
   nur die Einblendung. */
.vi-dlg-ov {
  position: fixed; inset: 0;
  z-index: var(--vdlg-z-dialog);
  display: flex; align-items: center; justify-content: center;
  padding: var(--space-5) var(--space-4);
  background: var(--bg-overlay);
  opacity: 0;
  transition: opacity 140ms ease;
}
.vi-dlg-ov.is-open { opacity: 1; }

/* Das Dialogfeld. Kopf und Fuß stehen fest, NUR der Body scrollt — das ist die
   Regel gegen die verschachtelten Scrollflächen im Bestand. */
.vi-dlg-panel {
  position: relative;
  display: flex; flex-direction: column;
  width: 100%; max-width: var(--vdlg-w-m);
  max-height: min(88vh, 920px);
  background: var(--color-surface);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-xl);
  overflow: hidden;
  transform: translateY(8px) scale(.99);
  transition: transform 160ms cubic-bezier(.22, .8, .3, 1);
}
.vi-dlg-ov.is-open .vi-dlg-panel { transform: none; }

.vi-dlg-panel.is-s  { max-width: var(--vdlg-w-s); }
.vi-dlg-panel.is-m  { max-width: var(--vdlg-w-m); }
.vi-dlg-panel.is-l  { max-width: var(--vdlg-w-l); }
.vi-dlg-panel.is-xl { max-width: var(--vdlg-w-xl); }

/* ── Kopf ── Titel · optionale Kontextzeile · Schließen ────────────────────
   Kein großer Header: der Titel ist eine Abschnittsüberschrift (17 px), keine
   Seitenüberschrift. Die Kontextzeile trägt WORAN gearbeitet wird (Vorgang,
   Objekt) — nie eine Erklärung, was der Dialog tut (CLAUDE.md · UI-Regeln). */
.vi-dlg-head {
  flex: 0 0 auto;
  display: flex; align-items: flex-start; gap: var(--space-4);
  padding: var(--vdlg-head-y) var(--vdlg-pad-x);
  border-bottom: 1px solid var(--border-subtle);
  background: var(--color-surface);
}
.vi-dlg-headmain { flex: 1 1 auto; min-width: 0; }
.vi-dlg-title {
  margin: 0;
  font-family: var(--font-body);
  font-size: var(--text-lg);
  font-weight: var(--fw-semibold);
  line-height: var(--lh-tight);
  letter-spacing: -.01em;
  color: var(--gray-900);
}
.vi-dlg-sub {
  margin: 3px 0 0;
  font-size: var(--text-sm);
  line-height: var(--lh-snug);
  color: var(--gray-500);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.vi-dlg-x {
  flex: 0 0 auto;
  display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px; margin: -2px -6px 0 0; padding: 0;
  border: none; background: transparent;
  border-radius: var(--radius-md);
  color: var(--gray-500); cursor: pointer;
  transition: background var(--transition), color var(--transition);
}
.vi-dlg-x:hover { background: var(--gray-100); color: var(--gray-900); }
.vi-dlg-x:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.vi-dlg-x svg { display: block; }

/* ── Inhalt ── der EINZIGE Scrollbereich des Dialogs ─────────────────────── */
.vi-dlg-body {
  flex: 1 1 auto; min-height: 0;
  overflow-y: auto; overflow-x: hidden;
  /* Der Platz der Bildlaufleiste wird IMMER freigehalten. Sonst ist der rechte Rand
     eines scrollenden Dialogs ~10 px schmaler als der linke — genau das Bild
     „ungleichmäßige Ränder" (Befund Block 3, §12) — und der Inhalt springt beim
     Wechsel zwischen scrollendem und nicht scrollendem Zustand. */
  scrollbar-gutter: stable both-edges;
  padding: var(--vdlg-pad-y) var(--vdlg-pad-x);
  font-size: var(--text-md);
  color: var(--gray-900);
}
/* Ohne Fußzeile schließt der Inhalt bündig ab. */
.vi-dlg-panel.no-foot .vi-dlg-body { padding-bottom: var(--vdlg-pad-y); }

/* ── Fuß ── Primäraktion rechts, Abbrechen links davon ────────────────────
   Genau EINE Primäraktion. Weitere Wege (z. B. „Löschen") stehen links außen
   über `.vi-dlg-footl` und sind nie primär eingefärbt. */
.vi-dlg-foot {
  flex: 0 0 auto;
  display: flex; align-items: center; justify-content: flex-end;
  gap: var(--space-2);
  padding: var(--vdlg-foot-y) var(--vdlg-pad-x);
  border-top: 1px solid var(--border-subtle);
  background: var(--gray-25);
}
.vi-dlg-footl { margin-right: auto; display: flex; align-items: center; gap: var(--space-2); }

/* Ein Fußzeilen-Knopf, den ein Dialog über `hidden` ausblendet, muss auch
   verschwinden: `.btn { display: inline-flex }` ist Autor-CSS und schlägt das
   UA-`[hidden]` — dieselbe Falle wie bei `.vi-confirm-actions` in components.css. */
.vi-dlg-foot [data-vdlg-btn][hidden] { display: none !important; }

/* Fehlermeldung des Dialogs — immer ganz oben im Body, nie als Toast versteckt. */
.vi-dlg-err {
  display: none;
  margin-bottom: var(--vdlg-gap);
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-md);
  border: 1px solid var(--color-danger);
  background: var(--color-danger-soft);
  color: var(--color-danger-ink);
  font-size: var(--text-sm);
  line-height: var(--lh-snug);
}
.vi-dlg-err.is-on { display: block; }

/* ═══════════════════════════════════════════════════════════════════════════
   2 · DRAWER — dieselbe Hülle, andere Anordnung
   Der Drawer ist kein zweites Dialogsystem: Kopf, Body, Fuß, Feldoptik und
   Tastaturverhalten sind identisch. Er fährt nur von rechts ein und lässt den
   Seitenkontext sichtbar. Die gewachsene `.vi-drawer` (components.css) bleibt
   bestehen; neue Drawer nutzen diese Hülle.
   ═══════════════════════════════════════════════════════════════════════════ */
.vi-dlg-ov.is-drawer {
  z-index: var(--vdlg-z-drawer);
  align-items: stretch; justify-content: flex-end;
  padding: 0;
}
.vi-dlg-ov.is-drawer .vi-dlg-panel {
  width: min(var(--vdlg-drawer-w), 96vw); max-width: none;
  height: 100%; max-height: none;
  border: none; border-left: 1px solid var(--border-subtle);
  border-radius: 0;
  transform: translateX(100%);
  transition: transform 220ms cubic-bezier(.22, .8, .3, 1);
}
.vi-dlg-ov.is-drawer .vi-dlg-panel.is-l  { width: min(640px, 96vw); }
.vi-dlg-ov.is-drawer .vi-dlg-panel.is-xl { width: min(860px, 98vw); }
.vi-dlg-ov.is-drawer.is-open .vi-dlg-panel { transform: none; }

/* Die Bestands-Drawer ziehen mit: EINE Stapelhöhe für alle Sidepanels.
   (Wert weiterhin per Fallback abgesichert, falls diese Datei fehlt.) */
.vi-drawer-ov { z-index: var(--vdlg-z-drawer, 1400); }

/* ═══════════════════════════════════════════════════════════════════════════
   3 · FORMULARFELDER IN OVERLAYS — EINE Optik
   Gilt für Dialog UND Drawer, damit „Aufgabe erstellen" und „Weitere Filter"
   nicht wie zwei Programme aussehen. Bewusst auf Overlays begrenzt: die
   globalen `.form-*`-Regeln tragen hunderte Bestandsmasken und werden nicht
   angefasst (CLAUDE.md · UI-Regeln).
   ═══════════════════════════════════════════════════════════════════════════ */
.vi-dlg-body .form-group,
.vi-dlg-body .vi-fld { margin-bottom: var(--vdlg-gap); }
/* Nur das LETZTE Feld des Dialogkörpers verliert seinen Außenabstand. Die frühere
   Fassung prüfte `:last-child` gegen den jeweiligen Elternknoten — ein Feld, das in
   einem Umschalt-Wrapper steckt (`<div id="vl-n-cp-wrap"><div class="form-group">…`),
   ist dort immer letztes Kind und stand dann ohne Abstand am nächsten Label. */
.vi-dlg-body > .form-group:last-child,
.vi-dlg-body > .vi-fld:last-child,
.vi-dlg-body > .vl-form > .form-group:last-child { margin-bottom: 0; }

/* Feldgruppe = fachlich zusammengehörige Felder mit einer leisen Überschrift. */
.vi-dlg-grp { margin-bottom: var(--vdlg-gap-grp); }
.vi-dlg-grp:last-child { margin-bottom: 0; }
.vi-dlg-grph {
  margin: 0 0 var(--space-3);
  font-size: var(--text-sm);
  font-weight: var(--fw-semibold);
  line-height: var(--lh-snug);
  letter-spacing: 0;
  color: var(--gray-700);
}

/* Zwei Felder nebeneinander — bricht auf schmalen Breiten sauber um. */
.vi-dlg-row {
  display: grid; grid-template-columns: 1fr 1fr; gap: var(--vdlg-gap);
  margin-bottom: var(--vdlg-gap);
}
.vi-dlg-row:last-child { margin-bottom: 0; }
.vi-dlg-row > .form-group,
.vi-dlg-row > .vi-fld { margin-bottom: 0; }
.vi-dlg-row.is-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }

/* Beschriftung: Satzschreibung, kompakt, direkt über dem Feld.
   Die alte Optik (9 px Versalien mit .1em Sperrung) war lauter als der Wert,
   den sie beschriftet — genau das Behördenvordruck-Bild. */
.vi-dlg-body .form-label,
.vi-dlg-body .vi-fld-l {
  display: block;
  margin-bottom: var(--space-1);
  font-family: var(--font-body);
  font-size: var(--text-sm);
  font-weight: var(--fw-medium);
  line-height: var(--lh-snug);
  letter-spacing: 0;
  text-transform: none;
  color: var(--gray-900);
}
/* Pflichtfeld: EIN Zeichen, in Markenfarbe, nie rot (rot heißt Fehler). */
.vi-dlg-body .vi-req { color: var(--color-sage); font-weight: var(--fw-semibold); }

.vi-dlg-body .form-input,
.vi-dlg-body .form-select,
.vi-dlg-body textarea.form-input,
.vi-dlg-body input[type="text"].form-input,
.vi-dlg-body input[type="date"].form-input,
.vi-dlg-body input[type="time"].form-input,
.vi-dlg-body input[type="number"].form-input {
  width: 100%; box-sizing: border-box;
  min-height: var(--ui-field-h);
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--gray-300);
  border-radius: var(--radius-md);
  background: var(--color-surface);
  font-family: var(--font-body);
  font-size: var(--text-md);
  line-height: var(--lh-snug);
  color: var(--gray-900);
  transition: border-color var(--transition), box-shadow var(--transition);
}
.vi-dlg-body textarea.form-input { min-height: 84px; resize: vertical; }
.vi-dlg-body .form-input::placeholder { color: var(--gray-400); }
.vi-dlg-body .form-input:hover:not(:disabled),
.vi-dlg-body .form-select:hover:not(:disabled) { border-color: var(--gray-400); }
/* EIN Fokusring, in der Markenfarbe — nicht sieben, davon zwei blaue. */
.vi-dlg-body .form-input:focus,
.vi-dlg-body .form-select:focus {
  outline: none;
  border-color: var(--color-sage);
  box-shadow: var(--focus-ring);
}
.vi-dlg-body .form-input:disabled,
.vi-dlg-body .form-select:disabled {
  background: var(--gray-100);
  color: var(--gray-600);
  cursor: not-allowed;
}
/* Fehlerzustand: Rahmen + Meldung unter dem Feld. Nie nur Farbe. */
.vi-dlg-body .form-input.is-err,
.vi-dlg-body .form-select.is-err { border-color: var(--color-danger); }
.vi-dlg-body .form-input.is-err:focus,
.vi-dlg-body .form-select.is-err:focus { box-shadow: 0 0 0 3px var(--color-danger-soft); }

.vi-dlg-body .form-hint,
.vi-dlg-body .vi-fld-hint {
  margin-top: var(--space-1);
  font-size: var(--text-xs);
  line-height: var(--lh-snug);
  color: var(--gray-500);
  background: none; padding: 0; border-radius: 0;
}
.vi-dlg-body .vi-fld-err {
  margin-top: var(--space-1);
  font-size: var(--text-xs);
  line-height: var(--lh-snug);
  color: var(--color-danger-ink);
}

/* Kontrollkästchen als ganze Zeile — die Beschriftung ist der Klickbereich. */
.vi-dlg-check {
  display: flex; align-items: flex-start; gap: var(--space-2);
  font-size: var(--text-md);
  line-height: var(--lh-snug);
  color: var(--gray-900);
  cursor: pointer;
}
.vi-dlg-check + .vi-dlg-check { margin-top: var(--space-2); }
.vi-dlg-check input[type="checkbox"] {
  flex: 0 0 auto; width: 16px; height: 16px; margin: 1px 0 0;
  accent-color: var(--color-sage); cursor: pointer;
}
.vi-dlg-check:focus-within { outline: none; }
.vi-dlg-check input[type="checkbox"]:focus-visible { outline: none; box-shadow: var(--focus-ring); border-radius: var(--radius-sm); }
.vi-dlg-check .vi-dlg-checkhint { display: block; font-size: var(--text-xs); color: var(--gray-500); }

/* Schnellwahl neben einem Feld (z. B. Heute · Morgen · Diese Woche).
   Kleine Schalter, kein zweites Button-System: Geometrie aus .btn-sm. */
.vi-dlg-quick { display: flex; flex-wrap: wrap; gap: var(--space-1); margin-top: var(--space-2); }
.vi-dlg-qbtn {
  padding: 3px var(--space-2);
  border: 1px solid var(--gray-300);
  border-radius: var(--radius-pill);
  background: var(--color-surface);
  font-family: var(--font-body);
  font-size: var(--text-xs);
  font-weight: var(--fw-medium);
  line-height: var(--lh-snug);
  color: var(--gray-700);
  cursor: pointer;
  transition: background var(--transition), border-color var(--transition), color var(--transition);
}
.vi-dlg-qbtn:hover { background: var(--gray-50); border-color: var(--gray-400); color: var(--gray-900); }
.vi-dlg-qbtn.is-on { background: var(--color-sage-soft); border-color: var(--color-sage); color: var(--color-forest); }
.vi-dlg-qbtn:focus-visible { outline: none; box-shadow: var(--focus-ring); }

/* ═══════════════════════════════════════════════════════════════════════════
   4 · BEZUGSBLOCK — „woraus ist das entstanden?"
   Eine ruhige Fläche, kein zweiter Kasten im Kasten: linker Markenstrich statt
   Rahmen, damit die Maske EIN Blatt bleibt. Trägt ausschließlich Metadaten der
   Quelle — der Inhalt der Quelle gehört in die Quelle, nicht in die Aufgabe.
   ═══════════════════════════════════════════════════════════════════════════ */
.vi-dlg-src {
  display: flex; align-items: flex-start; gap: var(--space-3);
  padding: var(--space-3);
  border-radius: var(--radius-md);
  background: var(--gray-50);
  box-shadow: inset 2px 0 0 var(--color-sage);
}
.vi-dlg-srcmain { flex: 1 1 auto; min-width: 0; }
.vi-dlg-srck {
  display: block;
  font-size: var(--text-xs);
  font-weight: var(--fw-semibold);
  letter-spacing: 0;
  color: var(--gray-500);
}
.vi-dlg-srct {
  display: block; margin-top: 2px;
  font-size: var(--text-md);
  font-weight: var(--fw-medium);
  line-height: var(--lh-snug);
  color: var(--gray-900);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.vi-dlg-srcm {
  display: block; margin-top: 2px;
  font-size: var(--text-sm);
  line-height: var(--lh-snug);
  color: var(--gray-500);
}
/* Vorschau: höchstens zwei Zeilen. Wer mehr braucht, öffnet die Quelle. */
.vi-dlg-srcp {
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
  margin-top: var(--space-2);
  font-size: var(--text-sm);
  line-height: var(--lh-normal);
  color: var(--gray-700);
}
.vi-dlg-srca { flex: 0 0 auto; }

/* ═══════════════════════════════════════════════════════════════════════════
   5 · RESPONSIV — schmale Breiten sind kein Sonderfall
   ≤ 640 px wird der Dialog zum Sheet: volle Breite, unten angedockt, Fuß immer
   erreichbar (safe-area beachtet). Nichts wird abgeschnitten, nichts scrollt
   waagerecht.
   ═══════════════════════════════════════════════════════════════════════════ */
@media (max-width: 640px) {
  .vi-dlg-ov { padding: 0; align-items: flex-end; }
  .vi-dlg-panel,
  .vi-dlg-panel.is-s, .vi-dlg-panel.is-m, .vi-dlg-panel.is-l, .vi-dlg-panel.is-xl {
    width: 100%; max-width: none;
    /* `dvh` folgt der ein-/ausfahrenden Browserleiste; `vh` bleibt als Fallback
       für ältere Engines stehen (die zweite Deklaration gewinnt, wo sie gilt). */
    max-height: 92vh; max-height: 92dvh;
    border-radius: var(--radius-xl) var(--radius-xl) 0 0;
    border-left: none; border-right: none; border-bottom: none;
    transform: translateY(16px);
  }
  .vi-dlg-head { padding: var(--space-3) var(--space-4); }
  .vi-dlg-body { padding: var(--space-4); }
  .vi-dlg-foot {
    flex-direction: column-reverse; align-items: stretch;
    gap: var(--space-2);
    padding: var(--space-3) var(--space-4) calc(var(--space-3) + var(--app-safe-bottom));
  }
  .vi-dlg-foot .btn-primary,
  .vi-dlg-foot .btn-secondary,
  .vi-dlg-foot .btn-ghost,
  .vi-dlg-foot .btn-danger { width: 100%; justify-content: center; }
  .vi-dlg-footl { margin-right: 0; }
  .vi-dlg-row, .vi-dlg-row.is-3 { grid-template-columns: 1fr; }
  .vi-dlg-ov.is-drawer .vi-dlg-panel,
  .vi-dlg-ov.is-drawer .vi-dlg-panel.is-l,
  .vi-dlg-ov.is-drawer .vi-dlg-panel.is-xl {
    width: 100vw; height: 100%; max-height: none; border-radius: 0; transform: translateX(100%);
  }
  /* ── DER GEÖFFNETE ZUSTAND MUSS AUCH HIER GEWINNEN ────────────────────────
     Für den DIALOG ging das schon vorher auf: `.vi-dlg-ov.is-open .vi-dlg-panel`
     (drei Klassen) schlägt `.vi-dlg-panel.is-m` (zwei Klassen).
     Für den DRAWER nicht: `.vi-dlg-ov.is-drawer .vi-dlg-panel.is-l` hat VIER
     Klassen — genauso viele wie `.vi-dlg-ov.is-drawer.is-open .vi-dlg-panel` —
     und steht später in der Datei. Ein großer Drawer (Größe l/xl) blieb auf
     Mobilgeräten deshalb vollständig außerhalb des Bildschirms (translateX(100%)):
     sichtbar war nur die Abdunklung, die Aktionen waren nicht erreichbar
     (Block 3, §18). Diese Zeilen setzen den geöffneten Zustand für beide Formen
     ausdrücklich durch, statt auf Spezifitätsglück zu bauen. */
  .vi-dlg-ov.is-open .vi-dlg-panel,
  .vi-dlg-ov.is-open .vi-dlg-panel.is-s,
  .vi-dlg-ov.is-open .vi-dlg-panel.is-m,
  .vi-dlg-ov.is-open .vi-dlg-panel.is-l,
  .vi-dlg-ov.is-open .vi-dlg-panel.is-xl,
  .vi-dlg-ov.is-drawer.is-open .vi-dlg-panel,
  .vi-dlg-ov.is-drawer.is-open .vi-dlg-panel.is-l,
  .vi-dlg-ov.is-drawer.is-open .vi-dlg-panel.is-xl { transform: none; }
  .vi-dlg-src { flex-direction: column; gap: var(--space-2); }
  .vi-dlg-srca { width: 100%; }
  .vi-dlg-srca .btn-ghost { width: 100%; justify-content: center; }
}

/* Die Seite hinter dem Overlay wird festgehalten. In ViCORE scrollt NICHT das
   <body>, sondern `.content.page.active` — vi-dialog.js sperrt deshalb die
   tatsächlich scrollende Fläche und ersetzt die Breite ihrer Bildlaufleiste als
   Innenabstand (kein Layoutsprung). Diese Klasse ist die Markierung dafür und
   hält zusätzlich Seiten fest, deren <body> selbst scrollt (Vorschauen, Login). */
body.vi-dlg-lock { overflow: hidden; }
/* Berührung: auf Touchgeräten scrollt sonst die Fläche unter dem Sheet weiter. */
body.vi-dlg-lock .content { overscroll-behavior: contain; }

@media (prefers-reduced-motion: reduce) {
  .vi-dlg-ov, .vi-dlg-panel { transition: none; }
  .vi-dlg-panel { transform: none; }
}
