/*!
 * kiez.dev Design-System -- verbindliche Klassen-Grundlage für jedes UI
 * in diesem Projekt (Kern, Admin-Shell, alle Module). Framework-frei,
 * kein Build-Schritt, kein JS-Framework nötig.
 *
 * Datei liegt unter public_html/assets/core/css/design-system.css und wird
 * über /assets/core/css/design-system.css eingebunden:
 *   <link rel="stylesheet" href="/assets/core/css/design-system.css">
 * Referenz dazu in PROJECT.md Sec9. Vorgabe: keine Ad-hoc-Styles oder
 * andere CSS-Frameworks parallel einsetzen, sondern diese Klassen nutzen
 * bzw. bei Bedarf hier zentral erweitern (eine Aufgabe, eine Stelle).
 * Keine style="..."-Attribute für feste Werte und keine <style>-Blöcke in
 * Views. Welche Klasse wofür gilt, Seitenaufbau, Abschnittsabstände und
 * Menüregeln stehen in DESIGN_SYSTEM.md im Projektwurzelverzeichnis; neue
 * Klassen werden dort im selben Commit nachgetragen.
 *
 * Erfordert im <head> jeder Seite (sonst greifen die Responsive-Regeln
 * unten nicht):
 *   <meta name="viewport" content="width=device-width, initial-scale=1">
 *
 * Theme switching:
 *   - Follows OS preference automatically (prefers-color-scheme).
 *   - Force a theme by setting data-theme="light" or "dark" on <html>.
 *   - Prefix: all classes use "d2-" to avoid collisions with other systems.
 *
 * Responsive:
 *   - Mobile-first. Basis-Styles gelten für schmale Viewports, @media
 *     (min-width: ...) erweitert nach oben.
 *   - Breakpoint-Skala (Referenzwerte, in @media direkt als px verwendet,
 *     da CSS Custom Properties in Media-Feature-Werten nicht auswertbar sind):
 *       sm: 480px   -- sehr schmale Screens (Handy hochkant)
 *       md: 768px   -- Tablet / Handy quer
 *       lg: 1024px  -- kleines Notebook
 *       xl: 1280px  -- Desktop
 *   - Siehe Abschnitt 19 für die konkreten Responsive-Anpassungen und
 *     Sichtbarkeits-Hilfsklassen (d2-hide-mobile / d2-hide-desktop).
 */

/* ==========================================================================
   1. Design tokens
   ========================================================================== */

:root {
  /* Font stacks */
  --d2-font-sans: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --d2-font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;

  /* Radius scale */
  --d2-radius: 0.5rem;
  --d2-radius-sm: calc(var(--d2-radius) - 4px);
  --d2-radius-md: calc(var(--d2-radius) - 2px);
  --d2-radius-lg: var(--d2-radius);
  --d2-radius-xl: calc(var(--d2-radius) + 4px);
  --d2-radius-pill: 9999px;

  /* Spacing scale */
  --d2-space-1: 4px;
  --d2-space-2: 8px;
  --d2-space-3: 12px;
  --d2-space-4: 16px;
  --d2-space-5: 20px;
  --d2-space-6: 24px;
  --d2-space-7: 32px;
  --d2-space-8: 40px;

  /* Shadows */
  --d2-shadow-sm: 0 1px 2px hsl(220 20% 10% / 0.06);
  --d2-shadow: 0 1px 3px hsl(220 20% 10% / 0.10), 0 1px 2px hsl(220 20% 10% / 0.06);
  --d2-shadow-lg: 0 10px 30px hsl(220 20% 10% / 0.16), 0 4px 10px hsl(220 20% 10% / 0.08);

  /* Transition timing */
  --d2-ease: cubic-bezier(0.4, 0, 0.2, 1);
  --d2-fast: 120ms;
  --d2-slow: 220ms;

  /* Color tokens — light (values as "H S% L%" so hsl(var(--x)) works) */
  --d2-background: 0 0% 100%;
  --d2-foreground: 222 47% 11%;
  --d2-card: 0 0% 100%;
  --d2-card-foreground: 222 47% 11%;
  --d2-popover: 0 0% 100%;
  --d2-popover-foreground: 222 47% 11%;

  --d2-primary: 221 83% 53%;
  --d2-primary-foreground: 210 40% 98%;
  --d2-secondary: 210 40% 96%;
  --d2-secondary-foreground: 222 47% 11%;
  --d2-muted: 210 40% 96%;
  --d2-muted-foreground: 215 16% 47%;
  --d2-accent: 210 40% 94%;
  --d2-accent-foreground: 222 47% 11%;

  --d2-destructive: 0 84% 60%;
  --d2-destructive-foreground: 210 40% 98%;
  --d2-success: 142 71% 35%;
  --d2-success-foreground: 210 40% 98%;
  --d2-warning: 32 95% 44%;
  --d2-warning-foreground: 210 40% 98%;
  --d2-info: 199 89% 48%;
  --d2-info-foreground: 210 40% 98%;

  --d2-border: 214 32% 91%;
  --d2-input: 214 32% 91%;
  --d2-ring: 221 83% 53%;

  --d2-sidebar: 0 0% 98%;
  --d2-sidebar-foreground: 240 5% 26%;
  --d2-sidebar-primary: 221 83% 53%;
  --d2-sidebar-primary-foreground: 210 40% 98%;
  --d2-sidebar-accent: 240 5% 96%;
  --d2-sidebar-accent-foreground: 240 6% 10%;
  --d2-sidebar-border: 220 13% 91%;
}

/* Dark theme — follows OS setting automatically; a manual override wins
   in either direction via data-theme="dark" / data-theme="light" on <html>. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;
    --d2-background: 214 61% 17%;
    --d2-foreground: 210 40% 98%;
    --d2-card: 214 55% 20%;
    --d2-card-foreground: 210 40% 98%;
    --d2-popover: 214 55% 20%;
    --d2-popover-foreground: 210 40% 98%;

    --d2-primary: 217 91% 60%;
    --d2-primary-foreground: 222 47% 11%;
    --d2-secondary: 214 50% 23%;
    --d2-secondary-foreground: 210 40% 98%;
    --d2-muted: 214 50% 23%;
    --d2-muted-foreground: 215 20% 68%;
    --d2-accent: 214 50% 26%;
    --d2-accent-foreground: 210 40% 98%;

    --d2-destructive: 0 91% 71%;
    --d2-destructive-foreground: 222 47% 11%;
    --d2-success: 142 69% 58%;
    --d2-success-foreground: 222 47% 11%;
    --d2-warning: 38 92% 60%;
    --d2-warning-foreground: 222 47% 11%;
    --d2-info: 199 89% 65%;
    --d2-info-foreground: 222 47% 11%;

    --d2-border: 214 50% 27%;
    --d2-input: 214 50% 27%;
    --d2-ring: 217 91% 60%;

    --d2-sidebar: 214 50% 15%;
    --d2-sidebar-foreground: 210 40% 98%;
    --d2-sidebar-primary: 217 91% 60%;
    --d2-sidebar-primary-foreground: 222 47% 11%;
    --d2-sidebar-accent: 214 50% 20%;
    --d2-sidebar-accent-foreground: 210 40% 98%;
    --d2-sidebar-border: 214 50% 24%;
  }

  :root:not([data-theme="light"]) .d2-score-cell--1 { background: hsl(0 45% 28%); color: hsl(0 70% 88%); }
  :root:not([data-theme="light"]) .d2-score-cell--2 { background: hsl(28 45% 28%); color: hsl(28 70% 88%); }
  :root:not([data-theme="light"]) .d2-score-cell--3 { background: hsl(48 40% 26%); color: hsl(48 70% 85%); }
  :root:not([data-theme="light"]) .d2-score-cell--4 { background: hsl(85 35% 24%); color: hsl(85 55% 85%); }
  :root:not([data-theme="light"]) .d2-score-cell--5 { background: hsl(135 35% 22%); color: hsl(135 55% 85%); }
}

:root[data-theme="dark"] {
  color-scheme: dark;
  --d2-background: 214 61% 17%;
  --d2-foreground: 210 40% 98%;
  --d2-card: 214 55% 20%;
  --d2-card-foreground: 210 40% 98%;
  --d2-popover: 214 55% 20%;
  --d2-popover-foreground: 210 40% 98%;

  --d2-primary: 217 91% 60%;
  --d2-primary-foreground: 222 47% 11%;
  --d2-secondary: 214 50% 23%;
  --d2-secondary-foreground: 210 40% 98%;
  --d2-muted: 214 50% 23%;
  --d2-muted-foreground: 215 20% 68%;
  --d2-accent: 214 50% 26%;
  --d2-accent-foreground: 210 40% 98%;

  --d2-destructive: 0 91% 71%;
  --d2-destructive-foreground: 222 47% 11%;
  --d2-success: 142 69% 58%;
  --d2-success-foreground: 222 47% 11%;
  --d2-warning: 38 92% 60%;
  --d2-warning-foreground: 222 47% 11%;
  --d2-info: 199 89% 65%;
  --d2-info-foreground: 222 47% 11%;

  --d2-border: 214 50% 27%;
  --d2-input: 214 50% 27%;
  --d2-ring: 217 91% 60%;

  --d2-sidebar: 214 50% 15%;
  --d2-sidebar-foreground: 210 40% 98%;
  --d2-sidebar-primary: 217 91% 60%;
  --d2-sidebar-primary-foreground: 222 47% 11%;
  --d2-sidebar-accent: 214 50% 20%;
  --d2-sidebar-accent-foreground: 210 40% 98%;
  --d2-sidebar-border: 214 50% 24%;
}

:root[data-theme="dark"] .d2-score-cell--1 { background: hsl(0 45% 28%); color: hsl(0 70% 88%); }
:root[data-theme="dark"] .d2-score-cell--2 { background: hsl(28 45% 28%); color: hsl(28 70% 88%); }
:root[data-theme="dark"] .d2-score-cell--3 { background: hsl(48 40% 26%); color: hsl(48 70% 85%); }
:root[data-theme="dark"] .d2-score-cell--4 { background: hsl(85 35% 24%); color: hsl(85 55% 85%); }
:root[data-theme="dark"] .d2-score-cell--5 { background: hsl(135 35% 22%); color: hsl(135 55% 85%); }

:root[data-theme="light"] { color-scheme: light; }

/* ==========================================================================
   2. Reset & base elements
   ========================================================================== */

*, *::before, *::after { box-sizing: border-box; }

/* Inline-SVGs erhalten sonst per Default vertical-align:baseline, was Platz
   für Textunterlängen unterhalb des Icons reserviert -- das macht das Icon
   optisch höher als eigentlich vorgesehen, sichtbar z.B. in schmalen
   Icon-Buttons wie dem Theme-Umschalter. */
svg { vertical-align: middle; }

html {
  font-size: 16px;
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  font-family: var(--d2-font-sans);
  background: hsl(var(--d2-background));
  color: hsl(var(--d2-foreground));
  line-height: 1.5;
}

h1, h2, h3, h4, h5, h6 {
  margin: 0 0 var(--d2-space-3);
  font-weight: 600;
  line-height: 1.25;
}
h1 { font-size: 1.6rem; }
h2 { font-size: 1.3rem; }
h3 { font-size: 1.15rem; }
h4 { font-size: 1.05rem; }
h5 { font-size: 1rem; }
h6 { font-size: 0.9rem; }
@media (min-width: 480px) {
  h1 { font-size: 2rem; }
  h2 { font-size: 1.5rem; }
  h3 { font-size: 1.25rem; }
  h4 { font-size: 1.1rem; }
}

p { margin: 0 0 var(--d2-space-3); }
p:last-child { margin-bottom: 0; }

/* Projektweiter Standard für Links: Hervorhebung per Hintergrundfarbe statt
   Unterstreichung. Zentral hier definiert statt pro Stelle wiederholt, damit
   jeder <a> im Projekt automatisch dasselbe Hover-Verhalten bekommt --
   spezialisierte Elemente wie .d2-btn--link (kein <a>, siehe unten) oder
   .d2-navbar__dropdown > summary brauchen eine eigene, gleichlautende Regel. */
a {
  color: hsl(var(--d2-primary));
  text-decoration: none;
  border-radius: var(--d2-radius-sm);
}
a:hover { background: hsl(var(--d2-muted)); text-decoration: none; }

small, .d2-text-sm { font-size: 0.875rem; }
.d2-text-lg { font-size: 1.125rem; }
.d2-text-muted { color: hsl(var(--d2-muted-foreground)); }
.d2-lede { color: hsl(var(--d2-muted-foreground)); font-size: 1.05rem; }

.d2-code, code {
  font-family: var(--d2-font-mono);
  font-size: 0.9em;
  background: hsl(var(--d2-muted));
  padding: 0.15em 0.4em;
  border-radius: var(--d2-radius-sm);
}
pre {
  font-family: var(--d2-font-mono);
  background: hsl(var(--d2-muted));
  padding: var(--d2-space-4);
  border-radius: var(--d2-radius-md);
  overflow-x: auto;
}
pre code { background: none; padding: 0; }

kbd, .d2-kbd {
  font-family: var(--d2-font-mono);
  font-size: 0.85em;
  background: hsl(var(--d2-muted));
  border: 1px solid hsl(var(--d2-border));
  border-bottom-width: 2px;
  border-radius: var(--d2-radius-sm);
  padding: 0.1em 0.5em;
}

blockquote {
  margin: 0 0 var(--d2-space-3);
  padding-left: var(--d2-space-4);
  border-left: 3px solid hsl(var(--d2-border));
  color: hsl(var(--d2-muted-foreground));
}

hr, .d2-separator {
  border: none;
  border-top: 1px solid hsl(var(--d2-border));
  margin: var(--d2-space-4) 0;
}
.d2-separator--vertical {
  border-top: none;
  border-left: 1px solid hsl(var(--d2-border));
  height: auto;
  align-self: stretch;
  margin: 0 var(--d2-space-3);
}

ul, ol { margin: 0 0 var(--d2-space-3); padding-left: 1.4em; }

img, svg, video { max-width: 100%; }

button, input, textarea, select { font: inherit; color: inherit; }

::selection { background: hsl(var(--d2-primary) / 0.25); }

/* Scrollbar theming — Firefox via standard props, WebKit via pseudo-elements */
* {
  scrollbar-width: thin;
  scrollbar-color: hsl(var(--d2-muted-foreground) / 0.4) transparent;
}
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
  background: hsl(var(--d2-muted-foreground) / 0.4);
  border-radius: var(--d2-radius-pill);
  border: 2px solid hsl(var(--d2-background));
  background-clip: padding-box;
}
::-webkit-scrollbar-thumb:hover { background: hsl(var(--d2-muted-foreground) / 0.6); }

.d2-focus-ring:focus-visible,
.d2-btn:focus-visible,
.d2-input:focus-visible,
.d2-textarea:focus-visible,
.d2-select:focus-visible {
  outline: 2px solid hsl(var(--d2-ring));
  outline-offset: 2px;
}

/* ==========================================================================
   3. Layout helpers
   ========================================================================== */

.d2-container {
  width: 100%;
  max-width: 1120px;
  margin-inline: auto;
  padding-inline: var(--d2-space-4);
}
@media (min-width: 768px) {
  .d2-container { padding-inline: var(--d2-space-5); }
}
@media (min-width: 1024px) {
  .d2-container { padding-inline: var(--d2-space-6); }
}

/* Zentriert Auth-Seiten (Login, Registrierung, ...) vertikal und horizontal,
   responsive über die volle Viewport-Höhe -- dvh statt vh, damit mobile
   Browser-UI-Leisten die Zentrierung nicht verschieben. */
.d2-auth-shell {
  min-height: 100vh;
  min-height: 100dvh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--d2-space-4);
}

.d2-stack { display: flex; flex-direction: column; gap: var(--d2-space-3); }
.d2-cluster { display: flex; flex-wrap: wrap; align-items: center; gap: var(--d2-space-2); }

/* Dashboard-Verwaltung: Zeile aus Checkbox+Label (links) und
   Vollflächig/Spalte/Position (rechts, siehe dashboard-verwaltung/index.php).
   Bei langen Widget-Bezeichnungen (z.B. "Eigene Betreute: Letzte
   Dokumentation") würde die rechte Gruppe sonst ab einer bestimmten Breite
   komplett in eine eigene Zeile umbrechen -- und landet dort wegen
   justify-content:space-between mit nur einem Element in der Zeile links
   statt wie gewohnt rechts (space-between wird bei einem Element zu
   flex-start). Ab 600px bleiben beide Spalten nebeneinander, das Label
   bricht stattdessen selbst um. Darunter (mobil) bleibt das normale
   Untereinander-Verhalten von .d2-cluster, weil sonst die rechte Gruppe
   nicht mehr schrumpft und den Text überlappt. */
@media (min-width: 600px) {
  .d2-widget-zeile { flex-wrap: nowrap; }
  .d2-widget-zeile > label { flex: 1 1 auto; min-width: 0; }
}
.d2-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: var(--d2-space-4);
}
.d2-flex-between { display: flex; align-items: center; justify-content: space-between; gap: var(--d2-space-3); }

/* Dashboard-Raster (app/Admin/views/dashboard.php): ab md 12 Spalten und
   feine Zeilen fester Höhe, jede Kachel --breite Spalten breit und --hoehe
   Zeilen hoch (Werte aus der Datenbank, inline gesetzt), Reihenfolge exakt
   wie angeordnet. Die feste Zeilenhöhe macht die Höhe erst wirksam; was
   nicht hineinpasst, scrollt innerhalb der Karte. Auf dem Handy bestimmt
   der Inhalt die Höhe. Spaltenzahl muss zu AdminSupport::DASHBOARD_SPALTEN
   passen. */
.d2-dashboard-grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--d2-space-4); align-items: start; }
.d2-dashboard-karte { min-width: 0; }
@media (min-width: 768px) {
  .d2-dashboard-grid { grid-template-columns: repeat(12, minmax(0, 1fr)); grid-auto-rows: 2rem; align-items: stretch; }
  .d2-dashboard-karte { display: flex; flex-direction: column; min-height: 0; grid-column: span var(--breite, 4); grid-row: span var(--hoehe, 4); }
  .d2-dashboard-karte > .d2-card, .d2-dashboard-karte > .d2-dashboard-leerfeld { flex: 1 1 auto; min-height: 0; overflow: auto; }
  /* Inhalt füllt die Kachel: Tabellen scrollen in ihrem eigenen Rahmen
     (Überschrift bleibt stehen), .d2-dashboard-fuellraster nimmt die
     restliche Höhe ein und wird per Script passend angeordnet. */
  .d2-dashboard-karte > .d2-card { display: flex; flex-direction: column; }
  .d2-dashboard-karte .d2-card__content { flex: 1 1 auto; display: flex; flex-direction: column; min-height: 0; }
  .d2-dashboard-karte .d2-table-wrap { flex: 0 1 auto; min-height: 0; overflow: auto; }
  .d2-dashboard-karte .d2-dashboard-fuellraster { flex: 1 1 0; min-height: 0; }
  /* Rasterhilfe im Anordnen-Modus: Spalten als Streifen, Zeilen als
     Linien, jeweils mit derselben Schrittweite wie das Raster. */
  .d2-dashboard-grid--anordnen {
    background-image:
      linear-gradient(to right, hsl(var(--d2-muted) / 0.5) calc(100% - var(--d2-space-4)), transparent 0),
      linear-gradient(to bottom, hsl(var(--d2-border)) 1px, transparent 0);
    background-size: calc((100% + var(--d2-space-4)) / 12) 100%, 100% calc(2rem + var(--d2-space-4));
  }
  .d2-dashboard-grid--anordnen .d2-dashboard-karte__ziehgriff { display: block; }
}
/* Grafische Elemente einer Kachel (z.B. Status-Quadrate): das Script in
   dashboard.php wählt Spaltenzahl und Kantenlänge so, dass alle Elemente
   ohne Scrollen möglichst groß in die Kachel passen, und setzt dafür
   --spalten und --groesse. Bis dahin (und ohne Script) gilt das eigene
   Layout des Widgets. */
/* Doppelte Klasse: schlägt das eigene Layout, das Widgets per <style> im
   Kartenhtml mitbringen (steht später im Dokument). */
.d2-dashboard-fuellraster.d2-dashboard-fuellraster--berechnet {
  display: grid;
  grid-template-columns: repeat(var(--spalten), var(--groesse));
  grid-auto-rows: var(--groesse);
  align-content: center;
}
.d2-dashboard-fuellraster.d2-dashboard-fuellraster--berechnet > * { width: 100%; height: 100%; min-width: 0; }

/* Leerfeld: hält Platz frei, sichtbar nur im Anordnen-Modus. Die
   Mindesthöhe sorgt dafür, dass auch eine Zeile nur aus Leerfeldern als
   Abstand stehen bleibt. Auf dem Handy (eine Spalte) wäre es nur Leerraum. */
.d2-dashboard-leerfeld {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 6rem;
  border-radius: var(--d2-radius);
  color: hsl(var(--d2-muted-foreground));
  visibility: hidden;
}
.d2-dashboard-grid--anordnen .d2-dashboard-leerfeld { visibility: visible; outline: 2px dashed hsl(var(--d2-border)); outline-offset: 2px; }
@media (max-width: 767.98px) {
  .d2-dashboard-grid:not(.d2-dashboard-grid--anordnen) .d2-dashboard-karte--leer { display: none; }
}
/* Anordnen-Modus: Werkzeugleiste über jeder Karte, gestrichelter Rahmen,
   gezogene Karte halb transparent. touch-action am Griff verhindert, dass
   der Finger beim Ziehen stattdessen die Seite scrollt. */
.d2-dashboard-karte__werkzeuge { display: none; }
.d2-dashboard-grid--anordnen { user-select: none; }
.d2-dashboard-grid--anordnen .d2-dashboard-karte__werkzeuge {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--d2-space-1);
  margin-bottom: var(--d2-space-1);
}
.d2-dashboard-grid--anordnen .d2-dashboard-karte > .d2-card { outline: 2px dashed hsl(var(--d2-border)); outline-offset: 2px; }
.d2-dashboard-karte__griff {
  height: 1.875rem;
  padding: 0 var(--d2-space-2);
  border: 1px solid hsl(var(--d2-border));
  border-radius: var(--d2-radius-sm);
  background: hsl(var(--d2-card));
  color: hsl(var(--d2-muted-foreground));
  font-size: 1rem;
  cursor: grab;
  touch-action: none;
}
.d2-dashboard-karte__masse { margin-left: auto; font-variant-numeric: tabular-nums; }
/* Anfasser zum Größe ändern, unten rechts auf der Kachel, nur im
   Anordnen-Modus ab md (auf dem Handy gibt es keine Breite/Höhe). */
.d2-dashboard-karte { position: relative; }
.d2-dashboard-karte__ziehgriff {
  display: none;
  position: absolute;
  right: -6px;
  bottom: -6px;
  width: 22px;
  height: 22px;
  padding: 0;
  border: 2px solid hsl(var(--d2-background));
  border-radius: 50%;
  background: hsl(var(--d2-primary));
  cursor: nwse-resize;
  touch-action: none;
  z-index: 1;
}
.d2-dashboard-karte--skaliert > .d2-card, .d2-dashboard-karte--skaliert > .d2-dashboard-leerfeld { outline-color: hsl(var(--d2-primary)); }
.d2-dashboard-karte--gezogen { opacity: 0.5; }
.d2-dashboard-karte--gezogen .d2-dashboard-karte__griff { cursor: grabbing; }

/* ==========================================================================
   3b. Seitenaufbau und Abschnitte (Regeln siehe DESIGN_SYSTEM.md)
   Reihenfolge einer Admin-Seite: Subnav, .d2-back-link, h1, Abschnitte.
   Abstand zwischen Abschnitten (Card, Alert, Tabelle, Raster) ist immer
   .d2-section (16px), ein neuer Hauptbereich mit h2 beginnt mit
   .d2-section-title (24px). Innerhalb eines Abschnitts gelten die
   Abstands-Hilfsklassen aus Abschnitt 24.
   ========================================================================== */

.d2-main { padding-block: var(--d2-space-6); }
.d2-section { margin-top: var(--d2-space-4); }
.d2-section-title { margin-top: var(--d2-space-6); }
.d2-back-link { display: inline-block; margin-bottom: var(--d2-space-4); }
/* Schmale Inhaltsspalte für Formularseiten (480px) bzw. Detail- und
   Einstellungsseiten (640px), zentriert im .d2-container. */
.d2-page-narrow { max-width: 480px; margin: 0 auto; }
.d2-page-medium { max-width: 640px; margin: 0 auto; }
/* Anmelde-, Registrierungs- und Passwortseiten. */
.d2-container--auth { max-width: 380px; }

/* ==========================================================================
   4. Buttons
   ========================================================================== */

.d2-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  gap: var(--d2-space-2);
  height: 2.25rem;
  padding: 0 var(--d2-space-4);
  border-radius: var(--d2-radius-md);
  border: 1px solid transparent;
  font-size: 0.875rem;
  font-weight: 500;
  white-space: nowrap;
  cursor: pointer;
  transition: background-color var(--d2-fast) var(--d2-ease), border-color var(--d2-fast) var(--d2-ease), opacity var(--d2-fast) var(--d2-ease);
  background: hsl(var(--d2-primary));
  color: hsl(var(--d2-primary-foreground));
}
.d2-btn:hover { opacity: 0.9; }
.d2-btn:active { opacity: 0.8; }
.d2-btn:disabled, .d2-btn[aria-disabled="true"] {
  opacity: 0.5;
  cursor: not-allowed;
}

.d2-btn--secondary {
  background: hsl(var(--d2-secondary));
  color: hsl(var(--d2-secondary-foreground));
}
.d2-btn--outline {
  background: transparent;
  border-color: hsl(var(--d2-border));
  color: hsl(var(--d2-foreground));
}
.d2-btn--outline:hover { background: hsl(var(--d2-accent)); opacity: 1; }
.d2-btn--ghost {
  background: transparent;
  color: hsl(var(--d2-foreground));
}
.d2-btn--ghost:hover { background: hsl(var(--d2-accent)); opacity: 1; }
/* Kurze Bestätigung nach einer Aktion (z.B. Kopieren), per JS gesetzt und wieder entfernt. */
.d2-btn--bestaetigt, .d2-btn--bestaetigt:hover { background: hsl(var(--d2-success) / 0.15); color: hsl(var(--d2-success)); }
.d2-btn--destructive {
  background: hsl(var(--d2-destructive));
  color: hsl(var(--d2-destructive-foreground));
}
.d2-btn--success {
  background: hsl(var(--d2-success));
  color: hsl(var(--d2-success-foreground));
}
.d2-btn--link {
  background: transparent;
  color: hsl(var(--d2-primary));
  height: auto;
  padding: var(--d2-space-1) var(--d2-space-2);
}
.d2-btn--link:hover { background: hsl(var(--d2-muted)); text-decoration: none; opacity: 1; }
/* Link-Button ohne Innenabstand, z.B. "Bearbeiten" direkt im Fließtext. */
.d2-btn--bare { padding: 0; height: auto; }

.d2-btn--sm { height: 1.875rem; padding: 0 var(--d2-space-3); font-size: 0.8rem; }
.d2-btn--lg { height: 2.75rem; padding: 0 var(--d2-space-5); font-size: 0.95rem; }
.d2-btn--icon { width: 2.25rem; height: 2.25rem; padding: 0; }
/* .d2-btn--icon setzt Breite/Höhe/Padding fix und gewinnt dabei laut
   Quellreihenfolge über .d2-btn--sm/--lg, auch wenn beide zusammen auf einem
   Button stehen (z.B. Theme-Umschalter) -- ohne diese Regel bliebe die
   Kombination bei der vollen 2.25rem-Standardgröße hängen statt kleiner/
   größer zu werden, wie die jeweilige Zusatzklasse eigentlich vorgibt. */
.d2-btn--icon.d2-btn--sm { width: 1.875rem; height: 1.875rem; }
.d2-btn--icon.d2-btn--lg { width: 2.75rem; height: 2.75rem; }
.d2-btn--block { width: 100%; }

.d2-btn-group { display: inline-flex; }
.d2-btn-group .d2-btn { border-radius: 0; margin-left: -1px; }
.d2-btn-group .d2-btn:first-child { border-top-left-radius: var(--d2-radius-md); border-bottom-left-radius: var(--d2-radius-md); margin-left: 0; }
.d2-btn-group .d2-btn:last-child { border-top-right-radius: var(--d2-radius-md); border-bottom-right-radius: var(--d2-radius-md); }

@media (max-width: 479px) {
  .d2-btn-group { flex-direction: column; width: 100%; }
  .d2-btn-group .d2-btn { width: 100%; margin-left: 0; margin-top: -1px; border-radius: 0; }
  .d2-btn-group .d2-btn:first-child { border-radius: var(--d2-radius-md) var(--d2-radius-md) 0 0; margin-top: 0; }
  .d2-btn-group .d2-btn:last-child { border-radius: 0 0 var(--d2-radius-md) var(--d2-radius-md); }
}

/* ==========================================================================
   5. Forms
   ========================================================================== */

.d2-field { display: flex; flex-direction: column; gap: var(--d2-space-2); }
.d2-label { font-size: 0.875rem; font-weight: 500; color: hsl(var(--d2-foreground)); }
.d2-hint { font-size: 0.8rem; color: hsl(var(--d2-muted-foreground)); }

/* Nur-Lese-Wert in Anzeige-Modals (z.B. Mieter-Details): fett allein war zu
   schwach von der Beschriftung (.d2-label) zu unterscheiden -- ein eigener
   Kasten macht auf einen Blick klar, was Feld und was Inhalt ist. */
.d2-field__wert {
  display: block;
  background: hsl(var(--d2-muted));
  border: 1px solid hsl(var(--d2-border));
  border-radius: var(--d2-radius-md);
  padding: var(--d2-space-2) var(--d2-space-3);
  font-size: 0.9rem;
}
.d2-error-text { font-size: 0.8rem; color: hsl(var(--d2-destructive)); }

.d2-input,
.d2-textarea,
.d2-select {
  width: 100%;
  background: hsl(var(--d2-background));
  color: hsl(var(--d2-foreground));
  border: 1px solid hsl(var(--d2-input));
  border-radius: var(--d2-radius-md);
  padding: 0 var(--d2-space-3);
  height: 2.25rem;
  font-size: 0.875rem;
  transition: border-color var(--d2-fast) var(--d2-ease), box-shadow var(--d2-fast) var(--d2-ease);
}
.d2-textarea { height: auto; padding: var(--d2-space-2) var(--d2-space-3); min-height: 5.5rem; resize: vertical; }
.d2-input::placeholder, .d2-textarea::placeholder { color: hsl(var(--d2-muted-foreground)); }
.d2-input:focus, .d2-textarea:focus, .d2-select:focus {
  outline: none;
  border-color: hsl(var(--d2-ring));
  box-shadow: 0 0 0 3px hsl(var(--d2-ring) / 0.25);
}
.d2-input:disabled, .d2-textarea:disabled, .d2-select:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}
.d2-input.d2-input--error, .d2-textarea.d2-input--error {
  border-color: hsl(var(--d2-destructive));
}

.d2-input[type="file"] {
  padding: var(--d2-space-1);
  display: inline-flex;
  align-items: center;
  width: auto;
}
.d2-input[type="file"]::file-selector-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 1.5rem;
  padding: 0 var(--d2-space-3);
  margin-right: var(--d2-space-3);
  vertical-align: middle;
  border: none;
  border-radius: var(--d2-radius-md);
  font-size: 0.8rem;
  font-weight: 500;
  font-family: inherit;
  cursor: pointer;
  background: hsl(var(--d2-primary));
  color: hsl(var(--d2-primary-foreground));
  transition: opacity var(--d2-fast) var(--d2-ease);
}
.d2-input[type="file"]::file-selector-button:hover { opacity: 0.9; }
.d2-input[type="file"]::file-selector-button:active { opacity: 0.8; }

.d2-select {
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%2364748b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 0.6rem center;
  padding-right: 2rem;
}
select[multiple].d2-select {
  appearance: auto;
  background-image: none;
  height: auto;
  padding: var(--d2-space-1) 0;
}
select[multiple].d2-select option {
  padding: var(--d2-space-1) var(--d2-space-3);
}

/* Varianten stehen nach den Grundregeln von .d2-input, sonst gewinnen
   dort width, height, padding und border bei gleicher Spezifität. */
/* Farbwähler (input[type=color]) in Status-Tabellen. */
.d2-input--color { width: 3.5rem; padding: 0.2rem; }
/* Schreibgeschützter, markierbarer Wert (z.B. Backup-Schlüssel): ganzer
   Inhalt wird per Klick markiert, deshalb cursor:text. */
.d2-input--secret {
  height: 4.5rem;
  display: flex;
  align-items: center;
  font-family: var(--d2-font-mono);
  word-break: break-all;
  cursor: text;
}
/* Inline bearbeitbarer Titel (Dashboard-Verwaltung): sieht erst beim Hover
   wie ein Feld aus, der Speicherstatus färbt den Rahmen kurz ein. */
.d2-input--inline { min-width: 0; flex: 1 1 auto; border-color: transparent; background: transparent; transition: border-color var(--d2-fast) var(--d2-ease), background var(--d2-fast) var(--d2-ease); }
.d2-input--inline:hover { background: hsl(var(--d2-muted) / 0.5); }
.d2-input--gespeichert { border-color: hsl(var(--d2-success)) !important; }
.d2-input--fehlerhaft { border-color: hsl(var(--d2-destructive)) !important; }
/* Eigener Dateiauswahl-Button: das echte input[type=file] bleibt
   bedienbar, aber unsichtbar, das folgende <label class="d2-btn"> ist die
   Schaltfläche. Grund: die Beschriftung von ::file-selector-button kommt
   aus der Browsersprache und ist per CSS nicht änderbar. */
.d2-file-picker { position: relative; display: flex; align-items: center; gap: var(--d2-space-3); }
.d2-file-picker input[type="file"] { position: absolute; width: 1px; height: 1px; opacity: 0; overflow: hidden; }
.d2-file-picker input:focus-visible + label { outline: 2px solid hsl(var(--d2-ring)); outline-offset: 2px; }
.d2-checkbox, .d2-radio {
  width: 1.05rem;
  height: 1.05rem;
  accent-color: hsl(var(--d2-primary));
  cursor: pointer;
}

.d2-check-row {
  display: flex;
  align-items: center;
  gap: var(--d2-space-2);
  font-size: 0.875rem;
  cursor: pointer;
}

.d2-switch {
  position: relative;
  display: inline-block;
  width: 2.5rem;
  height: 1.4rem;
  flex-shrink: 0;
}
.d2-switch input {
  position: absolute;
  opacity: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  cursor: pointer;
}
.d2-switch__track {
  position: absolute;
  inset: 0;
  background: hsl(var(--d2-muted));
  border-radius: var(--d2-radius-pill);
  transition: background-color var(--d2-fast) var(--d2-ease);
}
.d2-switch__track::before {
  content: "";
  position: absolute;
  top: 2px;
  left: 2px;
  width: calc(1.4rem - 4px);
  height: calc(1.4rem - 4px);
  background: hsl(var(--d2-background));
  border-radius: 50%;
  transition: transform var(--d2-fast) var(--d2-ease);
  box-shadow: var(--d2-shadow-sm);
}
.d2-switch input:checked + .d2-switch__track { background: hsl(var(--d2-primary)); }
.d2-switch input:checked + .d2-switch__track::before { transform: translateX(1.1rem); }
.d2-switch input:focus-visible + .d2-switch__track { outline: 2px solid hsl(var(--d2-ring)); outline-offset: 2px; }

.d2-file {
  display: flex;
  align-items: center;
  gap: var(--d2-space-3);
  border: 1px dashed hsl(var(--d2-border));
  border-radius: var(--d2-radius-md);
  padding: var(--d2-space-4);
  font-size: 0.875rem;
  color: hsl(var(--d2-muted-foreground));
}

/* ==========================================================================
   6. Card
   ========================================================================== */

.d2-card {
  background: hsl(var(--d2-card));
  color: hsl(var(--d2-card-foreground));
  border: 1px solid hsl(var(--d2-border));
  border-radius: var(--d2-radius-lg);
  box-shadow: var(--d2-shadow-sm);
}
.d2-card__header { padding: var(--d2-space-4) var(--d2-space-4) 0; }
.d2-card__title { margin: 0; font-size: 1.05rem; font-weight: 600; }
.d2-card__description { margin: var(--d2-space-1) 0 0; color: hsl(var(--d2-muted-foreground)); font-size: 0.875rem; }
.d2-card__content { padding: var(--d2-space-4); }
.d2-card__footer {
  padding: 0 var(--d2-space-4) var(--d2-space-4);
  display: flex;
  align-items: center;
  gap: var(--d2-space-2);
}

/* Kompaktere Variante für dichte Nur-Lese-Ansichten (z.B. Exposé in
   wohnungen/index.php) -- gleiche Struktur wie die reguläre Karte, nur mit
   engeren Abständen statt eigener, abweichender Auszeichnung. */
.d2-card--compact .d2-card__header { padding: var(--d2-space-3) var(--d2-space-3) 0; }
.d2-card--compact .d2-card__content { padding: var(--d2-space-3); }
.d2-card--compact .d2-grid-cols-2 { gap: var(--d2-space-3); }

/* Hervorhebung für kritische Daten (z.B. Notfalldaten), analog zu
   .d2-accordion--kritisch -- transparentes Rot statt Volltonfarbe, damit der
   Kastenhintergrund darunter sichtbar bleibt. */
.d2-card--kritisch { border-color: hsl(var(--d2-destructive)); background: hsl(var(--d2-destructive) / 0.08); }
/* Ganze Karte als Link (z.B. Mieter-Kacheln der Dokumentation). */
.d2-card--link { display: block; text-decoration: none; color: inherit; }
/* Kurzer Rahmen-Puls, wenn per Sprungmarke zu einer Karte gescrollt wird. */
.d2-card--hervorgehoben { box-shadow: 0 0 0 3px hsl(var(--d2-primary) / 0.6); transition: box-shadow 0.3s ease; }

/* ==========================================================================
   7. Badge & status dot
   ========================================================================== */

/* Pille bleibt immer einzeilig: bei zwei Zeilen wirkt die volle Rundung
   wie ein Oval und der Text klebt an der Kante. In Tabellen wird die Spalte
   dadurch breiter, .d2-table-wrap scrollt dann horizontal. */
.d2-badge {
  display: inline-flex;
  align-items: center;
  gap: var(--d2-space-1);
  padding: 0.2em 0.75em;
  border-radius: var(--d2-radius-pill);
  font-size: 0.75rem;
  font-weight: 600;
  line-height: 1.4;
  white-space: nowrap;
  background: hsl(var(--d2-secondary));
  color: hsl(var(--d2-secondary-foreground));
}
.d2-badge--primary { background: hsl(var(--d2-primary) / 0.15); color: hsl(var(--d2-primary)); }
.d2-badge--outline { background: transparent; border: 1px solid hsl(var(--d2-border)); color: hsl(var(--d2-foreground)); }
.d2-badge--destructive { background: hsl(var(--d2-destructive) / 0.15); color: hsl(var(--d2-destructive)); }
.d2-badge--success { background: hsl(var(--d2-success) / 0.15); color: hsl(var(--d2-success)); }
.d2-badge--warning { background: hsl(var(--d2-warning) / 0.18); color: hsl(var(--d2-warning)); }
.d2-badge--info { background: hsl(var(--d2-info) / 0.15); color: hsl(var(--d2-info)); }

.d2-status-dot {
  display: inline-block;
  width: 0.55em;
  height: 0.55em;
  border-radius: 50%;
  background: hsl(var(--d2-muted-foreground));
  flex-shrink: 0;
}
.d2-status-dot--online { background: hsl(var(--d2-success)); }
.d2-status-dot--busy { background: hsl(var(--d2-destructive)); }
.d2-status-dot--away { background: hsl(var(--d2-warning)); }
/* Runder Statuspunkt vor einem Text in Tabellenzellen. */
.d2-status-dot--text { width: 0.85rem; height: 0.85rem; margin-right: var(--d2-space-1); vertical-align: middle; }
/* Quadratisches Farbfeld in Textgröße (z.B. Status in Überschriften),
   Farbe kommt als Inline-Wert aus der Datenbank. */
.d2-farbfeld { display: inline-block; width: 1em; height: 1em; border-radius: var(--d2-radius-sm); }
/* Badge mit Entfernen-Kreuz (Rollen eines Benutzers). */
.d2-badge--removable { display: inline-flex; align-items: center; gap: 6px; }
.d2-badge__remove-form { display: inline; line-height: 1; }
.d2-badge__remove { border: none; background: none; cursor: pointer; color: inherit; padding: 0; font-size: 1em; }
.d2-status-dot--offline { background: hsl(var(--d2-muted-foreground)); }

/* ==========================================================================
   8. Alerts
   ========================================================================== */

.d2-alert {
  display: flex;
  gap: var(--d2-space-3);
  padding: var(--d2-space-4);
  border: 1px solid hsl(var(--d2-border));
  border-radius: var(--d2-radius-md);
  background: hsl(var(--d2-muted) / 0.4);
}
.d2-alert__icon { flex-shrink: 0; line-height: 1; }
.d2-alert__title { margin: 0 0 2px; font-weight: 600; font-size: 0.9rem; }
.d2-alert__description { margin: 0; font-size: 0.875rem; color: hsl(var(--d2-muted-foreground)); }

.d2-alert--destructive { background: hsl(var(--d2-destructive) / 0.08); border-color: hsl(var(--d2-destructive) / 0.35); }
.d2-alert--destructive .d2-alert__title { color: hsl(var(--d2-destructive)); }
.d2-alert--success { background: hsl(var(--d2-success) / 0.08); border-color: hsl(var(--d2-success) / 0.35); }
.d2-alert--success .d2-alert__title { color: hsl(var(--d2-success)); }
.d2-alert--warning { background: hsl(var(--d2-warning) / 0.1); border-color: hsl(var(--d2-warning) / 0.35); }
.d2-alert--warning .d2-alert__title { color: hsl(var(--d2-warning)); }
.d2-alert--info { background: hsl(var(--d2-info) / 0.08); border-color: hsl(var(--d2-info) / 0.35); }
.d2-alert--info .d2-alert__title { color: hsl(var(--d2-info)); }

/* Gelb hervorgehobener Block ohne Alert-Aufbau (Icon/Titel), z.B. Feld
   und Text „Sonstiges“ einer Übergabe. Eigener Gelbton statt --d2-warning:
   der ist im hellen Theme orange, gewünscht ist ausdrücklich Gelb. */
.d2-hervorgehoben {
  padding: var(--d2-space-3);
  background: hsl(50 98% 55% / 0.22);
  border: 1px solid hsl(47 95% 48%);
  border-left-width: 4px;
  border-radius: var(--d2-radius-md);
}

/* Wartungsmodus (Ankündigungsbanner + /wartung-Seite): eigener Orange-Ton
   statt --d2-warning, da der Token andernorts (Badges, Status-Punkte) für
   Zwecke mit anderer erwarteter Farbwirkung genutzt wird -- hier soll es
   unabhängig davon immer eindeutig orange sein. */
.d2-wartung-box {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: var(--d2-space-2);
  padding: var(--d2-space-4);
  background: rgba(249, 115, 22, 0.15);
  border: 1px solid rgba(249, 115, 22, 0.4);
  border-radius: var(--d2-radius-md);
  color: inherit;
}
.d2-wartung-box__icon { color: rgb(249, 115, 22); }
.d2-wartung-box__countdown { font-weight: 700; font-size: 1.25rem; }
/* Als Banner über der Navbar: randlos über die volle Breite. */
.d2-wartung-box--banner { border-radius: 0; border-width: 0 0 1px 0; }
.d2-wartung-box__schliessen {
  position: absolute;
  top: var(--d2-space-2);
  right: var(--d2-space-2);
  background: none;
  border: none;
  color: inherit;
  font-size: 1.25rem;
  line-height: 1;
  cursor: pointer;
  padding: var(--d2-space-1);
  opacity: 0.7;
}
.d2-wartung-box__schliessen:hover { opacity: 1; }
/* Letzte 3 Minuten vor Wartungsbeginn: Banner ist nicht mehr wegklickbar
   (siehe layout.php) und blinkt langsam per Fade, um kurz vor Sperre
   nochmal Aufmerksamkeit zu erzeugen. */
@keyframes d2-wartung-blinken {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.35; }
}
.d2-wartung-box--blinkt { animation: d2-wartung-blinken 2.5s ease-in-out infinite; }

/* ==========================================================================
   9. Table
   ========================================================================== */

.d2-table-wrap { overflow-x: auto; border: 1px solid hsl(var(--d2-border)); border-radius: var(--d2-radius-md); }
.d2-table { width: 100%; border-collapse: collapse; font-size: 0.875rem; }
.d2-table th, .d2-table td { padding: var(--d2-space-3) var(--d2-space-4); text-align: left; border-bottom: 1px solid hsl(var(--d2-border)); }
.d2-table th { font-weight: 600; color: hsl(var(--d2-muted-foreground)); background: hsl(var(--d2-muted) / 0.4); }
.d2-table tbody tr:last-child td { border-bottom: none; }
.d2-table tbody tr:hover { background: hsl(var(--d2-accent) / 0.5); }
.d2-table--striped tbody tr:nth-child(even) { background: hsl(var(--d2-muted) / 0.3); }
.d2-table__sort { color: inherit; font-weight: inherit; white-space: nowrap; }
.d2-table__sort:hover { color: hsl(var(--d2-primary)); background: hsl(var(--d2-muted)); text-decoration: none; }

/* Score-Einfärbung in der Auswertung: 5 Stufen relativ zur angezeigten
   Liste (niedrigster Score = rot, höchster = grün), siehe DECISIONS.md. */
.d2-table td.d2-score-cell { font-weight: 600; text-align: center; }
.d2-score-cell--1 { background: hsl(0 72% 90%); color: hsl(0 65% 30%); }
.d2-score-cell--2 { background: hsl(28 80% 88%); color: hsl(28 70% 28%); }
.d2-score-cell--3 { background: hsl(48 85% 85%); color: hsl(45 70% 26%); }
.d2-score-cell--4 { background: hsl(85 55% 85%); color: hsl(85 45% 24%); }
.d2-score-cell--5 { background: hsl(135 55% 85%); color: hsl(135 45% 20%); }

.d2-table td.d2-cell--hervorgehoben { background: hsl(var(--d2-destructive) / 0.12); }
/* Ganze Zeile hervorheben (z.B. überfälliger Verleih), bleibt auch beim
   Hover rot, deshalb gleiche Spezifität wie die Hover-Regel und später. */
.d2-table tbody tr.d2-row--hervorgehoben,
.d2-table tbody tr.d2-row--hervorgehoben:hover { background: hsl(var(--d2-destructive) / 0.12); }

/* ==========================================================================
   10. Tabs (markup: nav[role=tablist] > button[role=tab][aria-selected])
   ========================================================================== */

.d2-tabs__list {
  display: flex;
  gap: var(--d2-space-1);
  border-bottom: 1px solid hsl(var(--d2-border));
}
.d2-tabs__trigger {
  padding: var(--d2-space-2) var(--d2-space-4);
  border: none;
  background: none;
  font-size: 0.875rem;
  font-weight: 500;
  color: hsl(var(--d2-muted-foreground));
  cursor: pointer;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  transition: color var(--d2-fast) var(--d2-ease), border-color var(--d2-fast) var(--d2-ease);
}
.d2-tabs__trigger:hover { color: hsl(var(--d2-foreground)); }
.d2-tabs__trigger[aria-selected="true"] {
  color: hsl(var(--d2-primary));
  border-bottom-color: hsl(var(--d2-primary));
}
.d2-tabs__panel { padding: var(--d2-space-4) 0; }
.d2-tabs__panel[hidden] { display: none; }

/* ==========================================================================
   11. Accordion (native details/summary — no JS needed)
   ========================================================================== */

.d2-accordion { border: 1px solid hsl(var(--d2-border)); border-radius: var(--d2-radius-md); overflow: hidden; }
.d2-accordion + .d2-accordion { border-top: none; border-top-left-radius: 0; border-top-right-radius: 0; }
.d2-accordion > summary {
  list-style: none;
  cursor: pointer;
  padding: var(--d2-space-3) var(--d2-space-4);
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-weight: 500;
  font-size: 0.9rem;
}
.d2-accordion > summary::-webkit-details-marker { display: none; }
.d2-accordion > summary::after {
  content: "";
  width: 8px;
  height: 8px;
  border-right: 2px solid hsl(var(--d2-muted-foreground));
  border-bottom: 2px solid hsl(var(--d2-muted-foreground));
  transform: rotate(45deg);
  transition: transform var(--d2-fast) var(--d2-ease);
}
.d2-accordion[open] > summary::after { transform: rotate(-135deg); }
.d2-accordion__body { padding: 0 var(--d2-space-4) var(--d2-space-4); font-size: 0.875rem; color: hsl(var(--d2-muted-foreground)); }

/* Hervorhebung für besonders wichtige Abschnitte (z.B. Notfalldaten) --
   bewusst sowohl im zu- als auch im aufgeklappten Zustand sichtbar, da
   .d2-accordion > summary unabhängig vom [open]-Zustand gerendert wird. */
.d2-accordion--kritisch { border-color: hsl(var(--d2-destructive)); }
.d2-accordion--kritisch > summary { color: hsl(var(--d2-destructive)); background: hsl(var(--d2-destructive) / 0.08); }
.d2-accordion--kritisch > summary::after { border-right-color: hsl(var(--d2-destructive)); border-bottom-color: hsl(var(--d2-destructive)); }

/* Änderungsverlauf (siehe partials/verlauf.php): Feldänderungen werden
   farblich hervorgehoben, reine Kontakt-Einträge bleiben neutral/gedämpft. */
.d2-verlauf-eintrag { padding: var(--d2-space-3); border-radius: var(--d2-radius-md); }
.d2-verlauf-eintrag--aenderung { background: hsl(var(--d2-info) / 0.08); border-left: 3px solid hsl(var(--d2-info)); }
.d2-verlauf-eintrag--geloescht { background: hsl(var(--d2-destructive) / 0.08); border-left: 3px solid hsl(var(--d2-destructive)); }
.d2-verlauf-alt { text-decoration: line-through; color: hsl(var(--d2-muted-foreground)); }
.d2-verlauf-neu { font-weight: 600; }

/* ==========================================================================
   12. Breadcrumb & pagination
   ========================================================================== */

.d2-breadcrumb { display: flex; flex-wrap: wrap; align-items: center; gap: var(--d2-space-1); font-size: 0.875rem; list-style: none; padding: 0; margin: 0; }
.d2-breadcrumb li { display: flex; align-items: center; gap: var(--d2-space-1); }
.d2-breadcrumb li:not(:last-child)::after { content: "/"; color: hsl(var(--d2-muted-foreground)); margin-left: var(--d2-space-1); }
.d2-breadcrumb a { color: hsl(var(--d2-muted-foreground)); }
.d2-breadcrumb a:hover { color: hsl(var(--d2-foreground)); }
.d2-breadcrumb li:last-child { color: hsl(var(--d2-foreground)); font-weight: 500; }

.d2-pagination { display: flex; align-items: center; gap: var(--d2-space-1); list-style: none; padding: 0; margin: 0; }
.d2-pagination button, .d2-pagination a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 2rem;
  height: 2rem;
  padding: 0 var(--d2-space-2);
  border-radius: var(--d2-radius-md);
  border: 1px solid transparent;
  background: none;
  font-size: 0.85rem;
  cursor: pointer;
  color: hsl(var(--d2-foreground));
}
.d2-pagination button:hover, .d2-pagination a:hover { background: hsl(var(--d2-accent)); }
.d2-pagination [aria-current="page"] { background: hsl(var(--d2-primary)); color: hsl(var(--d2-primary-foreground)); }
.d2-pagination button:disabled { opacity: 0.4; cursor: not-allowed; }

/* ==========================================================================
   13. Avatar, progress, skeleton, spinner
   ========================================================================== */

.d2-avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.5rem;
  height: 2.5rem;
  border-radius: 50%;
  background: hsl(var(--d2-muted));
  color: hsl(var(--d2-muted-foreground));
  font-size: 0.9rem;
  font-weight: 600;
  overflow: hidden;
  flex-shrink: 0;
}
.d2-avatar img { width: 100%; height: 100%; object-fit: cover; }
.d2-avatar--sm { width: 1.75rem; height: 1.75rem; font-size: 0.75rem; }
.d2-avatar--lg { width: 3.5rem; height: 3.5rem; font-size: 1.2rem; }

.d2-progress { height: 0.5rem; border-radius: var(--d2-radius-pill); background: hsl(var(--d2-muted)); overflow: hidden; }
.d2-progress__bar { height: 100%; background: hsl(var(--d2-primary)); transition: width var(--d2-slow) var(--d2-ease); }
.d2-progress--lg { height: 0.6rem; }
.d2-progress--flat { height: 8px; border-radius: 4px; background: hsl(var(--d2-border)); }

.d2-skeleton {
  border-radius: var(--d2-radius-md);
  background: linear-gradient(90deg, hsl(var(--d2-muted)) 25%, hsl(var(--d2-accent)) 37%, hsl(var(--d2-muted)) 63%);
  background-size: 400% 100%;
  animation: d2-skeleton-shimmer 1.4s ease infinite;
}
@keyframes d2-skeleton-shimmer {
  0% { background-position: 100% 50%; }
  100% { background-position: 0 50%; }
}

.d2-spinner {
  width: 1.25rem;
  height: 1.25rem;
  border: 2px solid hsl(var(--d2-muted));
  border-top-color: hsl(var(--d2-primary));
  border-radius: 50%;
  animation: d2-spin 0.7s linear infinite;
}
@keyframes d2-spin { to { transform: rotate(360deg); } }

/* ==========================================================================
   14. Tooltip (CSS-only, via data-tooltip attribute)
   ========================================================================== */

[data-tooltip] { position: relative; }
[data-tooltip]::after {
  content: attr(data-tooltip);
  position: absolute;
  bottom: calc(100% + 6px);
  left: 50%;
  transform: translateX(-50%) translateY(4px);
  background: hsl(var(--d2-foreground));
  color: hsl(var(--d2-background));
  font-size: 0.75rem;
  white-space: nowrap;
  padding: 0.3em 0.6em;
  border-radius: var(--d2-radius-sm);
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--d2-fast) var(--d2-ease), transform var(--d2-fast) var(--d2-ease);
  z-index: 50;
}
[data-tooltip]:hover::after, [data-tooltip]:focus-visible::after {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}

/* ==========================================================================
   15. Modal / dialog (native <dialog> element)
   ========================================================================== */

.d2-modal {
  border: 1px solid hsl(var(--d2-border));
  border-radius: var(--d2-radius-lg);
  padding: 0;
  width: min(480px, 92vw);
  background: hsl(var(--d2-card));
  color: hsl(var(--d2-card-foreground));
  box-shadow: var(--d2-shadow-lg);
}
/* Breiten: Standard 480px, --sm 420px (Bestätigungen), --lg 560px
   (Suche, Formulare), --xl 640px (Detailansichten mit Tabellen). */
.d2-modal--sm { width: min(420px, 92vw); }
.d2-modal--lg { width: min(560px, 92vw); }
.d2-modal--xl { width: min(640px, 92vw); }
.d2-modal::backdrop { background: hsl(220 20% 5% / 0.5); backdrop-filter: blur(2px); }
.d2-modal__header { padding: var(--d2-space-4); border-bottom: 1px solid hsl(var(--d2-border)); }
.d2-modal__title { margin: 0; font-size: 1.05rem; font-weight: 600; }
/* Dialog mit Reitern (.d2-tabs__list im Header): deren Unterkante ersetzt
   die Trennlinie des Headers. */
.d2-modal__header--tabs { padding-bottom: 0; border-bottom: none; }
.d2-modal__body { padding: var(--d2-space-4); font-size: 0.9rem; }
.d2-modal__footer {
  padding: var(--d2-space-4);
  border-top: 1px solid hsl(var(--d2-border));
  display: flex;
  justify-content: flex-end;
  gap: var(--d2-space-2);
}

/* ==========================================================================
   16. Dropdown menu (toggle an .is-open class from JS)
   ========================================================================== */

.d2-menu {
  position: relative;
  display: inline-block;
}
.d2-menu__list {
  position: absolute;
  top: calc(100% + 4px);
  right: 0;
  min-width: 180px;
  background: hsl(var(--d2-popover));
  color: hsl(var(--d2-popover-foreground));
  border: 1px solid hsl(var(--d2-border));
  border-radius: var(--d2-radius-md);
  box-shadow: var(--d2-shadow-lg);
  padding: var(--d2-space-1);
  display: none;
  z-index: 40;
}
.d2-menu.is-open .d2-menu__list { display: block; }
.d2-menu__item {
  display: flex;
  align-items: center;
  gap: var(--d2-space-2);
  width: 100%;
  padding: var(--d2-space-2) var(--d2-space-3);
  border: none;
  background: none;
  text-align: left;
  font-size: 0.875rem;
  border-radius: var(--d2-radius-sm);
  cursor: pointer;
  color: inherit;
}
.d2-menu__item:hover { background: hsl(var(--d2-accent)); }
.d2-menu__item--destructive { color: hsl(var(--d2-destructive)); }
.d2-menu__separator { border-top: 1px solid hsl(var(--d2-border)); margin: var(--d2-space-1) 0; }

/* Vorschlagsliste unter einem Eingabefeld (Adressen, Wohnungen, Personen).
   Startet unsichtbar, das jeweilige Skript setzt style.display und bei
   position:absolute am Body auch Position und Breite. --anchored hängt die
   Liste stattdessen direkt unter ein position:relative-Elternelement. */
.d2-autocomplete {
  position: absolute;
  z-index: 1000;
  display: none;
  max-height: 240px;
  overflow-y: auto;
  background: hsl(var(--d2-popover));
  color: hsl(var(--d2-popover-foreground));
  border: 1px solid hsl(var(--d2-border));
  border-radius: var(--d2-radius-md);
  box-shadow: var(--d2-shadow-lg);
}
.d2-autocomplete--anchored { top: 100%; left: 0; right: 0; }
.d2-autocomplete__item { padding: var(--d2-space-2) var(--d2-space-3); font-size: 0.9rem; }
.d2-autocomplete--divided .d2-autocomplete__item { border-bottom: 1px solid hsl(var(--d2-border)); }
.d2-autocomplete--divided .d2-autocomplete__item:last-child { border-bottom: none; }
.d2-autocomplete__item--selectable { cursor: pointer; }
.d2-autocomplete__item--selectable:hover { background: hsl(var(--d2-muted)); }
.d2-autocomplete__note { color: hsl(var(--d2-destructive)); font-size: 0.8rem; margin-top: 2px; }
/* Trefferliste der Personensuche (Dokumentation) als Karte unter dem Feld. */
.d2-search-results { position: absolute; z-index: 10; width: 100%; margin-top: var(--d2-space-1); max-height: 260px; overflow-y: auto; }
.d2-search-results__item { display: block; padding: var(--d2-space-2) var(--d2-space-3); color: inherit; }

/* ==========================================================================
   17. Toast (position a .d2-toast-container, append .d2-toast via JS)
   ========================================================================== */

.d2-toast-container {
  position: fixed;
  bottom: var(--d2-space-5);
  right: var(--d2-space-5);
  display: flex;
  flex-direction: column;
  gap: var(--d2-space-2);
  z-index: 100;
}
.d2-toast {
  min-width: 260px;
  max-width: 360px;
  background: hsl(var(--d2-popover));
  color: hsl(var(--d2-popover-foreground));
  border: 1px solid hsl(var(--d2-border));
  border-radius: var(--d2-radius-md);
  box-shadow: var(--d2-shadow-lg);
  padding: var(--d2-space-3) var(--d2-space-4);
  font-size: 0.875rem;
}
.d2-toast--success { border-left: 3px solid hsl(var(--d2-success)); }
.d2-toast--destructive { border-left: 3px solid hsl(var(--d2-destructive)); }
.d2-toast--warning { border-left: 3px solid hsl(var(--d2-warning)); }

@media (max-width: 479px) {
  .d2-toast-container { left: var(--d2-space-3); right: var(--d2-space-3); bottom: var(--d2-space-3); }
  .d2-toast { min-width: 0; max-width: none; width: 100%; }
}

/* ==========================================================================
   17b. Leaflet-Popup (Kartenmarker, siehe kiez.karten)
   ========================================================================== */

/* leaflet.css setzt Popup-Hintergrund/-Text fest auf weiß/#333 (siehe
   modules/kiez.karten/assets/leaflet/leaflet.css) -- eigene Inhalte darin
   (z.B. der "Details"-Button auf der Wohnungen-Karte) nutzen aber die
   Theme-Farben und waren im Dark-Theme dadurch weißer Text auf weißem
   Grund. --d2-popover/-foreground statt fest weiß, damit Popups im
   jeweiligen Theme lesbar bleiben. !important nötig, da leaflet.css
   dieselben Selektoren mit derselben Spezifität nutzt und je nach
   Ladereihenfolge sonst gewinnen würde (leaflet.css wird erst innerhalb
   der jeweiligen Seite eingebunden, also nach dieser Datei). */
.leaflet-popup-content-wrapper,
.leaflet-popup-tip {
  background: hsl(var(--d2-popover)) !important;
  color: hsl(var(--d2-popover-foreground)) !important;
}
.leaflet-container a.leaflet-popup-close-button {
  color: hsl(var(--d2-muted-foreground)) !important;
}
.leaflet-container a.leaflet-popup-close-button:hover,
.leaflet-container a.leaflet-popup-close-button:focus {
  color: hsl(var(--d2-foreground)) !important;
}

/* leaflet.css vergibt intern z-index bis 1000 (Kacheln, Marker, Popups,
   Zoom-Controls, siehe dortige Kommentare "required styles"/"control
   positioning"), der Kartencontainer selbst schirmt das aber nicht ab --
   ohne eigene Stapelkontext-Grenze konkurrieren diese Werte direkt mit
   Seitenelementen wie der Navbar (z-index 30) und überdecken deren
   aufgeklappte Menüs. isolation:isolate kapselt Leaflets komplette
   Werteskala in den Kartencontainer, unabhängig davon, welchen z-index
   spätere Bibliotheks-Updates intern verwenden. */
.leaflet-container {
  isolation: isolate;
}

/* ==========================================================================
   17c. Kartencontainer (kiez.karten, Wohnungskarte, Exposé-Minikarte)
   ========================================================================== */

/* Kartencontainer: Höhe je nach Einsatz, bei variabler Höhe (Partial
   karte.php) kommt sie als Inline-Wert. */
.d2-map { border-radius: var(--d2-radius); overflow: hidden; }
.d2-map--mini { height: 220px; }
.d2-map--large { height: 65vh; min-height: 400px; }

/* ==========================================================================
   18. Navbar & sidebar
   ========================================================================== */

.d2-navbar {
  position: sticky;
  top: 0;
  /* Muss über dem Backdrop (z-index 40) liegen: position+z-index hier
     erzeugt einen eigenen Stapelkontext, dadurch bleibt die fixierte
     Kompakt-Schublade (z-index 41, siehe .is-compact .d2-navbar__nav) sonst
     trotz ihres höheren Werts unter dem Backdrop gefangen -- ein Klick auf
     einen Menüpunkt traf dann das Backdrop statt der Schublade und schloss
     sie sofort wieder, statt das Untermenü zu öffnen. */
  z-index: 42;
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--d2-space-4);
  padding: var(--d2-space-3) var(--d2-space-4);
  border-bottom: 1px solid hsl(var(--d2-border));
  background: hsl(var(--d2-background));
}
.d2-navbar__brand { display: flex; align-items: center; }
.d2-navbar__logo { height: 32px; width: auto; display: block; }
.d2-about-logo { height: 160px; width: auto; display: inline-block; touch-action: manipulation; }
/* Logo-Datei ist ein statisches SVG mit fest hinterlegter dunkler
   Füllfarbe -- kann anders als der Rest des Design-Systems nicht über
   CSS-Variablen umgefärbt werden, deshalb hier eine gezielte Umkehrung
   fürs dunkle Theme statt einer zweiten Logo-Datei. Gilt für alle
   Einbindungen (Navbar, Über-Dialog, Installer). */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .d2-navbar__logo,
  :root:not([data-theme="light"]) .d2-about-logo,
  :root:not([data-theme="light"]) .d2-install-logo { filter: invert(1); }
}
:root[data-theme="dark"] .d2-navbar__logo,
:root[data-theme="dark"] .d2-about-logo,
:root[data-theme="dark"] .d2-install-logo { filter: invert(1); }
.d2-navbar__nav { display: flex; align-items: center; gap: var(--d2-space-1); min-width: 0; overflow: hidden; }
.d2-navbar__nav svg, .d2-navbar__dropdown-menu svg { flex-shrink: 0; }
.d2-navbar__nav > a {
  padding: var(--d2-space-2) var(--d2-space-3);
  border-radius: var(--d2-radius-sm);
}
/* Menüpunkt in der Leiste bzw. im Dropdown: Icon und Text in einer Zeile,
   nie umbrechen (sonst springt die Leistenhöhe). */
.d2-navbar__link { display: inline-flex; align-items: center; gap: var(--d2-space-2); white-space: nowrap; }
.d2-navbar__dropdown-link { display: flex; align-items: center; gap: var(--d2-space-2); white-space: nowrap; }
.d2-navbar__actions { display: flex; align-items: center; gap: var(--d2-space-2); }

/* Bewusst zurückhaltend gehalten (kleine Schrift, gedeckte Farbe, dünner
   Trennstrich) -- reine Versionsangabe, kein visuelles Gewicht wie die
   Navbar. */
.d2-footer {
  padding: var(--d2-space-3) var(--d2-space-4);
  text-align: center;
  border-top: 1px solid hsl(var(--d2-border));
}
.d2-footer__version {
  background: none;
  border: none;
  padding: var(--d2-space-1) var(--d2-space-2);
  font: inherit;
  font-size: 0.75rem;
  color: hsl(var(--d2-muted-foreground));
  cursor: pointer;
  border-radius: var(--d2-radius-sm);
}
.d2-footer__version:hover { color: hsl(var(--d2-foreground)); background: hsl(var(--d2-muted)); text-decoration: none; }

/* Toggle-Button für die mobile Navigation. Markup: <button class="d2-navbar__toggle">,
   JS bindet Click -> Klasse "is-open" auf .d2-navbar__nav (Schublade) und
   .d2-navbar__backdrop um.

   Der Wechsel zwischen Desktop-Leiste und Kompaktmodus (Schublade) läuft
   bewusst über die JS-gesetzte Klasse "is-compact" auf .d2-navbar statt über
   einen festen Breakpoint (siehe pruefeKompaktModus() in layout.php): wie
   viele Menüpunkte in eine Zeile passen, hängt von Sprache/Länge der Labels
   und des Benutzernamens ab, ein fester Pixelwert würde in bestimmten
   Fensterbreiten dazu führen, dass die Leiste kurz vor Erscheinen des
   Hamburgers zweizeilig umbricht (.d2-navbar steht deshalb oben fest auf
   flex-wrap: nowrap -- ohne is-compact würde .d2-navbar__nav dann
   überlaufende Einträge abschneiden statt umzubrechen, siehe overflow:hidden
   dort, was der JS-Messung als Auslöser dient). */
.d2-navbar__toggle {
  display: none;
  align-items: center;
  justify-content: center;
  width: 2.25rem;
  height: 2.25rem;
  border: 1px solid hsl(var(--d2-border));
  border-radius: var(--d2-radius-md);
  background: none;
  cursor: pointer;
  color: inherit;
}
.d2-navbar.is-compact .d2-navbar__brand { display: none; }
.d2-navbar.is-compact .d2-navbar__toggle { display: inline-flex; }
.d2-navbar.is-compact .d2-navbar__nav {
  position: fixed;
  top: 0;
  left: 0;
  height: 100vh;
  height: 100dvh;
  width: min(320px, 85vw);
  flex-direction: column;
  align-items: stretch;
  overflow-y: auto;
  overflow-x: hidden;
  padding: var(--d2-space-4);
  background: hsl(var(--d2-background));
  border-right: 1px solid hsl(var(--d2-border));
  box-shadow: var(--d2-shadow-lg);
  transform: translateX(-100%);
  transition: transform var(--d2-fast) var(--d2-ease);
  z-index: 41;
}
.d2-navbar.is-compact .d2-navbar__nav.is-open { transform: translateX(0); }
.d2-navbar__backdrop {
  display: none;
  position: fixed;
  inset: 0;
  background: hsl(220 20% 5% / 0.5);
  z-index: 40;
}
.d2-navbar__backdrop.is-open { display: block; }

/* Dropdowns für Menügruppen (Verwaltung, Module). Markup: <details
   class="d2-navbar__dropdown"><summary>...</summary><div
   class="d2-navbar__dropdown-menu">...</div></details> -- native
   Details/Summary statt JS-Toggle, damit Klick-außen-schließt und
   Tastaturbedienung ohne eigenen Code funktionieren. Öffnen per Hover auf
   Desktop-Breite kommt per JS dazu (siehe layout.php), das dabei die Klasse
   d2-navbar__dropdown--visible setzt -- <details> rendert geschlossenen
   Inhalt unabhängig von CSS-Overrides gar nicht, ein opacity-Übergang ist
   daher erst nach dem Setzen von [open] möglich. */
.d2-navbar__dropdown { position: relative; }
.d2-navbar__dropdown > summary {
  cursor: pointer;
  list-style: none;
  color: inherit;
  padding: var(--d2-space-2) var(--d2-space-3);
  border-radius: var(--d2-radius-sm);
  /* Ohne nowrap bricht ein langes Label (z.B. "Dashboard-Verwaltung") bei
     knappem Platz um, statt dass die Navbar-Zeile überläuft --
     pruefeKompaktModus() (siehe layout.php) misst genau dieses Überlaufen
     und würde sonst nie auslösen: die Zeile wird durch das interne
     Umbrechen ja formal nicht breiter als verfügbar, nur höher. Die
     normalen <a>-Menüpunkte haben das bereits inline (siehe layout.php). */
  white-space: nowrap;
}
.d2-navbar__dropdown > summary:hover { background: hsl(var(--d2-muted)); }
.d2-navbar__dropdown > summary::-webkit-details-marker { display: none; }
/* Eigener Rahmen nur für den Account-Menüpunkt (Benutzername), damit
   erkennbar ist, dass er eine Funktion hat -- die übrigen Dropdown-Punkte
   (Verwaltung etc.) bleiben bewusst wie normale Navigationslinks ohne
   Rahmen. */
.d2-navbar__dropdown--konto > summary { border: 1px solid hsl(var(--d2-border)); }
.d2-navbar__dropdown--konto > summary:hover { background: hsl(var(--d2-accent)); }
/* Konto-Trigger zeigt nur noch das Icon (siehe layout.php) statt des
   Benutzernamens -- der Name steht stattdessen als eigener Kasten oben im
   geöffneten Menü. Quadratisches Padding statt der Text-Variante, damit das
   Icon zentriert sitzt. */
.d2-navbar__dropdown--konto > summary {
  display: flex;
  align-items: center;
  padding: var(--d2-space-2);
}
.d2-navbar__dropdown-name {
  padding: var(--d2-space-1) var(--d2-space-3);
  font-weight: 600;
  white-space: nowrap;
}
/* position:fixed statt :absolute, mit top/left per JS gesetzt (siehe
   layout.php, toggle-Listener): .d2-navbar__nav trägt wegen
   pruefeKompaktModus() overflow:hidden (siehe dortiger Kommentar), das
   schneidet ein absolut positioniertes Kind an der unteren Kante der
   Navbar-Zeile ab -- das Menü hätte [open]/opacity:1, wäre aber unsichtbar.
   position:fixed entgeht dieser Clip-Grenze. */
.d2-navbar__dropdown-menu {
  position: fixed;
  z-index: 20;
  display: flex;
  flex-direction: column;
  min-width: 180px;
  background: hsl(var(--d2-popover));
  color: hsl(var(--d2-popover-foreground));
  border: 1px solid hsl(var(--d2-border));
  border-radius: var(--d2-radius-md);
  box-shadow: var(--d2-shadow-lg);
  padding: var(--d2-space-2);
  opacity: 0;
  transform: translateY(-4px);
  transition: opacity 0.15s ease, transform 0.15s ease;
}
.d2-navbar__dropdown--visible > .d2-navbar__dropdown-menu {
  opacity: 1;
  transform: translateY(0);
}
.d2-navbar__dropdown-menu a { padding: var(--d2-space-2) var(--d2-space-3); border-radius: var(--d2-radius-sm); }
/* Menüpunkte ohne Ziel-URL (Account öffnen, Theme umschalten, Logout) sind
   <button>/<form><button>, keine <a> -- gleiche Optik wie die Link-Einträge
   nötig, da native Buttons sonst eigenes Chrome (Hintergrund, Rahmen,
   Schrift) mitbringen. */
.d2-navbar__dropdown-menu button {
  display: flex;
  align-items: center;
  gap: var(--d2-space-2);
  width: 100%;
  padding: var(--d2-space-2) var(--d2-space-3);
  border-radius: var(--d2-radius-sm);
  background: none;
  border: none;
  font: inherit;
  color: inherit;
  text-align: left;
  white-space: nowrap;
  cursor: pointer;
}
.d2-navbar__dropdown-menu a:hover,
.d2-navbar__dropdown-menu button:hover { background: hsl(var(--d2-muted)); }
/* Alle Dropdown-Menüs: statt einer Trennlinie zwischen Gruppen (z.B.
   pinnedLast-Einträge, Konto-Menü) eigenständige, per transparentem Spalt
   getrennte Kästen -- die äußere .d2-navbar__dropdown-menu liefert nur noch
   die Positionierung, die Optik (Hintergrund/Rahmen/Radius/Schatten) wandert
   auf .d2-navbar__dropdown-group. */
.d2-navbar__dropdown-menu--grouped {
  background: none;
  border: none;
  box-shadow: none;
  padding: 0;
  gap: var(--d2-space-2);
}
.d2-navbar__dropdown-group {
  display: flex;
  flex-direction: column;
  background: hsl(var(--d2-popover));
  border: 1px solid hsl(var(--d2-border));
  border-radius: var(--d2-radius-md);
  box-shadow: var(--d2-shadow-lg);
  padding: var(--d2-space-2);
}
/* Überschrift eines Kastens ('subgroupLabel' am Menüeintrag): klein und
   gedämpft, damit sie als Einordnung liest und nicht als klickbarer Punkt. */
.d2-navbar__dropdown-heading {
  padding: var(--d2-space-1) var(--d2-space-3) var(--d2-space-1);
  font-size: 0.7rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: hsl(var(--d2-muted-foreground));
  white-space: nowrap;
}
.d2-navbar.is-compact .d2-navbar__dropdown-menu {
  position: static;
  margin-top: var(--d2-space-1);
  padding-left: var(--d2-space-3);
  border: none;
  box-shadow: none;
  background: none;
}
.d2-navbar.is-compact .d2-navbar__dropdown-group {
  background: none;
  border: none;
  box-shadow: none;
  padding: 0;
}

.d2-sidebar {
  display: flex;
  flex-direction: column;
  width: 240px;
  background: hsl(var(--d2-sidebar));
  color: hsl(var(--d2-sidebar-foreground));
  border-right: 1px solid hsl(var(--d2-sidebar-border));
  height: 100%;
}
/* Off-Canvas auf schmalen Screens. Markup braucht zusätzlich ein Element
   mit .d2-sidebar-backdrop (Klick darauf schließt, JS toggelt "is-open"
   an beiden Elementen synchron). */
@media (max-width: 767px) {
  .d2-sidebar {
    position: fixed;
    inset-block: 0;
    left: 0;
    z-index: 60;
    transform: translateX(-100%);
    box-shadow: var(--d2-shadow-lg);
    transition: transform var(--d2-slow) var(--d2-ease);
  }
  .d2-sidebar.is-open { transform: translateX(0); }
  .d2-sidebar-backdrop {
    display: none;
    position: fixed;
    inset: 0;
    background: hsl(220 20% 5% / 0.5);
    z-index: 55;
  }
  .d2-sidebar-backdrop.is-open { display: block; }
}
.d2-sidebar__header { padding: var(--d2-space-4); font-weight: 700; }
.d2-sidebar__nav { display: flex; flex-direction: column; gap: 2px; padding: var(--d2-space-2); flex: 1; }
.d2-sidebar__item {
  display: flex;
  align-items: center;
  gap: var(--d2-space-2);
  padding: var(--d2-space-2) var(--d2-space-3);
  border-radius: var(--d2-radius-md);
  font-size: 0.875rem;
  color: inherit;
  cursor: pointer;
}
.d2-sidebar__item:hover { background: hsl(var(--d2-sidebar-accent)); text-decoration: none; }
.d2-sidebar__item.is-active {
  background: hsl(var(--d2-sidebar-primary));
  color: hsl(var(--d2-sidebar-primary-foreground));
}
.d2-sidebar__footer { padding: var(--d2-space-3); border-top: 1px solid hsl(var(--d2-sidebar-border)); }
.d2-sidebar__heading {
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: hsl(var(--d2-muted-foreground));
  padding: var(--d2-space-3) var(--d2-space-3) var(--d2-space-1);
}

/* ==========================================================================
   19. Responsive-Hilfsklassen
   ========================================================================== */

/* Generisches Stack-Verhalten: nebeneinander ab md, darunter untereinander.
   Für .d2-cluster/.d2-flex-between-Zeilen, die auf schmalen Screens
   umbrechen sollen statt seitlich zu quetschen. */
.d2-stack-mobile { flex-direction: column; align-items: stretch; }
@media (min-width: 768px) {
  .d2-stack-mobile { flex-direction: row; align-items: center; }
}

/* Sichtbarkeit gezielt nach Breakpoint steuern. */
@media (max-width: 767px) {
  .d2-hide-mobile { display: none !important; }
}
@media (min-width: 768px) {
  .d2-hide-desktop { display: none !important; }
}

/* .d2-grid-cols-{n}: feste Spaltenzahl ab md, davor immer einspaltig.
   Ergänzt das bestehende auto-fit .d2-grid für Fälle, in denen eine
   exakte Spaltenzahl (z.B. Formular-Layout) gebraucht wird. */
.d2-grid-cols-2, .d2-grid-cols-3, .d2-grid-cols-4 {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--d2-space-4);
}
@media (min-width: 768px) {
  .d2-grid-cols-2 { grid-template-columns: repeat(2, 1fr); }
  .d2-grid-cols-3 { grid-template-columns: repeat(3, 1fr); }
  .d2-grid-cols-4 { grid-template-columns: repeat(4, 1fr); }
}

/* ==========================================================================
   20. Lightbox (Bildergalerie-Vollansicht, als <dialog> statt Div+[hidden] --
   nur so landet sie im nativen Top-Layer und damit sicher über einem bereits
   offenen d2-modal, z.B. dem Exposé in wohnungen/index.php; ein normales
   z-index-Div bleibt sonst hinter dem Top-Layer-Dialog verdeckt)
   ========================================================================== */

dialog.d2-lightbox {
  position: fixed;
  inset: 0;
  width: 100vw;
  height: 100vh;
  max-width: 100vw;
  max-height: 100vh;
  margin: 0;
  padding: 0;
  border: none;
  align-items: center;
  justify-content: center;
  background: hsl(220 20% 5% / 0.9);
}
/* dialog:not([open]) { display: none; } ist UA-Standard -- diese Regel
   überschreibt nur den Anzeige-Modus, wenn geöffnet (siehe showModal() in
   den Views), sonst bliebe es beim UA-Default "display: block". */
dialog.d2-lightbox[open] {
  display: flex;
}
.d2-lightbox__bild {
  max-width: min(90vw, 1100px);
  max-height: 90vh;
  object-fit: contain;
  border-radius: var(--d2-radius-md);
}
.d2-lightbox__schliessen,
.d2-lightbox__pfeil {
  position: absolute;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: hsl(0 0% 100% / 0.1);
  color: #fff;
  border: none;
  border-radius: var(--d2-radius-md);
  cursor: pointer;
  transition: background-color var(--d2-fast) var(--d2-ease);
}
.d2-lightbox__schliessen:hover,
.d2-lightbox__pfeil:hover { background: hsl(0 0% 100% / 0.2); }
.d2-lightbox__schliessen {
  top: var(--d2-space-4);
  right: var(--d2-space-4);
  width: 2.5rem;
  height: 2.5rem;
  font-size: 1.5rem;
  line-height: 1;
}
.d2-lightbox__pfeil {
  top: 50%;
  transform: translateY(-50%);
  width: 3rem;
  height: 3rem;
  font-size: 2rem;
  line-height: 1;
}
.d2-lightbox__pfeil--links { left: var(--d2-space-4); }
.d2-lightbox__pfeil--rechts { right: var(--d2-space-4); }
.d2-lightbox__pfeil[hidden] { display: none; }

/* ==========================================================================
   21. Status-Farbfeld (Ampelsystem, Modul Dokumentation) -- Klick auf das
   Farbfeld öffnet ein Popover mit allen Status als Farbkästen, Auswahl
   übernimmt per fetch() sofort ohne Speichern/Seitenwechsel. Ursprünglich
   nur in dokumentieren/index.php, jetzt global, da auch die Eingabemaske
   in mieter/zeigen.php dasselbe Farbfeld nutzt (siehe DRY-Vorgabe).
   ========================================================================== */
.d2-status-swatch {
  display: inline-block;
  width: 1.5rem;
  height: 1.5rem;
  border-radius: var(--d2-radius-sm);
  border: 1px solid hsl(var(--d2-border));
  cursor: pointer;
  padding: 0;
}
.d2-status-popover {
  display: none;
  position: absolute;
  z-index: 20;
  padding: var(--d2-space-2);
  gap: var(--d2-space-2);
}
.d2-status-popover.ist-offen { display: flex; }

.d2-regenbogen-regen {
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 9999;
  overflow: hidden;
}
.d2-regenbogen-regen__emoji {
  position: absolute;
  top: -10%;
  animation-name: d2-regenbogen-fallen;
  animation-timing-function: linear;
  animation-fill-mode: forwards;
}
.d2-regenbogen-regen__emoji span {
  display: inline-block;
  animation-name: d2-regenbogen-schaukeln;
  animation-timing-function: ease-in-out;
  animation-iteration-count: infinite;
}
@keyframes d2-regenbogen-fallen {
  from { top: -10%; }
  to { top: 110%; }
}
@keyframes d2-regenbogen-schaukeln {
  0%, 100% { transform: translateX(-10px) rotate(-8deg); }
  50% { transform: translateX(10px) rotate(8deg); }
}

.d2-logo-schweben {
  position: fixed;
  top: -300px;
  left: 50%;
  transform: translateX(-50%);
  height: 260px;
  width: auto;
  max-width: 90vw;
  z-index: 9999;
  pointer-events: none;
  transition: top 1.4s cubic-bezier(0.22, 1, 0.36, 1);
}
.d2-logo-schweben.ist-oben { top: 0; }

/* ==========================================================================
   22. Fachliche Bausteine der Module (nur hier definiert, damit kein Modul
   eigene <style>-Blöcke braucht)
   ========================================================================== */

/* Listenzeile mit Inhalt links und Aktionen rechts, Trennlinie zwischen den
   Zeilen (Backup-Liste). __actions ist die feste Aktionsspalte. Unter 480px
   stehen Inhalt und Aktionen untereinander, sonst schiebt ein langer,
   unumbrechbarer Inhalt (Dateiname) die Aktionen aus der Karte. */
.d2-list-row {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: var(--d2-space-3);
  padding: var(--d2-space-3) var(--d2-space-4);
}
.d2-list-row > :first-child { min-width: 0; overflow-wrap: anywhere; }
.d2-list-row:not(:last-child) { border-bottom: 1px solid hsl(var(--d2-border)); }
.d2-list-row__actions { display: flex; flex-direction: column; gap: var(--d2-space-2); }
@media (min-width: 480px) {
  .d2-list-row { flex-direction: row; justify-content: space-between; align-items: center; }
  .d2-list-row__actions { flex-shrink: 0; width: 9.5rem; }
}

/* Umrandete Auswahlzeile (Schlüsselart beim Verleih). */
.d2-option-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--d2-space-2);
  border: 1px solid hsl(var(--d2-border));
  border-radius: var(--d2-radius);
  padding: var(--d2-space-3);
}

/* Großer Einzelwert, z.B. die Schlüssel-Codierung. */
.d2-display-text { font-size: 2rem; font-weight: 700; text-align: center; margin: 0; }

/* Schwebende Großanzeige der Codierung beim Überfahren (Schlüsselliste). */
.d2-codierung-tooltip {
  position: fixed;
  z-index: 1000;
  pointer-events: none;
  max-width: min(80vw, 480px);
  padding: var(--d2-space-5) var(--d2-space-6);
  border-radius: var(--d2-radius-lg);
  font-size: 2.25rem;
  font-weight: 700;
  line-height: 1.2;
  text-align: center;
  color: #fff;
  text-shadow: 0 1px 3px rgba(0,0,0,0.5);
  background: linear-gradient(90deg, #ff5252, #ffb347, #ffe74c, #6bff7a, #4cc9ff, #7b6bff, #ff5ee0, #ff5252);
  background-size: 300% 100%;
  animation: d2-codierung-regenbogen 4s linear infinite;
  box-shadow: 0 10px 30px rgba(0,0,0,0.35);
}
@keyframes d2-codierung-regenbogen {
  0% { background-position: 0% 50%; }
  100% { background-position: 300% 50%; }
}

/* QR-Etikett (Schlüssel): Code oben, Codierung als Text darunter. Maße
   kommen als Inline-Werte aus den Druckeinstellungen, die Schriftgröße des
   Textes passt ein Skript an die Breite an. */
a:has(> .d2-qr-block) { display: inline-block; text-decoration: none; cursor: pointer; }
.d2-qr-block { margin: 0 auto; display: flex; flex-direction: column; border: 1px solid hsl(var(--d2-border)); border-radius: var(--d2-radius-sm); }
.d2-qr-block__code { margin: 0 auto; flex: 0 0 auto; }
.d2-qr-block__code svg { display: block; width: 100%; height: 100%; }
.d2-qr-text {
  flex: 1 1 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  white-space: nowrap;
  text-align: center;
  font-family: Helvetica, Arial, sans-serif;
}
/* QR-Code zum Verknüpfen eines Geräts (Signal). */
.d2-qr-box { width: 220px; height: 220px; }

/* Rettungsdienst-Symbol in der Mieterliste: gedämpft, beim Hover voll. */
.d2-rettung-btn img { opacity: 0.7; transition: opacity var(--d2-fast) var(--d2-ease); }
.d2-rettung-btn:hover img { opacity: 1; }

/* Bildergalerie als Raster aus Vorschaubildern. */
.d2-grid--bilder { grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: var(--d2-space-3); }
.d2-grid--bilder-sm { grid-template-columns: repeat(auto-fill, minmax(110px, 1fr)); gap: var(--d2-space-3); }
.d2-bild-thumb { width: 100%; height: 120px; object-fit: cover; border-radius: 4px; }
.d2-bild-thumb--sm { height: 90px; }

/* Kleine 16px-Symbole in Tabellenzellen, als Button oder Link. */
.d2-icon-button { background: none; border: none; padding: 0; cursor: pointer; display: flex; flex-shrink: 0; line-height: 0; }
.d2-icon-link { display: flex; flex-shrink: 0; line-height: 0; }
.d2-icon-sm { width: 16px; height: 16px; max-width: 16px; flex-shrink: 0; }

/* ==========================================================================
   23. Startseite, Anmeldung und Installer (eigene Seiten ohne Admin-Layout)
   ========================================================================== */

.d2-start-body { opacity: 1; transition: opacity 0.4s ease; }
.d2-start-body.d2-start-ausblenden { opacity: 0; }
.d2-start-shell {
  min-height: 100vh;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--d2-space-6);
}
.d2-start-logo {
  height: 120px;
  width: auto;
  opacity: 0;
  transform: translateY(-24px);
  animation: d2-start-logo-einblenden 0.7s cubic-bezier(0.22, 1, 0.36, 1) forwards;
}
@keyframes d2-start-logo-einblenden {
  from { opacity: 0; transform: translateY(-24px); }
  to { opacity: 1; transform: translateY(0); }
}
/* Ladeanimation: zwei um 70 Grad gekippte Ringe, deren Schatten umlaufen. */
.d2-start-loader {
  --color-1: #A19B9B;
  --color-2: #ff3d00;
  --size: 1px;

  position: relative;
  transform: rotateZ(45deg);
  perspective: calc(1000 * var(--size));
  border-radius: 50%;
  width: calc(48 * var(--size));
  height: calc(48 * var(--size));
  color: var(--color-1);
}
.d2-start-loader:before,
.d2-start-loader:after {
  content: '';
  display: block;
  position: absolute;
  top: 0;
  left: 0;
  width: inherit;
  height: inherit;
  border-radius: 50%;
  transform: rotateX(70deg);
  animation: d2-start-spin 1s linear infinite;
}
.d2-start-loader:after {
  color: var(--color-2);
  transform: rotateY(70deg);
  animation-delay: 0.4s;
}
@keyframes d2-start-spin {
  0%, 100% { box-shadow: 0.2em 0 0 0 currentcolor; }
  12% { box-shadow: 0.2em 0.2em 0 0 currentcolor; }
  25% { box-shadow: 0 0.2em 0 0 currentcolor; }
  37% { box-shadow: -0.2em 0.2em 0 0 currentcolor; }
  50% { box-shadow: -0.2em 0 0 0 currentcolor; }
  62% { box-shadow: -0.2em -0.2em 0 0 currentcolor; }
  75% { box-shadow: 0 -0.2em 0 0 currentcolor; }
  87% { box-shadow: 0.2em -0.2em 0 0 currentcolor; }
}
.d2-login-body { animation: d2-login-einblenden 0.4s ease; }
@keyframes d2-login-einblenden { from { opacity: 0; } to { opacity: 1; } }

/* Installer (app/Core/Install): breitere Spalte als die Anmeldung, weil
   Prüfliste und Formulare zweispaltig sind. Umschalter hell/dunkel oben
   rechts, da es keine Kopfleiste gibt. */
.d2-container--install { max-width: 640px; }
.d2-install-logo { display: block; height: 72px; width: auto; margin: 0 auto var(--d2-space-4); }
.d2-install-theme { position: fixed; top: var(--d2-space-3); right: var(--d2-space-3); z-index: 10; }

/* Schrittanzeige: nummerierte Punkte, erledigte mit Haken, der aktuelle
   hervorgehoben (aria-current="step"). */
.d2-steps { display: flex; gap: var(--d2-space-1); list-style: none; margin: 0; padding: 0; }
.d2-steps__item {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--d2-space-1);
  font-size: 0.7rem;
  text-align: center;
  color: hsl(var(--d2-muted-foreground));
}
.d2-steps__nummer {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.75rem;
  height: 1.75rem;
  border-radius: 50%;
  border: 1px solid hsl(var(--d2-border));
  background: hsl(var(--d2-card));
  font-weight: 600;
}
.d2-steps__label { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.d2-steps__item--aktiv { color: hsl(var(--d2-foreground)); font-weight: 600; }
.d2-steps__item--aktiv .d2-steps__nummer { background: hsl(var(--d2-primary)); border-color: hsl(var(--d2-primary)); color: hsl(var(--d2-primary-foreground)); }
.d2-steps__item--erledigt .d2-steps__nummer { background: hsl(var(--d2-success) / 0.15); border-color: hsl(var(--d2-success) / 0.5); color: hsl(var(--d2-success)); }
@media (min-width: 480px) {
  .d2-steps__item { font-size: 0.8rem; }
}

/* Prüfliste mit Ergebnis je Zeile (Badge rechts), Hinweis darunter. */
.d2-checklist__titel { margin: var(--d2-space-4) 0 var(--d2-space-2); font-size: 0.9rem; font-weight: 600; }
.d2-checklist { list-style: none; margin: 0; padding: 0; border: 1px solid hsl(var(--d2-border)); border-radius: var(--d2-radius-md); }
.d2-checklist__item {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--d2-space-1) var(--d2-space-3);
  padding: var(--d2-space-2) var(--d2-space-3);
  border-bottom: 1px solid hsl(var(--d2-border));
  font-size: 0.875rem;
}
.d2-checklist__item:last-child { border-bottom: none; }
.d2-checklist__name { min-width: 0; overflow-wrap: anywhere; }
.d2-checklist__hinweis { flex-basis: 100%; margin: 0; font-size: 0.8rem; color: hsl(var(--d2-muted-foreground)); }

/* ==========================================================================
   24. Hilfsklassen (Utilities)
   Stehen bewusst am Dateiende: bei gleicher Spezifität gewinnt die spätere
   Regel, so setzen sie sich gegen Komponentenwerte durch. Abstände, Größen
   und Schrift tragen zusätzlich !important, weil sie die früheren
   Inline-Styles ersetzen und wie diese Vorrang haben müssen. Anzeige- und
   Flex-Klassen haben kein !important, damit Skripte über element.style
   (z.B. style.display) weiterhin umschalten können.
   Werte ausschließlich aus der Token-Skala (--d2-space-1 bis -8).
   ========================================================================== */

/* Abstände außen: m = alle Seiten, mt/mb = oben/unten, my = oben und unten,
   mx-auto = horizontal zentrieren, ml-auto = nach rechts schieben. */
.d2-m-0 { margin: 0 !important; }
.d2-mt-0 { margin-top: 0 !important; }
.d2-mt-1 { margin-top: var(--d2-space-1) !important; }
.d2-mt-2 { margin-top: var(--d2-space-2) !important; }
.d2-mt-3 { margin-top: var(--d2-space-3) !important; }
.d2-mt-4 { margin-top: var(--d2-space-4) !important; }
.d2-mt-5 { margin-top: var(--d2-space-5) !important; }
.d2-mt-6 { margin-top: var(--d2-space-6) !important; }
.d2-mt-7 { margin-top: var(--d2-space-7) !important; }
.d2-mt-8 { margin-top: var(--d2-space-8) !important; }
.d2-mb-0 { margin-bottom: 0 !important; }
.d2-mb-1 { margin-bottom: var(--d2-space-1) !important; }
.d2-mb-2 { margin-bottom: var(--d2-space-2) !important; }
.d2-mb-3 { margin-bottom: var(--d2-space-3) !important; }
.d2-mb-4 { margin-bottom: var(--d2-space-4) !important; }
.d2-mb-6 { margin-bottom: var(--d2-space-6) !important; }
.d2-my-2 { margin-top: var(--d2-space-2) !important; margin-bottom: var(--d2-space-2) !important; }
.d2-my-3 { margin-top: var(--d2-space-3) !important; margin-bottom: var(--d2-space-3) !important; }
.d2-my-4 { margin-top: var(--d2-space-4) !important; margin-bottom: var(--d2-space-4) !important; }
.d2-my-5 { margin-top: var(--d2-space-5) !important; margin-bottom: var(--d2-space-5) !important; }
.d2-mx-auto { margin-left: auto !important; margin-right: auto !important; }
.d2-ml-auto { margin-left: auto !important; }

/* Abstände innen: p = alle Seiten, pt/pb/pl/pr = einzelne Seite,
   py = oben und unten. */
.d2-p-0 { padding: 0 !important; }
.d2-p-3 { padding: var(--d2-space-3) !important; }
.d2-p-4 { padding: var(--d2-space-4) !important; }
.d2-pt-0 { padding-top: 0 !important; }
.d2-pt-4 { padding-top: var(--d2-space-4) !important; }
.d2-pb-2 { padding-bottom: var(--d2-space-2) !important; }
.d2-pb-3 { padding-bottom: var(--d2-space-3) !important; }
.d2-pl-0 { padding-left: 0 !important; }
.d2-pl-1 { padding-left: var(--d2-space-1) !important; }
.d2-pl-2 { padding-left: var(--d2-space-2) !important; }
.d2-pl-4 { padding-left: var(--d2-space-4) !important; }
.d2-pl-5 { padding-left: var(--d2-space-5) !important; }
.d2-pr-1 { padding-right: var(--d2-space-1) !important; }
.d2-py-2 { padding-top: var(--d2-space-2) !important; padding-bottom: var(--d2-space-2) !important; }

/* Abstand zwischen Flex-/Grid-Kindern. */
.d2-gap-1 { gap: var(--d2-space-1) !important; }
.d2-gap-2 { gap: var(--d2-space-2) !important; }
.d2-gap-3 { gap: var(--d2-space-3) !important; }
.d2-gap-4 { gap: var(--d2-space-4) !important; }

/* Anzeige */
.d2-block { display: block; }
.d2-inline { display: inline; }
.d2-inline-block { display: inline-block; }
.d2-flex { display: flex; }
.d2-inline-flex { display: inline-flex; }
.d2-invisible { visibility: hidden; }
.d2-relative { position: relative; }
.d2-cursor-pointer { cursor: pointer; }
/* Gedämpft, z.B. nicht erreichbare Rechte in der Rollen-Matrix. */
.d2-dimmed { opacity: .55; }

/* Flex */
.d2-flex-col { flex-direction: column; }
.d2-flex-row { flex-direction: row; }
.d2-flex-wrap { flex-wrap: wrap; }
.d2-flex-nowrap { flex-wrap: nowrap; }
.d2-flex-1 { flex: 1; }
.d2-flex-none { flex: 0 0 auto; }
/* Wächst mit, bricht aber unter 320px in eine eigene Zeile um. */
.d2-flex-basis-320 { flex: 1 1 320px; }
/* Volle Zeile ganz vorn in einem Flex-Container (Statusmeldung über
   einem einzeiligen Formular). */
.d2-flex-fullrow { flex-basis: 100%; order: -1; }
.d2-shrink-0 { flex-shrink: 0; }
.d2-min-w-0 { min-width: 0; }
.d2-items-center { align-items: center; }
.d2-items-start { align-items: flex-start; }
.d2-items-end { align-items: flex-end; }
.d2-self-start { align-self: flex-start; }
.d2-justify-start { justify-content: flex-start; }
.d2-justify-center { justify-content: center; }
.d2-justify-end { justify-content: flex-end; }
.d2-justify-between { justify-content: space-between; }

/* Größen */
.d2-w-full { width: 100% !important; }
.d2-w-5rem { width: 5rem !important; }
.d2-w-6rem { width: 6rem !important; }
.d2-w-7rem { width: 7rem !important; }
.d2-h-auto { height: auto !important; }
.d2-maxw-120 { max-width: 120px !important; }
.d2-maxw-140 { max-width: 140px !important; }
.d2-maxw-160 { max-width: 160px !important; }
.d2-maxw-220 { max-width: 220px !important; }
.d2-maxw-240 { max-width: 240px !important; }
.d2-maxw-320 { max-width: 320px !important; }
.d2-maxw-420 { max-width: 420px !important; }
.d2-maxw-480 { max-width: 480px !important; }
.d2-maxw-512 { max-width: 512px !important; }
.d2-maxw-640 { max-width: 640px !important; }
.d2-maxw-720 { max-width: 720px !important; }

/* Rahmen als Trennlinie zwischen Zeilen oder Bereichen. */
.d2-border-t { border-top: 1px solid hsl(var(--d2-border)) !important; }
.d2-border-b { border-bottom: 1px solid hsl(var(--d2-border)) !important; }

/* Listen */
.d2-list-none { list-style: none !important; }
.d2-list-tight { padding-left: 1.2em !important; }
.d2-list-inset { margin-left: 1.2em !important; }

/* Text */
.d2-text-center { text-align: center !important; }
.d2-nowrap { white-space: nowrap !important; }
.d2-text-pre { white-space: pre-wrap !important; }
.d2-text-base { font-size: 1rem !important; }
.d2-text-xs { font-size: 0.8rem !important; }
.d2-font-normal { font-weight: 400 !important; }
.d2-font-mono { font-family: var(--d2-font-mono) !important; }
.d2-text-danger { color: hsl(var(--d2-destructive)) !important; }
