/* =========================================================================
   newways.suite – Design System
   Handgeschrieben, ohne Build-Schritt. Alle Farben laufen über Tokens,
   dadurch funktionieren Hell-/Dunkelmodus und Kunden-Branding automatisch.

   Seit 1.17.0 laufen auch die Maße über Tokens: eine Abstandsskala im
   4-px-Raster (--space-1 … --space-12), eine Schriftskala und Komponenten-
   Tokens (--card-pad, --cell-py, --control-h …). Warum welche Werte:
   docs/notizen/oberflaeche-1.17.md. Token-NAMEN bleiben stehen, auch alte –
   695 Inline-Stile und elf <style>-Blöcke in den Ansichten hängen daran.
   ========================================================================= */

/* ---------- 1. Reset ---------- */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; }
html { -webkit-text-size-adjust: 100%; tab-size: 4; }
/* Auf dem Telefon ist 100vh die Höhe OHNE Adresszeile – also mehr, als man
   sieht, solange die Leiste eingeblendet ist. Eine Seite, die genau
   hineinpasst, ließ sich deshalb um ein paar Pixel schieben: das Wackeln,
   das man nicht erklären kann. dvh misst, was wirklich da ist; die Zeile
   davor bleibt für ältere Browser stehen.
   overscroll-behavior nimmt zusätzlich das Gummiband am Rand. */
body { min-height: 100vh; line-height: 1.6; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-rendering: optimizeLegibility; }
body { min-height: 100dvh; overscroll-behavior-y: contain; }
img, svg, video, canvas { display: block; max-width: 100%; height: auto; }
input, button, textarea, select { font: inherit; color: inherit; }
button { background: none; border: 0; cursor: pointer; }
a { color: inherit; text-decoration: none; }
ul, ol { list-style: none; padding: 0; }
table { border-collapse: collapse; width: 100%; }
/* `hidden` gewinnt immer. Die Browser-Vorgabe `[hidden] { display: none }`
   verliert gegen jede Autorenregel – ein Kasten mit `display: flex` blieb
   trotz `hidden` sichtbar (Konsent-Kasten 1.12.2, Arbeitsregeln). Die örtlichen
   Flicken (etwa `.ads-consent[hidden]`) bleiben trotzdem stehen. */
[hidden] { display: none !important; }
/* Der Fokusring liegt mit Abstand um das Element und folgt dessen Radius –
   eine Pille bleibt rund. Früher setzte diese Zeile `border-radius: 6px`
   AM Element selbst, und ein Knopf wurde beim Tabben eckig. */
:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
::selection { background: color-mix(in srgb, var(--accent) 25%, transparent); }

/* ---------- 2. Tokens ----------
   Die Farben sind warm und leicht ins Olivgrüne gezogen – dieselbe Familie
   wie die Produktseite unter newways.consulting/suite. Ein neutrales Grau
   würde daneben kalt und beliebig wirken; die Neutraltöne tragen deshalb
   einen Hauch der Markenfarbe.

   Gold hat in dieser Oberfläche genau eine Bedeutung, und die ist nicht
   dekorativ: „Sie sind am Zug." Wo Gold auftaucht, wartet etwas auf eine
   Entscheidung. Wird es für Schmuck verwendet, verliert es diese Bedeutung –
   deshalb kommt es an keiner anderen Stelle vor.
   ---------------------------------------------------------------------- */
:root {
  --brand:            #1a2d09;
  --accent:           #3e6d15;
  --accent-2:         #71610c;

  /* Gold: ausschließlich für „Sie sind am Zug". */
  --gold:             #cbae15;
  --gold-ink:         #6e5e0b;
  --gold-soft:        color-mix(in srgb, #cbae15 16%, transparent);

  /* Der Grund ist fast weiß und kaum warm; die Karten darauf sind weiß.
     Der Unterschied trägt die Gliederung – dafür braucht es keine schweren
     Linien und keine Muster. Seit 1.18.0 liegt auf dem Grund wieder ein sehr
     leiser Verlauf: zwei weiche Flecken in der Akzentfarbe (4 %) und im
     zweiten Markenton (3 %). Nicht als Muster, sondern damit das Glas der
     Seitenleiste und der Kopfleiste etwas hat, das es verwischen kann – über
     einer einfarbigen Fläche ist Glas unsichtbar. Gold kommt darin NICHT vor:
     Gold heißt „Sie sind am Zug", nie Dekoration (1.17 hat genau so ein
     Muster entfernt). Kein `background-attachment: fixed`, der Verlauf
     scrollt mit – bei 64 rem Durchmesser sieht man davon nichts. */
  --bg:               #f7f7f4;
  --bg-pattern:
    radial-gradient(64rem 44rem at 12% -12%, color-mix(in srgb, var(--accent) 4%, transparent), transparent 62%),
    radial-gradient(52rem 40rem at 104% 104%, color-mix(in srgb, var(--accent-2) 3%, transparent), transparent 62%);
  --surface:          #ffffff;
  /* --surface-2 ist zugleich der Rechengrund für --accent-text in
     components/head.php ($grundHell). Wer ihn ändert, zieht head.php nach –
     die Prüfung „Oberfläche: Rechengrund der Akzentschrift" vergleicht beide. */
  --surface-2:        #f1f1ec;
  --surface-3:        #e7e7e0;
  --surface-inset:    #fafaf8;
  /* Der zarte Olivton für ruhige Flächen – aus der Produktseite übernommen. */
  --wash:             #edf1e6;

  /* Warmes, leicht olivstichiges Fast-Schwarz statt eines kühlen Graus. */
  --text:             #16200b;
  --text-muted:       #5b6152;
  /* Abgedunkelt statt aufgehellt: 5,27:1 auf Weiß, 4,65:1 auf --surface-2.
     Vorher 3,42:1 – und dieses Grau trug Tabellenköpfe, Hinweise, Metazeilen. */
  --text-subtle:      #686e60;
  --text-inverse:     #ffffff;
  /* Wurde an drei Stellen benutzt (GoBD, Konsent-Kasten), aber nie angelegt –
     die Deklaration war ungültig und der Text erbte die volle Farbe. */
  --text-soft:        var(--text-muted);

  /* Linien sind Haarlinien: sie trennen, sie rahmen nicht ein. */
  --border:           rgba(22, 32, 11, .08);
  --border-strong:    rgba(22, 32, 11, .15);
  --border-accent:    color-mix(in srgb, var(--accent) 34%, transparent);

  --success:          #2a7247;
  --success-soft:     color-mix(in srgb, #2f7d4f 12%, transparent);
  --warning:          #945608;
  --warning-soft:     color-mix(in srgb, #c9791a 14%, transparent);
  --danger:           #b3271f;
  --danger-soft:      color-mix(in srgb, #b3271f 11%, transparent);
  --info:             #1c5f7a;
  --info-soft:        color-mix(in srgb, #1c5f7a 11%, transparent);
  --accent-soft:      color-mix(in srgb, var(--accent) 13%, transparent);

  /* Der Fokusring nimmt die Schriftrolle der Marke, nicht die Flächenrolle:
     Gold als Ring auf Weiß kam auf 2,2:1, --accent-text liegt über 4,5:1. */
  --focus:            var(--accent-text);
  /* Wird von components/head.php je Marke überschrieben. Die Rückfallwerte
     hier gelten für Ausgaben ohne Kopfbereich (PDF-Vorschau, Mailvorlagen). */
  --accent-text:      var(--accent);
  --accent-on:        #ffffff;

  /* Weicher, nicht runder: 8 · 12 · 16 · 20 · 24, Pillen 999. */
  --radius-xs: 8px;
  --radius-sm: 12px;
  --radius:    16px;
  --radius-lg: 20px;
  --radius-xl: 24px;
  --radius-full: 999px;

  /* Schatten mit einem Hauch Olivgrün statt reinem Schwarz – auf warmem
     Papier wirkt ein neutraler Schatten schmutzig. Mehrlagig und flach:
     eine enge Lage für die Kante, eine weite, sehr leichte für die Höhe. */
  --shadow-xs: 0 1px 2px rgba(22, 32, 11, .05);
  --shadow-sm: 0 1px 2px rgba(22, 32, 11, .04), 0 2px 8px -2px rgba(22, 32, 11, .04);
  --shadow:    0 1px 2px rgba(22, 32, 11, .04), 0 8px 24px -8px rgba(22, 32, 11, .10);
  --shadow-lg: 0 2px 6px -1px rgba(22, 32, 11, .05), 0 20px 44px -12px rgba(22, 32, 11, .16);
  --shadow-xl: 0 4px 12px -2px rgba(22, 32, 11, .06), 0 32px 72px -18px rgba(22, 32, 11, .24);

  /* ---- Abstand: 4-px-Raster ---- */
  --space-1:  .25rem;   /*  4 px */
  --space-2:  .5rem;    /*  8 px */
  --space-3:  .75rem;   /* 12 px */
  --space-4:  1rem;     /* 16 px */
  --space-5:  1.25rem;  /* 20 px */
  --space-6:  1.5rem;   /* 24 px */
  --space-7:  1.75rem;  /* 28 px */
  --space-8:  2rem;     /* 32 px */
  --space-9:  2.25rem;  /* 36 px */
  --space-10: 2.5rem;   /* 40 px */
  --space-11: 2.75rem;  /* 44 px */
  --space-12: 3rem;     /* 48 px */

  /* ---- Schrift: acht Stufen, nichts unter 12 px ---- */
  --fs-xs:   .75rem;    /* 12 px – Untergrenze */
  --fs-sm:   .8125rem;  /* 13 px */
  --fs-md:   .875rem;   /* 14 px */
  --fs-base: .9375rem;  /* 15 px */
  --fs-lg:   1.0625rem; /* 17 px */
  --fs-xl:   1.25rem;   /* 20 px */
  --fs-2xl:  clamp(1.25rem, 1.1rem + .5vw, 1.5rem);
  --fs-3xl:  clamp(1.625rem, 1.25rem + 1.1vw, 2.125rem);
  --fw-regular: 400;
  --fw-medium:  500;
  --fw-semibold: 600;
  --lh-tight: 1.2;
  --lh-snug:  1.4;
  --lh-body:  1.6;

  /* ---- Komponenten ---- */
  --card-pad:    1.5rem;              /* Innenabstand einer Karte */
  --card-gap:    clamp(1rem, 1.8vw, 1.5rem); /* zwischen Karten im Raster */
  --gap-section: 2rem;                /* zwischen Seitenkopf und Inhalt, zwischen Abschnitten */
  --cell-py:     .8125rem;            /* Tabellenzelle: 13 + 13 + Zeile ≈ 48 px */
  --cell-px:     1rem;
  --control-h:   2.625rem;            /* 42 px am Rechner, 44 px am Telefon */
  --control-h-sm: 2.125rem;           /* 34 px am Rechner, 44 px am Telefon */
  --control-radius: var(--radius-sm);
  /* Deckfarbe hinter dem Scroll-Schatten einer Tabelle: die Fläche, auf der
     sie liegt. In Karten ist das --surface. */
  --scroll-cover: var(--surface);

  /* Die Unschärfe des Glases. Welche Flächen Glas tragen und mit welcher
     Deckung, steht am Ende dieses Blocks (--glass-bg, --glass-surface) und
     in docs/notizen/oberflaeche-1.18.md. */
  --glass-blur: blur(20px) saturate(180%);

  /*
   * Schriften: die des jeweiligen Betriebssystems – San Francisco auf dem
   * Mac, Segoe UI Variable unter Windows, Roboto auf Android. Das ist keine
   * Sparmaßnahme, sondern eine Entscheidung: es wird keine Schriftdatei
   * geladen (kein fremder Server, kein Ruckeln beim ersten Aufbau), und die
   * Oberfläche sieht auf jedem Gerät nach diesem Gerät aus. Dieselbe Wahl wie
   * auf der Produktseite, damit Werbung und Werkzeug aus einem Guss wirken.
   */
  --font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI Variable Text", "Segoe UI",
               "Helvetica Neue", Roboto, "Noto Sans", Arial, sans-serif;
  --font-display: -apple-system, BlinkMacSystemFont, "Segoe UI Variable Display",
               "Segoe UI Semibold", "Segoe UI", "Helvetica Neue", Roboto, Arial, sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;

  --sidebar-w: 256px;
  --topbar-h: 60px;
  /* Höhe der unteren Leiste auf dem Telefon – Abstände richten sich danach. */
  --tabbar-h: 4.125rem;
  --page-max: 1440px;

  --ease: cubic-bezier(.22, 1, .36, 1);
  /* Sanft, aber nicht träge: 150–200 ms. */
  --dur: .18s;
  --dur-fast: .15s;

  color-scheme: light;

  /* ---- Glas (1.18): Material für Leisten, Menüs, Dialoge, Meldungen ----
     Deckung ist Rechnung, nicht Gefühl: 90 % sind der Wert, bei dem jede
     Schrift, die auf Glas steht (--text, --text-muted, --danger), auch über
     einem schwarzen Foto und über reinem Weiß 4,5:1 hält – hell und dunkel
     gerechnet, die Zahlen stehen in der Notiz und werden im Prüfstand
     nachgerechnet („Oberfläche: Glas 1.18"). --text-subtle steht NICHT auf
     Glas: jede Glasfläche setzt es auf --text-muted um (bei 90 % kam es über
     Schwarz nur auf 3,9:1). --glass-bg ist Glas im Seitengrund (Seitenleiste,
     Kopfleiste), --glass-surface Glas in der Kartenfarbe (alles, was
     schwebt). --glass-edge ist die Lichtkante oben, --glass-tint die Pille des
     gewählten Punkts (Akzent, sehr schwach, deckend). */
  --glass-bg:      color-mix(in srgb, var(--bg) 90%, transparent);
  --glass-surface: color-mix(in srgb, var(--surface) 90%, transparent);
  --glass-edge:    rgba(255, 255, 255, .65);
  --glass-shadow:  0 1px 2px rgba(22, 32, 11, .05), 0 16px 40px -12px rgba(22, 32, 11, .18);
  --glass-tint:    color-mix(in srgb, var(--accent) 10%, var(--surface));
  /* Karten bleiben deckend (Inhalt), tragen aber im Hellen eine kaum
     sichtbare Lichtkante oben; im Dunkeln steckt sie schon in --shadow-sm. */
  --card-edge:     rgba(255, 255, 255, .7);
}

html[data-theme="dark"] {
  /* --brand/--accent liefert die Vorlage aufgehellt aus (siehe head.php). */
  --accent-2:         #d8bd3f;
  --gold:             #e0c445;
  --gold-ink:         #f0dc8e;
  --gold-soft:        color-mix(in srgb, #e0c445 15%, transparent);

  /* Auch im Dunkeln kein reines Schwarz: ein sehr dunkles Olivgrau. Die
     Karten liegen eine deutliche Stufe heller als der Grund – vorher hoben
     sie sich kaum ab, und die Seite wirkte wie eine einzige Fläche. */
  --bg:               #0c0e0a;
  --bg-pattern:
    radial-gradient(64rem 44rem at 12% -12%, color-mix(in srgb, var(--accent) 6%, transparent), transparent 62%),
    radial-gradient(52rem 40rem at 104% 104%, color-mix(in srgb, var(--accent-2) 4%, transparent), transparent 62%);
  --surface:          #171a13;
  /* Rechengrund für --accent-text im Dunkeln ($grundDunkel in head.php). */
  --surface-2:        #1f2319;
  --surface-3:        #2a2f23;
  --surface-inset:    #121510;
  --wash:             #1a2013;

  --text:             #f1f2ec;
  --text-muted:       #a8ad9e;
  /* 5,58:1 auf --surface, 5,07:1 auf --surface-2 (vorher 4,46 / 4,08). */
  --text-subtle:      #8e9384;
  --text-inverse:     #0b0d08;

  --border:           rgba(241, 242, 236, .09);
  --border-strong:    rgba(241, 242, 236, .16);

  --success:          #5fbe86;
  --warning:          #e0a54a;
  --danger:           #ef7a72;
  --info:             #6ec1e0;

  /* Im Dunkeln trägt ein Schatten kaum; die Kante kommt von einer feinen
     Lichtlinie oben in der Fläche. */
  --shadow-xs: 0 1px 2px rgba(0, 0, 0, .45);
  --shadow-sm: inset 0 1px 0 rgba(255, 255, 255, .035), 0 1px 2px rgba(0, 0, 0, .4);
  --shadow:    inset 0 1px 0 rgba(255, 255, 255, .04), 0 8px 24px -8px rgba(0, 0, 0, .6);
  --shadow-lg: inset 0 1px 0 rgba(255, 255, 255, .05), 0 20px 44px -12px rgba(0, 0, 0, .7);
  --shadow-xl: inset 0 1px 0 rgba(255, 255, 255, .05), 0 32px 72px -18px rgba(0, 0, 0, .8);

  color-scheme: dark;

  /* Glas im Dunkeln: dieselbe Deckung (gerechnet: 90 % halten auch hier,
     --text-muted über reinem Weiß 6,6:1 auf --glass-bg). Die Lichtkante ist
     nur ein Hauch, der Schatten schwarz statt oliv, die Pille etwas kräftiger
     getönt, damit sie sich vom dunklen Grund abhebt. */
  --glass-bg:      color-mix(in srgb, var(--bg) 90%, transparent);
  --glass-surface: color-mix(in srgb, var(--surface) 90%, transparent);
  --glass-edge:    rgba(255, 255, 255, .07);
  --glass-shadow:  0 1px 2px rgba(0, 0, 0, .5), 0 20px 48px -12px rgba(0, 0, 0, .7);
  --glass-tint:    color-mix(in srgb, var(--accent) 16%, var(--surface));
  --card-edge:     rgba(255, 255, 255, 0);
}

/* Am Telefon: 44 px hohe Bedienelemente – die Größe, die ein Daumen
   zuverlässig trifft. */
@media (max-width: 1023px) {
  :root { --control-h: 2.75rem; --control-h-sm: 2.75rem; --card-pad: 1.25rem; --gap-section: 1.5rem; }
}
@media (max-width: 640px) {
  :root { --card-pad: 1.125rem; --cell-px: .875rem; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}

/* Inline-Icons ohne eigene Klasse bekommen eine sinnvolle Standardgröße */
/* Symbole: eine feste Größe, die der Reset nicht zusammendrückt.
   `max-width: 100%` (Zeile 19) gilt für Bilder; ein Symbol in einem engen
   Kasten würde daran auf wenige Pixel schrumpfen und als Punkt erscheinen. */
.ic { width: 1.15em; height: 1.15em; max-width: none; flex: none; }
svg:not([class]), svg[class=""] { width: 1.15em; height: 1.15em; }

/* ---------- 3. Basis ---------- */
body {
  font-family: var(--font-sans);
  background: var(--bg);
  /* Kein `background-attachment: fixed` mehr: es zeichnete bei jedem
     Scrollschritt neu, und iOS übergeht es ohnehin. */
  background-image: var(--bg-pattern);
  color: var(--text);
  font-size: 15px;
  font-optical-sizing: auto;
  /* Kein pauschales Negativ-Tracking: SF regelt die Laufweite selbst, und
     auf Segoe oder Roboto wirkte der Text gequetscht. */
  letter-spacing: 0;
}

/* Überschriften: 600, nicht 640–700. Negatives Tracking nur, wo die Schrift
   groß ist – unter 20 px bleibt die Laufweite, wie die Schrift sie mitbringt. */
h1, h2, h3, h4 { font-family: var(--font-display); font-weight: 600; letter-spacing: 0; line-height: var(--lh-tight); color: var(--text); text-wrap: balance; }
h1 { font-size: var(--fs-3xl); letter-spacing: -0.022em; line-height: 1.15; }
h2 { font-size: var(--fs-2xl); letter-spacing: -0.015em; }
h3 { font-size: var(--fs-lg); }
h4 { font-size: var(--fs-base); }
p  { color: var(--text-muted); }
small { font-size: var(--fs-sm); }
strong, b { font-weight: 600; color: var(--text); }
/* Nie unter 12 px: `code` in einem 12-px-Hinweis landete sonst bei 10,5 px. */
code, pre, .mono { font-family: var(--font-mono); font-size: max(.875em, 12px); }
hr { border: 0; border-top: 1px solid var(--border); margin: var(--space-6) 0; }

.display {
  font-family: var(--font-display);
  font-size: clamp(2rem, 1.2rem + 3.2vw, 3.4rem);
  font-weight: 600;
  letter-spacing: -0.03em;
  line-height: 1.05;
}
/* Kleinbeschriftung über einer Überschrift: Satzschreibung statt
   gesperrter Versalien – das technische Stakkato war einer der Gründe,
   warum die Oberfläche dicht wirkte. */
.eyebrow {
  font-size: var(--fs-sm); font-weight: 500; letter-spacing: 0;
  text-transform: none; color: var(--text-subtle); line-height: var(--lh-snug);
}
.lead { font-size: var(--fs-lg); color: var(--text-muted); line-height: var(--lh-body); }
.numeric { font-variant-numeric: tabular-nums; font-feature-settings: "tnum" 1; }

/* ---------- 4. Layout: App-Shell ---------- */
.shell { display: flex; min-height: 100vh; }
.shell { min-height: 100dvh; }

/* Die Seitenleiste ist seit 1.18.0 Glas im Seitengrund (--glass-bg, 90 %).
   1.17 hatte das Glas hier bewusst weggelassen: über einem einfarbigen Grund
   verwischt es nichts und kostet nur Rechenzeit. Jetzt liegt unter ihr der
   leise Verlauf des Seitengrunds (--bg-pattern) – die Leiste bekommt dadurch
   Tiefe, ohne dass Inhalt unter ihr durchläuft (die Seite beginnt rechts von
   ihr, --sidebar-w). Eine Haarlinie trennt sie weiterhin. Am Telefon bleibt
   die Schublade deckend (Abschnitt 23). --text-subtle wird auf Glas zu
   --text-muted (Deckungsrechnung, siehe Token-Block). */
.sidebar {
  position: fixed; inset: 0 auto 0 0; width: var(--sidebar-w); z-index: 60;
  display: flex; flex-direction: column; gap: var(--space-1);
  padding: var(--space-5) var(--space-3) var(--space-4);
  background: var(--glass-bg);
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  border-right: 1px solid var(--border);
  box-shadow: inset 0 1px 0 var(--glass-edge);
  --text-subtle: var(--text-muted);
  transition: transform var(--dur) var(--ease);
}
.sidebar__brand { display: flex; align-items: center; gap: var(--space-3); padding: var(--space-1) var(--space-3) var(--space-5); }
.sidebar__logo { height: 30px; width: auto; max-width: 160px; object-fit: contain; }
.sidebar__logo--dark { display: none; }
html[data-theme="dark"] .sidebar__logo--light { display: none; }
html[data-theme="dark"] .sidebar__logo--dark { display: block; }
.sidebar__wordmark { font-weight: 600; letter-spacing: -0.02em; font-size: var(--fs-lg); }
.sidebar__wordmark span { color: var(--text-subtle); font-weight: 400; }
.sidebar__section { padding: var(--space-5) var(--space-3) var(--space-2); }
.sidebar__nav { display: flex; flex-direction: column; gap: 2px; overflow-y: auto; flex: 1; padding-bottom: var(--space-2); }
.sidebar__footer { border-top: 1px solid var(--border); padding-top: var(--space-3); margin-top: var(--space-1); }

/* Navigationspunkt: 500, 38 px hoch, die Auswahl als schwebende Pille statt
   des 3-px-Balkens am Rand: --glass-tint (Akzent 10 % in der Kartenfarbe,
   deckend), Lichtkante oben, --shadow-xs. Das Symbol trägt die Marke
   (--accent-text ist für Schrift gerechnet und reicht damit für ein Symbol
   allemal; die Beschriftung selbst ist --text). */
.nav-item {
  display: flex; align-items: center; gap: var(--space-3);
  min-height: 2.375rem; padding: var(--space-2) var(--space-3); border-radius: var(--radius-sm);
  color: var(--text-muted); font-weight: 500; font-size: var(--fs-md); line-height: var(--lh-snug);
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
  position: relative;
}
.nav-item svg { width: 18px; height: 18px; flex: none; opacity: .8; }
.nav-item:hover { background: color-mix(in srgb, var(--text) 5%, transparent); color: var(--text); }
.nav-item.is-active { background: var(--glass-tint); color: var(--text); font-weight: 500; box-shadow: inset 0 1px 0 var(--glass-edge), var(--shadow-xs); }
.nav-item.is-active svg { color: var(--accent-text); opacity: 1; }
.nav-item.is-active::before { content: none; }
.nav-item__count {
  margin-left: auto; font-size: var(--fs-xs); font-weight: 500; min-width: 20px; text-align: center;
  padding: 0 .375rem; border-radius: var(--radius-full); font-variant-numeric: tabular-nums;
  background: var(--surface-3); color: var(--text-muted);
}
.nav-item.is-active .nav-item__count { background: var(--accent); color: var(--accent-on); }

.main { flex: 1; min-width: 0; margin-left: var(--sidebar-w); display: flex; flex-direction: column; }

/* Die Kopfleiste: Glas im Seitengrund, 90 % (vorher 80 – bei 80 fiel
   --text-muted über einem schwarzen Foto auf 3,7:1). */
.topbar {
  position: sticky; top: 0; z-index: 40; height: var(--topbar-h);
  display: flex; align-items: center; gap: var(--space-2);
  padding: 0 clamp(1rem, 3vw, 2.5rem);
  background: var(--glass-bg);
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  border-bottom: 1px solid var(--border);
  box-shadow: inset 0 1px 0 var(--glass-edge);
  --text-subtle: var(--text-muted);
}
.topbar__title { font-weight: 600; font-size: var(--fs-base); min-width: 0; }
.topbar__spacer { flex: 1; }
/* Die Suche in der Kopfleiste – vorher komplett als Inline-Stil in
   layouts/app.php und damit an keinem Token. */
.topbar__search { width: 100%; max-width: 280px; }
.topbar__search-box { position: relative; }
.topbar__search-icon {
  position: absolute; left: .75rem; top: 50%; transform: translateY(-50%);
  display: flex; color: var(--text-subtle); pointer-events: none;
}
.topbar__search-icon svg { width: 16px; height: 16px; }
/* Das Suchfeld liegt als hellere Pille AUF dem Glas (Kartenfarbe 60 %), nicht
   als dunklere Tönung darin: eine Tönung mit der Textfarbe drückte den
   Platzhalter über einem schwarzen Foto unter 4,5:1, die hellere Pille hebt
   ihn darüber (gerechnet: 5,7:1 mit --text-muted). Im Fokus wird sie deckend. */
.topbar__search .input {
  padding-left: 2.25rem; border-radius: var(--radius-full);
  background: color-mix(in srgb, var(--surface) 60%, transparent); border-color: transparent;
  box-shadow: inset 0 1px 0 var(--glass-edge), 0 0 0 1px var(--border);
}
.topbar__search .input:hover { border-color: transparent; background: color-mix(in srgb, var(--surface) 80%, transparent); }
.topbar__search .input:focus { background: var(--surface); border-color: var(--focus); }
/* Die Knöpfe der Kopfleiste: der rote Punkt der Benachrichtigungen und die
   Menüs, deren Lage vorher inline stand. */
.topbar__bell { position: relative; }
.topbar__dot { position: absolute; top: 8px; right: 9px; background: var(--danger); box-shadow: 0 0 0 2px var(--bg); }
/* Lage und Breite der Menüs (--wide, --up) stehen in Abschnitt 12 HINTER
   `.dropdown__menu` – hier oben verloren sie gegen die Grundregel. */

.page { padding: clamp(1.5rem, 3vw, 2.5rem) clamp(1rem, 3vw, 2.5rem) 5rem; width: 100%; max-width: var(--page-max); margin-inline: auto; }
.page--narrow { max-width: 940px; }
.page--wide { max-width: 1720px; }
/* Das Kundenportal ist breiter als eine Formularseite, schmaler als die
   Anwendung. Stand vorher als `style="max-width:1240px"` am Element. */
.page--portal { max-width: 1240px; }

.page-head { display: flex; flex-wrap: wrap; align-items: flex-end; gap: var(--space-4) var(--space-6); margin-bottom: var(--gap-section); }
.page-head__text { min-width: 0; flex: 1 1 320px; }
.page-head__actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); }
.page-head h1 { margin-bottom: var(--space-2); }
.page-head .eyebrow { display: block; margin-bottom: var(--space-1); }
.page-head .lead { max-width: 68ch; }

/* ---------- 5. Karten & Flächen ---------- */
/* Eine Karte hat eine Haarlinie und einen kaum sichtbaren Schatten – nicht
   beides schwer. Kopf und Fuß behalten ihre Haarlinie: 260 Kartenköpfe
   tragen direkt Listen, Tabellen oder Formulare, und ohne Linie verschwamm
   der Kopf mit dem Inhalt.
   Karten bleiben DECKEND (Apples eigene Regel für Liquid Glass: Inhalt liegt
   auf einer eigenen, deckenden Ebene; Glas gehört an Navigation und
   Bedienung). Neu seit 1.18.0 ist nur die Lichtkante oben (--card-edge,
   im Dunkeln aus, dort trägt --shadow-sm sie schon). */
.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: inset 0 1px 0 var(--card-edge), var(--shadow-sm);
  overflow: hidden;
}
.card--flat { box-shadow: none; }
.card--inset { background: var(--surface-inset); --scroll-cover: var(--surface-inset); }
/* Die Glaskarte: für Kennzahlen-Kacheln, die über dem Verlauf des
   Seitengrunds liegen – nicht für Tabellen und Formulare (Lesbarkeit; und
   ein Scroll-Schatten braucht eine deckende Fläche). Bis 1.17 stand hier
   deckend --surface unter einem Namen, der Glas versprach; in keiner
   Ansicht benutzt. Wer sie einsetzt, schreibt `card card--glass`. */
.card--glass {
  background: var(--glass-surface);
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  box-shadow: inset 0 1px 0 var(--glass-edge), var(--shadow-sm);
  --text-subtle: var(--text-muted);
}
.card__header {
  display: flex; align-items: center; gap: var(--space-3); flex-wrap: wrap;
  min-height: 3.5rem;
  padding: var(--space-4) var(--card-pad); border-bottom: 1px solid var(--border);
}
/* Kartenköpfe tragen mal <h2 class="text-lg">, mal <h3>: dieselbe Größe
   für beide, damit 260 Kartenköpfe in 61 Dateien gleich aussehen. */
.card__header h3, .card__header h2 { flex: 1; min-width: 0; font-size: var(--fs-lg); font-weight: 600; letter-spacing: -0.005em; }
.card__body { padding: var(--card-pad); }
.card__body--tight { padding: var(--space-3) var(--space-4); }
.card__footer { padding: var(--space-4) var(--card-pad); border-top: 1px solid var(--border); background: var(--surface-inset); }
.card--link { transition: box-shadow var(--dur) var(--ease), border-color var(--dur) var(--ease); }
.card--link:hover { box-shadow: var(--shadow); border-color: var(--border-strong); }

.panel { background: var(--surface-2); border-radius: var(--radius); padding: var(--space-4) var(--space-5); }

.hero {
  position: relative; overflow: hidden;
  border-radius: var(--radius-xl);
  padding: clamp(1.75rem, 4vw, 3.25rem);
  background:
    linear-gradient(135deg, color-mix(in srgb, var(--accent) 90%, #000) 0%, color-mix(in srgb, var(--accent) 55%, var(--accent-2)) 100%);
  color: #fff;
  box-shadow: var(--shadow);
}
.hero::after {
  content: ""; position: absolute; inset: auto -10% -60% auto; width: 460px; height: 460px;
  background: radial-gradient(circle, rgba(255,255,255,.22), transparent 65%);
  pointer-events: none;
}
.hero h1, .hero h2, .hero p, .hero .eyebrow { color: #fff; }
.hero p { color: rgba(255,255,255,.82); }
.hero .eyebrow { color: rgba(255,255,255,.72); }

/* ---------- 6. Raster ---------- */
.grid { display: grid; gap: var(--card-gap); }
.grid--2 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 320px), 1fr)); }
.grid--3 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr)); }
.grid--4 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 210px), 1fr)); }
.grid--cards { grid-template-columns: repeat(auto-fill, minmax(min(100%, 300px), 1fr)); }
/* Fünf Kennzahlen (Objektliste): mittel drei je Zeile, breit alle fünf –
   nie 4 + 1. Steht hinter .grid--4, damit es gewinnt. Am Telefon gilt die
   wischbare Reihe (.kennzahlen, Abschnitt 22b). */
.grid--5 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
@media (min-width: 720px)  { .grid--5 { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (min-width: 1300px) { .grid--5 { grid-template-columns: repeat(5, minmax(0, 1fr)); } }
/* `.span-full` wirkte nur in .form-grid; in einem .grid--2 (Verifactu) stand
   dafür ein Inline-Stil. */
.grid > .span-full { grid-column: 1 / -1; }
.split { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--card-gap); }
/* Zwei Spalten erst, wenn die Hauptspalte daneben noch trägt. Mit der
   Seitenleiste blieben bei 1100 px Fensterbreite für den Inhalt gut 400 px –
   Tabellen darin schnitten ihre letzte Spalte ab. */
@media (min-width: 1200px) {
  .split--main { grid-template-columns: minmax(0, 1fr) 336px; align-items: start; }
  .split--side { grid-template-columns: 320px minmax(0, 1fr); align-items: start; }
}
@media (min-width: 1500px) {
  .split--main { grid-template-columns: minmax(0, 1fr) 360px; }
}
.stack { display: flex; flex-direction: column; gap: var(--space-5); }
.stack--sm { gap: var(--space-2); }
.stack--lg { gap: var(--space-8); }
.row { display: flex; align-items: center; gap: var(--space-3); flex-wrap: wrap; }
.row--between { justify-content: space-between; }
.row--tight { gap: var(--space-2); }
.row--nowrap { flex-wrap: nowrap; }

/* ---------- 7. Buttons ---------- */
.btn {
  --btn-bg: var(--surface-2);
  --btn-fg: var(--text);
  --btn-border: var(--border);
  display: inline-flex; align-items: center; justify-content: center; gap: var(--space-2);
  padding: .5rem 1.125rem; min-height: var(--control-h);
  border-radius: var(--radius-full);
  background: var(--btn-bg); color: var(--btn-fg);
  border: 1px solid var(--btn-border);
  font-weight: 500; font-size: var(--fs-md); line-height: 1.25; letter-spacing: 0;
  white-space: nowrap; cursor: pointer;
  transition: background-color var(--dur) var(--ease), border-color var(--dur) var(--ease), color var(--dur) var(--ease), box-shadow var(--dur) var(--ease), opacity var(--dur) var(--ease), transform var(--dur-fast) var(--ease);
}
.btn svg { width: 17px; height: 17px; flex: none; }
/* Ein <span> im Knopf ist selbst ein Flexelement – aber innerlich noch
   Fließtext, und ein svg ist im Reset ein Blockelement. Aus
   „⟳ Jetzt abholen" wurden dadurch zwei Zeilen: Symbol oben, Wort darunter.
   Betrifft jeden Knopf, dessen Inhalt aus Gründen der Umschaltung in einer
   Spanne steckt. */
.btn > span { display: inline-flex; align-items: center; gap: .5rem; }
/* Kein Anheben beim Überfahren: die Rückmeldung kommt über die Fläche,
   nicht über Bewegung. Eine Seite, deren Knöpfe hüpfen, wirkt unruhig. */
.btn:hover { box-shadow: var(--shadow-xs); }
.btn:active { opacity: .88; }
/* Beim Drücken gibt der Knopf um anderthalb Prozent nach – die Linse, die
   Apple „Lensing" nennt, in ihrer zurückhaltendsten Form. Nur, wer Bewegung
   nicht abgeschaltet hat; der Block oben nimmt dann auch den Übergang. */
@media (prefers-reduced-motion: no-preference) {
  .btn:active { transform: scale(.985); }
}
.btn[disabled], .btn.is-disabled { opacity: .5; pointer-events: none; }

/* Die beiden gefüllten Knöpfe tragen eine Lichtkante oben (18 % Weiß, innen):
   die Fläche wirkt leicht gewölbt, ohne dass etwas leuchtet oder springt. */
.btn--primary { --btn-bg: var(--text); --btn-fg: var(--surface); --btn-border: transparent; box-shadow: inset 0 1px 0 rgba(255, 255, 255, .18); }
.btn--primary:hover { --btn-bg: color-mix(in srgb, var(--text) 86%, var(--surface)); box-shadow: inset 0 1px 0 rgba(255, 255, 255, .18), var(--shadow-xs); }
/* Im Dunkeln kein grelles Reinweiß: die Textfarbe selbst, ein warmes Hellgrau.
   Die Kante ist dort ein feiner Ring außen, ein Weiß innen sähe man nicht. */
html[data-theme="dark"] .btn--primary { --btn-bg: var(--text); --btn-fg: var(--bg); box-shadow: inset 0 1px 0 rgba(255, 255, 255, .5), 0 0 0 1px rgba(255, 255, 255, .06); }
html[data-theme="dark"] .btn--primary:hover { box-shadow: inset 0 1px 0 rgba(255, 255, 255, .5), 0 0 0 1px rgba(255, 255, 255, .06), var(--shadow-xs); }
.btn--accent  { --btn-bg: var(--accent); --btn-fg: var(--accent-on); --btn-border: transparent; box-shadow: inset 0 1px 0 rgba(255, 255, 255, .18); }
.btn--accent:hover { --btn-bg: color-mix(in srgb, var(--accent) 90%, var(--text)); box-shadow: inset 0 1px 0 rgba(255, 255, 255, .18), var(--shadow-xs); }
html[data-theme="dark"] .btn--accent { box-shadow: inset 0 1px 0 rgba(255, 255, 255, .18), 0 0 0 1px rgba(255, 255, 255, .08); }
html[data-theme="dark"] .btn--accent:hover { box-shadow: inset 0 1px 0 rgba(255, 255, 255, .18), 0 0 0 1px rgba(255, 255, 255, .08), var(--shadow-xs); }
.btn--ghost   { --btn-bg: transparent; --btn-border: var(--border-strong); }
.btn--ghost:hover { --btn-bg: color-mix(in srgb, var(--text) 4%, transparent); box-shadow: none; }
.btn--quiet   { --btn-bg: transparent; --btn-border: transparent; --btn-fg: var(--text-muted); }
.btn--quiet:hover { --btn-bg: color-mix(in srgb, var(--text) 6%, transparent); --btn-fg: var(--text); box-shadow: none; }
.btn--danger  { --btn-bg: var(--danger-soft); --btn-fg: var(--danger); --btn-border: transparent; }
.btn--success { --btn-bg: var(--success); --btn-fg: #fff; --btn-border: transparent; }
.btn--sm { padding: .3125rem .875rem; min-height: var(--control-h-sm); font-size: var(--fs-sm); }
.btn--lg { padding: .75rem 1.5rem; min-height: 3.25rem; font-size: 1rem; }
.btn--block { width: 100%; }
/* Symbolknöpfe folgen denselben Höhen-Tokens. Wer diese Maße ändert, ändert
   die beiden Zeilen für `.btn-group` unten mit (Spezifitätsfalle). */
.btn--icon { padding: 0; width: var(--control-h); height: var(--control-h); min-height: var(--control-h); border-radius: var(--radius-full); }
.btn--icon.btn--sm { width: var(--control-h-sm); height: var(--control-h-sm); min-height: var(--control-h-sm); }

/* Segmentschalter: die gewählte Stelle ist eine weiße Pille auf grauem
   Grund. Steht darin ein `.btn--primary` (Kalender: „Monat"), gilt er als
   gewählte Stelle – vorher schlug `.btn-group a` mit seiner grauen Schrift
   die Knopffarbe, und „Monat" stand grau auf Schwarz. */
.btn-group { display: inline-flex; align-items: center; background: var(--surface-2); border-radius: var(--radius-full); padding: 3px; gap: 2px; border: 1px solid var(--border); max-width: 100%; }
.btn-group a, .btn-group button {
  /* Ohne inline-flex bricht die Beschriftung unter das Symbol: svg ist im
     Reset ein Blockelement. Aus „▥ Board" wurden zwei Zeilen. */
  display: inline-flex; align-items: center; justify-content: center; gap: .375rem; white-space: nowrap;
  padding: .3125rem .875rem; border-radius: var(--radius-full); font-size: var(--fs-sm); font-weight: 500;
  color: var(--text-muted); transition: background-color var(--dur) var(--ease), color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.btn-group a.btn, .btn-group button.btn { min-height: calc(var(--control-h-sm) - 2px); --btn-bg: transparent; --btn-border: transparent; background: transparent; border-color: transparent; }
.btn-group a:hover, .btn-group button:hover { color: var(--text); box-shadow: none; }
.btn-group a.is-active, .btn-group button.is-active,
.btn-group a.btn--primary, .btn-group button.btn--primary { background: var(--surface); color: var(--text); box-shadow: var(--shadow-xs), 0 0 0 1px var(--border); }
/* Ein Symbolknopf ist quadratisch und randlos – auch hier drin. Ohne diese
   Zeile gewann `.btn-group a` (ein Typ mehr) über `.btn--icon`, und der
   Knopf bekam seitlich 13,6 px Polster in einem 32 px breiten Kasten. */
.btn-group a.btn--icon, .btn-group button.btn--icon { padding: 0; width: var(--control-h); height: var(--control-h); }
.btn-group a.btn--icon.btn--sm, .btn-group button.btn--icon.btn--sm { width: var(--control-h-sm); height: var(--control-h-sm); }

/* ---------- 8. Formulare ---------- */
.field { display: flex; flex-direction: column; gap: var(--space-2); min-width: 0; }
/* `.field__label` benutzt die GoBD-Seite (admin/gobd/index.php) – es gab die
   Klasse nie; jetzt sieht das Label dort aus wie überall. */
.label, .field__label { font-size: var(--fs-sm); font-weight: 500; color: var(--text-muted); letter-spacing: 0; line-height: var(--lh-snug); }
.label .req { color: var(--danger); }
.hint { font-size: var(--fs-sm); color: var(--text-subtle); line-height: var(--lh-snug); }
/* Technische Zeichenketten – Adressen, Schlüssel, Fehlermeldungen – haben
   keine Leerzeichen, an denen umgebrochen werden könnte. Ohne diese Zeile
   schieben sie ihren Kasten auseinander: die Rückkanal-Adresse sprengte am
   Telefon den Hinweiskasten um 45 px, eine IMAP-Fehlermeldung die Tabelle. */
.hint, .alert, .kontingent__zahl { overflow-wrap: anywhere; }
/* Tabellenzellen NICHT mehr `anywhere`: das senkte die Mindestbreite jeder
   Zelle auf ein Zeichen, und die Tabelle quetschte ihre Spalten, bis
   „31.07.2↵026" mitten in der Jahreszahl brach (B1). `break-word` bricht nur
   noch, was allein nicht in die Zeile passt; eine überbreite Zeichenkette
   macht die Tabelle breiter, und die scrollt dann sichtbar (Scroll-Schatten
   an .table-wrap). */
.table td { overflow-wrap: break-word; }
/* Ein Hinweis, der etwas kostet, wenn man ihn übersieht. */
.hint--warn { color: var(--danger); }
/* Sechs Ziffern, die jemand am Telefon vorliest: groß, gesperrt, mit
   gleichbreiten Ziffern – man vergleicht sie mit dem Ohr, nicht mit dem Auge. */
.code-eingabe {
  font-family: var(--mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  font-size: 1.4rem; letter-spacing: .34em; text-align: center;
  font-variant-numeric: tabular-nums; padding-left: .5rem;
}
.error-text { font-size: var(--fs-sm); color: var(--danger); font-weight: 500; }

.input, .select, .textarea {
  width: 100%; padding: .5rem .875rem; min-height: var(--control-h);
  background: var(--surface); color: var(--text);
  border: 1px solid var(--border-strong); border-radius: var(--control-radius);
  transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease), background-color var(--dur) var(--ease);
  font-size: var(--fs-base); line-height: 1.4;
}
.input::placeholder, .textarea::placeholder { color: var(--text-subtle); }
.input:hover, .select:hover, .textarea:hover { border-color: color-mix(in srgb, var(--text) 24%, transparent); }
/* Der Fokus: Rand in der Schriftrolle der Marke und ein weicher Hof. Die
   Flächenrolle (--accent) war bei Gold als Rand auf Weiß kaum zu sehen. */
.input:focus, .select:focus, .textarea:focus {
  outline: none; border-color: var(--focus);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--focus) 18%, transparent);
}
.input.is-invalid, .select.is-invalid, .textarea.is-invalid { border-color: var(--danger); }
.textarea { min-height: 110px; resize: vertical; line-height: var(--lh-body); padding-top: .625rem; }
.select {
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%238a919e' stroke-width='2.2' stroke-linecap='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right .75rem center; background-size: 16px;
  padding-right: 2.375rem;
}
/* Eine Auswahl, die nur so breit ist wie ihr Inhalt (Sprache der PDF-Vorschau). */
.select--auto { width: auto; }
.input--sm { min-height: var(--control-h-sm); padding: .3125rem .75rem; font-size: var(--fs-md); }
/* iOS vergrößert die Seite beim Tippen in jedes Feld unter 16 px – und
   verkleinert sie danach nicht wieder. Am Telefon also 16 px, überall. */
@media (max-width: 1023px) {
  .input, .select, .textarea, .input--sm { font-size: 16px; }
}
.input--ghost { background: transparent; border-color: transparent; }
.input--ghost:hover { background: var(--surface-2); }
.input--number { text-align: right; font-variant-numeric: tabular-nums; }

.input-group { display: flex; align-items: stretch; }
.input-group .input { border-radius: var(--radius-sm) 0 0 var(--radius-sm); }
.input-group__addon {
  display: flex; align-items: center; padding: 0 .75rem; font-size: var(--fs-md); color: var(--text-muted);
  background: var(--surface-2); border: 1px solid var(--border-strong); border-left: 0;
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
}

.check { display: flex; align-items: flex-start; gap: var(--space-3); cursor: pointer; padding: var(--space-1) 0; }
.check input[type="checkbox"], .check input[type="radio"] {
  appearance: none; width: 20px; height: 20px; flex: none; margin-top: 1px;
  border: 1.5px solid var(--border-strong); background: var(--surface);
  border-radius: 6px; cursor: pointer; position: relative;
  transition: background-color var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.check input[type="radio"] { border-radius: 50%; }
.check input:checked { background: var(--accent); border-color: var(--accent); }
/* Das Häkchen ist eine Maske, keine weiße Grafik: es nimmt --accent-on und
   bleibt damit auf jeder Akzentfarbe lesbar. Weiß auf Gold kam auf 2,2:1. */
.check input[type="checkbox"]:checked::after {
  content: ""; position: absolute; inset: 0;
  background: var(--accent-on);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='3.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6L9 17l-5-5'/%3E%3C/svg%3E") center / 13px no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='3.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6L9 17l-5-5'/%3E%3C/svg%3E") center / 13px no-repeat;
}
.check input[type="radio"]:checked::after {
  content: ""; position: absolute; inset: 5px; border-radius: 50%; background: var(--accent-on);
}
.check__text { font-size: var(--fs-base); color: var(--text); line-height: var(--lh-snug); }
.check__text small { display: block; color: var(--text-subtle); margin-top: 2px; }
/* Am Telefon ist die ganze Zeile das Tippziel und mindestens 44 px hoch
   (gemessen vorher 29 px). Das Kästchen bleibt oben an der ersten Zeile. */
@media (max-width: 1023px) {
  .check { min-height: 2.75rem; padding-block: .75rem; }
}

.switch { position: relative; display: inline-flex; align-items: center; gap: var(--space-3); cursor: pointer; }
.switch input { appearance: none; width: 44px; height: 26px; border-radius: var(--radius-full); background: var(--surface-3); transition: background-color var(--dur) var(--ease); cursor: pointer; }
.switch input:checked { background: var(--accent); }
.switch input::after {
  content: ""; position: absolute; left: 3px; top: 3px; width: 20px; height: 20px; border-radius: 50%;
  background: #fff; box-shadow: var(--shadow-xs); transition: transform var(--dur) var(--ease);
}
.switch input:checked::after { transform: translateX(18px); }

.form-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 240px), 1fr)); gap: var(--space-5) var(--space-5); }
.form-grid .span-2 { grid-column: span 2; }
.form-grid .span-full { grid-column: 1 / -1; }
@media (max-width: 640px) { .form-grid .span-2 { grid-column: span 1; } }

.fieldset { border: 0; padding: 0; }
.fieldset__legend { font-size: var(--fs-base); font-weight: 600; margin-bottom: var(--space-3); }

/* ---------- 9. Tabellen ---------- */
/* Eine Tabelle, die breiter ist als ihr Kasten, scrollt – und zeigt das.
   Der Schatten am Rand kommt aus zwei Hintergrund-Lagen: Deckflächen, die
   mit dem Inhalt mitlaufen (`local`), und Schatten, die am Kasten stehen
   (`scroll`). Am Anfang deckt die linke Fläche den linken Schatten, am Ende
   die rechte den rechten; passt die Tabelle hinein, ist keiner zu sehen.
   Ohne Skript, in jedem Browser. Die Deckfarbe ist die Fläche darunter
   (--scroll-cover, in Karten --surface). Vorher: seitlich scrollbar, aber
   nichts zeigte es an – „FÄLLIG" stand halb am Rand (B2). */
.table-wrap {
  overflow-x: auto; -webkit-overflow-scrolling: touch;
  background:
    linear-gradient(to right, var(--scroll-cover) 30%, transparent) left center / 3rem 100% no-repeat local,
    linear-gradient(to left, var(--scroll-cover) 30%, transparent) right center / 3rem 100% no-repeat local,
    radial-gradient(farthest-side at 0 50%, color-mix(in srgb, var(--text) 13%, transparent), transparent) left center / .875rem 100% no-repeat scroll,
    radial-gradient(farthest-side at 100% 50%, color-mix(in srgb, var(--text) 13%, transparent), transparent) right center / .875rem 100% no-repeat scroll;
}
@media print { .table-wrap { background: none; overflow: visible; } }
/* Schmale Spalten dürfen den Text nicht auf vier Zeilen quetschen: die
   Tabelle behält eine Mindestbreite und scrollt lieber waagerecht. */
.table-wrap > .table { min-width: 46rem; }
/* Die kompakte Tabelle hat wenige, schmale Spalten. Mit derselben
   Mindestbreite wie eine volle Tabelle scrollte sie in einer Kartenspalte
   auch dort waagerecht, wo sie bequem hineinpasst – und abgeschnitten wird
   dann ausgerechnet die letzte Spalte, in der die Schaltflächen stehen. */
.table-wrap > .table--compact { min-width: 34rem; }
@media (max-width: 780px) { .table-wrap > .table--responsive { min-width: 0; } }
.table td.is-primary { min-width: 12rem; }
/* Eine Tabelle IM Kartenkörper (Positionen der Beleg-Akte) steht bündig mit
   dem Text darüber und rückt die Spalten etwas enger. In der schmalen
   Hauptspalte neben der Seitenleiste fehlte sonst die Spalte „Betrag" –
   ausgerechnet die Zeilensumme (N1): 756 px Tabelle in 694 px Platz. */
.card__body .table-wrap > .table { --cell-px: .75rem; }
.card__body .table-wrap > .table :is(th, td):first-child { padding-left: 0; }
.card__body .table-wrap > .table :is(th, td):last-child { padding-right: 0; }
/* Nur als Tabelle – in der Kartenansicht am Telefon gilt min-width: 0. */
@media (min-width: 781px) { .split .card__body .table-wrap > .table { min-width: 30rem; } }
/* Zwischen 1200 und 1439 px steht die Beleg-Akte zweispaltig in 464–538 px:
   mit 36 rem und einer 12-rem-Bezeichnung lag „Betrag" hinter dem
   Scroll-Schatten. Die Bezeichnung bricht dort ohnehin um (2. Welle, belege). */
@media (min-width: 781px) and (max-width: 1439px) { .split .card__body .table--responsive td.is-primary { min-width: 9rem; } }
/* Ziffern gleich breit in jeder Zelle: Beträge, Daten und Nummern stehen
   dann untereinander, ohne dass die Spalte flattert. */
.table { font-size: var(--fs-md); font-variant-numeric: tabular-nums; line-height: var(--lh-snug); }
/* Tabellenkopf in Satzschreibung, 13 px, gedämpft – vorher Versalien mit
   Sperrung, das lauteste Element jeder Liste. */
.table th {
  text-align: left; font-weight: 500; font-size: var(--fs-sm); letter-spacing: 0; text-transform: none;
  color: var(--text-subtle); padding: var(--space-3) var(--cell-px); border-bottom: 1px solid var(--border); white-space: nowrap;
}
.table td { padding: var(--cell-py) var(--cell-px); border-bottom: 1px solid var(--border); vertical-align: middle; }
.table tbody tr { transition: background-color var(--dur) var(--ease); }
.table tbody tr:hover { background: color-mix(in srgb, var(--text) 2.5%, transparent); }
.table tbody tr:last-child td { border-bottom: 0; }
.table .num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.table .shrink { width: 1%; white-space: nowrap; }
/* Aktionsknöpfe in einer schmalen Zelle bleiben nebeneinander. Ohne diese
   Zeile brach `.row` (flex-wrap) sie in der 1-%-Spalte untereinander, und
   jede Zeile der Belegliste wurde 100–145 px hoch. */
.table .shrink > .row, .table .shrink > .btn-group { flex-wrap: nowrap; }
/* Ein gekürzter Verweis in einer Zelle (Kunde) kürzt nur als Blockkasten –
   als Inline-Element schob er die Spalte auf die volle Namensbreite. */
.table td > a.truncate { display: block; max-width: 24ch; }
.table--compact td, .table--compact th { padding: var(--space-2) var(--space-3); }
/* Die erste und letzte Zelle stehen bündig mit dem Karteninhalt darüber. */
.card > .table-wrap > .table :is(th, td):first-child,
.card > .table > * > tr > :is(th, td):first-child { padding-left: var(--card-pad); }
.card > .table-wrap > .table :is(th, td):last-child,
.card > .table > * > tr > :is(th, td):last-child { padding-right: var(--card-pad); }
/* „link" war bislang nur ein Name ohne Regel: `a` erbt die Farbe und trägt
   keine Unterstreichung, also sah ein Verweis mitten im Satz („Alle
   anzeigen", „Postfach einrichten") aus wie gewöhnlicher Text. Wer ihn
   nicht als Verweis erkennt, klickt ihn nicht. */
.link { text-decoration: underline; text-underline-offset: .18em; text-decoration-thickness: 1px; text-decoration-color: color-mix(in srgb, currentColor 45%, transparent); font-weight: 500; }
.link:hover { text-decoration-color: currentColor; }
.table a.link { font-weight: 500; text-decoration: none; }
.table a.link:hover { text-decoration: underline; }
.table .truncate, .table td.truncate { max-width: 24ch; }
@media (min-width: 1500px) { .table .truncate, .table td.truncate { max-width: 40ch; } }
/* Bis 1500 px Fensterbreite hat eine volle Liste neben der Seitenleiste gut
   1100 px. Die Belegliste (acht Spalten) brauchte 1280: etwas engere Zellen
   holen den größten Teil davon zurück.
   Die zusätzliche Kürzung auf 20 ch ist wieder heraus: sie kürzte Namen und
   Titel auch dort, wo die Tabelle Platz hatte („Finca mit Meerblick bei …"),
   und seit dem Seiten-Feinschliff trägt keine Liste mehr `.truncate` in einer
   Zelle – gemessen 14.09.2026: Belege, Kunden, Objekte, Mandanten bei 1440,
   1280, 1200 und 1024 px ohne einen gekürzten Text, Belegliste 1440 passt
   (1102/1102). Wo `.truncate` in einer Zelle bleibt, gilt der Grundwert 24 ch. */
@media (max-width: 1499px) {
  .card > .table-wrap > .table { --cell-px: .75rem; }
}
.table a.link:hover { color: var(--accent-text); }

/* Mobile: Tabellen als Karten */
@media (max-width: 780px) {
  .table--responsive thead { display: none; }
  /* Zwei feste Spalten waren zu viel: auf 390 px stand die zweite halb
     außerhalb der Karte, und „Ansprechpartner" und „Status" waren
     abgeschnitten – sichtbar nur, wenn man seitwärts scrollte. Jetzt
     entscheidet der Platz: eine Spalte am Telefon, zwei, sobald 14 rem je
     Feld hineinpassen. */
  .table--responsive tr {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 14rem), 1fr));
    gap: var(--space-1) var(--space-4);
    padding: var(--space-4) var(--space-1); border-bottom: 1px solid var(--border);
  }
  /* In der Kartenansicht gelten die Zellmaße der Tabelle nicht: kein
     Polster, kein Rand – auch nicht das bündige Polster der ersten/letzten
     Zelle in einer Karte. */
  .table--responsive td,
  .card > .table-wrap > .table--responsive td:first-child,
  .card > .table-wrap > .table--responsive td:last-child { border: 0; padding: .125rem 0; display: flex; align-items: baseline; gap: var(--space-2); }
  .card > .table-wrap > .table--responsive tr { padding-inline: var(--card-pad); }
  /* Wörter brechen hier nur an Silben, wenn sie allein nicht in die Zeile
     passen – nicht mehr mitten im Wort („Interviewleitfade↵n"). */
  .table--responsive td { overflow-wrap: break-word; hyphens: auto; -webkit-hyphens: auto; }
  .table--responsive td > * { min-width: 0; }
  .table--responsive td::before {
    content: attr(data-label); font-size: var(--fs-sm); text-transform: none; letter-spacing: 0;
    color: var(--text-subtle); min-width: 88px; flex: none;
    /* Die Beschriftungen stehen untereinander in einer Spalte. Ohne diese
       Zeile erbt eine Zahlenzelle ihr `text-align: right`, und ihre
       Beschriftung rückt als einzige ein. */
    text-align: left;
  }
  /* Die Hauptzelle hat keine Beschriftung und ist deshalb kein Flexkasten:
     Titel und Beschreibung einer Position standen sonst NEBENeinander, jede
     in halber Breite – daher „Interviewleitfade↵n" (N4). */
  .table--responsive td.is-primary { grid-column: 1 / -1; font-weight: 600; font-size: var(--fs-base); margin-bottom: var(--space-1); display: block; }
  /* Dieselbe Zusage in der Karte: die bündige erste Zelle oben
     (`.card > .table-wrap > … td:first-child`, 0,4,1) machte die Hauptzelle
     wieder zum Flexkasten – „RE-2026-0003Rechnung" in der Belegliste. */
  .card > .table-wrap > .table--responsive td.is-primary { display: block; }
  .table--responsive td.is-primary > .text-sm, .table--responsive td.is-primary > .muted { font-weight: 400; margin-top: 2px; }
  .table--responsive td.is-primary::before { display: none; }
  .table--responsive td.num { justify-content: flex-start; }
  /* In der Kartenansicht wird nicht gekürzt, sondern umgebrochen. Zwei
     Gründe: die 26 Zeichen aus der Tabelle sind hier keine knappe Spalte
     mehr, sondern eine willkürliche Grenze – und `text-overflow` wirkt an
     einem Flexkasten gar nicht, der Titel brach also ohne Auslassungspunkte
     mitten im Wort ab („newways.suite · St"). */
  .table--responsive td.truncate, .table--responsive .truncate {
    max-width: none; white-space: normal; overflow: visible;
    overflow-wrap: break-word;
  }
  /* `width: 1%` heißt in einer Tabelle „so schmal wie möglich". Hier ist die
     Zeile ein Grid und die Zelle ein Flexkasten – dort heißt es wörtlich
     1 % der Zeile, also knapp drei Pixel. Die Aktionsknöpfe wurden dadurch
     zu Punkten. */
  .table--responsive td.shrink { width: auto; }
  .table--responsive td > a.truncate { display: inline; }
  .table--responsive td.text-right { text-align: left; }
  /* Pfade und Code haben keine Umbruchstelle („/kunden/69585_30161/suite"):
     eine einzige solche Zelle schob in der Karte ALLE Werte aus dem Bild.
     Nur hier, gezielt – Datumszellen brechen weiter nicht mitten im Wort. */
  .table--responsive td > code, .table--responsive td > .umbruch { overflow-wrap: anywhere; }
  /* Aktionen in der Karte umbrechen statt über den Rand zu laufen
     (Team am Telefon: „Entfernen" angeschnitten). In der Tabelle bleiben sie
     einzeilig. */
  .table--responsive td.shrink > .row, .table--responsive td.shrink > .btn-group { flex-wrap: wrap; }
}

/* ---------- 10. Badges, Chips, Avatare ---------- */
.badge {
  display: inline-flex; align-items: center; gap: .375rem;
  padding: .1875rem .625rem; border-radius: var(--radius-full);
  font-size: var(--fs-xs); font-weight: 500; letter-spacing: 0; line-height: 1.35; white-space: nowrap;
  background: var(--surface-3); color: var(--text-muted);
}
.badge::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: currentColor; opacity: .8; flex: none; }
.badge--plain::before { display: none; }
.badge--slate   { background: var(--surface-3); color: var(--text-muted); }
.badge--blue    { background: var(--info-soft); color: var(--info); }
.badge--emerald { background: var(--success-soft); color: var(--success); }
.badge--amber   { background: var(--warning-soft); color: var(--warning); }
.badge--rose    { background: var(--danger-soft); color: var(--danger); }
.badge--cyan    { background: color-mix(in srgb, var(--accent-2) 14%, transparent); color: color-mix(in srgb, var(--accent-2) 80%, var(--text)); }
.badge--accent  { background: var(--accent-soft); color: var(--accent-text); }
.badge--gold    { background: var(--gold-soft); color: var(--gold-ink); }
.badge--lg { padding: .3125rem .75rem; font-size: var(--fs-sm); }

.chip {
  display: inline-flex; align-items: center; gap: .375rem;
  min-height: 2rem; padding: .25rem .75rem; border-radius: var(--radius-full);
  border: 1px solid var(--border-strong); font-size: var(--fs-sm); font-weight: 500; color: var(--text-muted);
  transition: background-color var(--dur) var(--ease), border-color var(--dur) var(--ease), color var(--dur) var(--ease);
}
.chip:hover { border-color: color-mix(in srgb, var(--text) 30%, transparent); color: var(--text); }
/* Der gewählte Chip: keine schwarze Pille mehr, sondern die schwebende
   Glas-Pille wie in der Navigation – --glass-tint, Lichtkante, --shadow-xs,
   Schrift --text. Das Dunkel braucht keine eigene Zeile mehr, die Tokens
   drehen sich mit. */
.chip.is-active { background: var(--glass-tint); color: var(--text); border-color: transparent; box-shadow: inset 0 1px 0 var(--glass-edge), var(--shadow-xs); }
/* Tippziel am Telefon: 44 px wie Knöpfe und Menüeinträge (vorher 40). */
@media (max-width: 1023px) { .chip { min-height: 2.75rem; } }

.avatar {
  width: 38px; height: 38px; border-radius: var(--radius-full); flex: none;
  display: grid; place-items: center; overflow: hidden;
  background: var(--surface-3); color: var(--text-muted);
  font-size: var(--fs-sm); font-weight: 600; letter-spacing: 0; text-transform: uppercase;
}
.avatar img { width: 100%; height: 100%; object-fit: cover; }
.avatar--sm { width: 28px; height: 28px; font-size: var(--fs-xs); }
.avatar--lg { width: 54px; height: 54px; font-size: 1.05rem; }
.avatar--xl { width: 76px; height: 76px; font-size: 1.5rem; border-radius: var(--radius-lg); }
.avatar--accent { background: var(--accent); color: var(--accent-on); }
.avatar-stack { display: flex; }
.avatar-stack .avatar { margin-left: -10px; border: 2px solid var(--surface); }
.avatar-stack .avatar:first-child { margin-left: 0; }

.dot { width: 8px; height: 8px; border-radius: 50%; flex: none; display: inline-block; }

/* ---------- 11. Kennzahlen ---------- */
.stat { display: flex; flex-direction: column; gap: var(--space-2); padding: var(--space-5) var(--card-pad); }
.stat__label { font-size: var(--fs-sm); color: var(--text-muted); font-weight: 500; }
.stat__label + * svg, .stat .subtle svg { width: 18px; height: 18px; }
.stat__value { font-size: clamp(1.5rem, 1.15rem + .9vw, 1.875rem); font-weight: 600; letter-spacing: -0.025em; font-variant-numeric: tabular-nums; line-height: 1.1; }
.stat__meta { font-size: var(--fs-sm); color: var(--text-muted); display: flex; align-items: center; gap: var(--space-1); }
.stat__meta svg { width: 15px; height: 15px; }
.stat__meta--up { color: var(--success); }
.stat__meta--down { color: var(--danger); }

.progress { height: 6px; border-radius: var(--radius-full); background: var(--surface-3); overflow: hidden; }
.progress__bar { height: 100%; border-radius: var(--radius-full); background: var(--accent); transition: width .5s var(--ease); }
.progress__bar.is-voll { background: var(--danger); }

/* ---------- Kontingente ---------- */
/* Zwei Zeilen, in denen eine Zahl und ein Balken dasselbe sagen. Die Zahl
   für den, der nachrechnet; der Balken für den, der nur schauen will, ob
   noch Luft ist. */
.kontingente { display: grid; gap: .9rem; }
.kontingent { display: grid; gap: .35rem; }
.kontingent__kopf { display: flex; align-items: baseline; justify-content: space-between; gap: 1rem; }
.kontingent__was { font-size: var(--fs-md); font-weight: 500; }
.kontingent__zahl { font-size: var(--fs-sm); color: var(--text-muted); white-space: nowrap; font-variant-numeric: tabular-nums; }
.progress--lg { height: 10px; }

.meter-ring { --pct: 0; width: 56px; height: 56px; border-radius: 50%; display: grid; place-items: center; flex: none;
  background: conic-gradient(var(--accent) calc(var(--pct) * 1%), var(--surface-3) 0);
}
.meter-ring::after { content: ""; position: absolute; width: 42px; height: 42px; border-radius: 50%; background: var(--surface); }
.meter-ring { position: relative; }
.meter-ring span { position: relative; font-size: var(--fs-xs); font-weight: 600; z-index: 1; }

/* ---------- 12. Overlays ---------- */
/* Der Dialog-Hintergrund: die Seite dahinter bleibt als Ahnung sichtbar,
   tritt aber deutlich zurück. Eigener Wert, nicht --glass-blur – er soll
   dämpfen, nicht als Fläche wirken. */
.backdrop {
  position: fixed; inset: 0; z-index: 90;
  background: color-mix(in srgb, #10150c 38%, transparent);
  -webkit-backdrop-filter: blur(8px) saturate(120%);
  backdrop-filter: blur(8px) saturate(120%);
}
@supports not ((backdrop-filter: blur(2px)) or (-webkit-backdrop-filter: blur(2px))) {
  .backdrop { background: color-mix(in srgb, #10150c 55%, transparent); }
}
.modal {
  position: fixed; z-index: 100; inset: 0; display: grid; place-items: center;
  padding: var(--space-4); pointer-events: none;
}
.modal__panel {
  pointer-events: auto; width: min(100%, 620px); max-height: min(86vh, 900px); overflow-y: auto;
  /* Der Dialogkörper ist DECKEND (Kartenfarbe), seit der Gegenprüfung 1.18.0.
     Er war kurz Glas – und damit Backdrop-Root für Kopf und Fuß: ein Element
     mit backdrop-filter ist der Hintergrund-Ursprung seiner Nachfahren, deren
     Unschärfe sieht nur, was innerhalb des Ahnen gemalt wird. Kopf und Fuß
     verwischten darum NICHTS, der Inhalt lief scharf unter ihnen durch
     (Befund pruef3 #1). Deckend ist der Körper ihr Untergrund, und die
     Unschärfe von Kopf und Fuß greift wirklich. Der gedämpfte .backdrop
     dahinter bleibt, wie er ist; Lichtkante und Schatten auch. */
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg);
  box-shadow: inset 0 1px 0 var(--glass-edge), var(--shadow-xl);
  /* Kopf und Fuß kleben (unten). Ohne Polster rollt der Browser ein
     angesprungenes Feld nur bis an den Rand der Fläche – also UNTER den Fuß
     (Annahmedialog am Telefon: 3 von 6 Tab-Stopps unsichtbar). Die Höhen
     misst der Dialog beim Öffnen; die Werte hier gelten bis dahin. */
  scroll-padding-top: var(--modal-kopf-h, 4.5rem);
  scroll-padding-bottom: var(--modal-fuss-h, 5rem);
}
.modal__panel--wide { width: min(100%, 900px); }
/* Der Dialog selbst nimmt beim Öffnen den Fokus (tabindex="-1"), damit ein
   Vorleser oben beginnt; ein Ring um die ganze Fläche hilft niemandem. */
.modal__panel:focus { outline: none; }
.modal__panel:has(.modal__footer--order) { --modal-fuss-h: 13rem; }
@media (max-width: 560px) { .modal__panel:has(.modal__footer--order) { --modal-fuss-h: 17rem; } }
/* Kopf und Fuß bleiben beim Scrollen stehen; die Linien darunter sind
   Haarlinien in der Farbe der Fläche – sie trennen nur, wenn darunter Inhalt
   durchläuft. Beide sind Glas AUF dem deckenden Körper: der ist ihr
   Untergrund, und was unter ihnen durchscrollt, wird wirklich verwischt
   (siehe .modal__panel – als der Körper selbst Glas war, sahen sie nur ihn). */
.modal__header { display: flex; align-items: center; gap: var(--space-4); padding: var(--space-5) var(--space-6); border-bottom: 1px solid var(--border); position: sticky; top: 0; background: var(--glass-surface); -webkit-backdrop-filter: var(--glass-blur); backdrop-filter: var(--glass-blur); z-index: 2; --text-subtle: var(--text-muted); }
.modal__header h2, .modal__header h3 { font-size: var(--fs-lg); }
.modal__body { padding: var(--space-6); }
.modal__footer { display: flex; gap: var(--space-2); justify-content: flex-end; padding: var(--space-4) var(--space-6); border-top: 1px solid var(--border); position: sticky; bottom: 0; background: var(--glass-surface); -webkit-backdrop-filter: var(--glass-blur); backdrop-filter: var(--glass-blur); --text-subtle: var(--text-muted); }
/* Public offer: leave room for the complete signature pad on short screens
   and when the on-screen keyboard reduces the visual viewport. */
.document-dialog .modal__panel { max-height: min(var(--document-dialog-height, 92dvh), 900px); }
.document-dialog .modal__panel--flow > form > .modal__header,
.document-dialog .modal__panel--flow > form > .modal__footer { position: static; }
@media (max-height: 540px) {
  .document-dialog .modal__header, .document-dialog .modal__footer { position: static; }
  .document-dialog .modal__panel { scroll-padding-block: 12px; }
}

.drawer {
  position: fixed; z-index: 100; top: 0; right: 0; bottom: 0; width: min(100%, 480px);
  background: var(--surface); border-left: 1px solid var(--border); box-shadow: var(--shadow-xl);
  display: flex; flex-direction: column; overflow-y: auto;
}

.dropdown { position: relative; }
.dropdown__menu {
  position: absolute; z-index: 70; right: 0; top: calc(100% + .5rem); min-width: 216px;
  background: var(--glass-surface); border: 1px solid var(--border); border-radius: var(--radius);
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  box-shadow: inset 0 1px 0 var(--glass-edge), var(--glass-shadow); padding: var(--space-1); overflow: hidden;
  --text-subtle: var(--text-muted);
}
.dropdown__menu--left { right: auto; left: 0; }
/* Modifikatoren stehen HINTER der Grundregel. Gleiche Spezifität heißt: die
   spätere Regel gewinnt. Standen --wide und --up oben bei der Kopfleiste,
   setzte `.dropdown__menu` `top` und `overflow: hidden` wieder zurück – das
   Benutzermenü der Seitenleiste lag mit `top` UND `bottom` als 10-px-Streifen
   da (Abmelden, Profil, Betreiberbereich unerreichbar), und die Liste der
   Benachrichtigungen scrollte nicht (4 von 14 sichtbar). Vorher standen die
   Werte als Inline-Stil am Element und gewannen immer. Die Prüfung
   „Oberfläche: Kaskade" hält die Reihenfolge fest. */
.dropdown__menu--wide { width: 330px; max-width: calc(100vw - 2rem); max-height: 420px; overflow-y: auto; }
.dropdown__menu--up { bottom: calc(100% + .5rem); top: auto; width: 100%; }
/* Menüs, die aus einer GLASLEISTE aufklappen (Glocke, Darstellung, das
   Benutzermenü der Seitenleiste, die Darstellung in Einrichtungs- und
   Buchungsleiste), sind deckend: die Leiste trägt backdrop-filter und ist
   damit Backdrop-Root ihrer Nachfahren – ein Glasmenü darin sähe nur die
   Leiste, nie die Seite darunter, und verwischte nichts (Gegenprüfung 1.18.0,
   Befund pruef3 #1: der Brotkrumen-Pfad stand scharf lesbar durch das Menü).
   Lichtkante und Schatten bleiben. Menüs im Inhalt (Kundenakte, Beleg,
   Objekt) bleiben Glas – sie haben keinen Glas-Ahnen. Spezifität (0,2,0):
   die Regel steht hinter der Grundregel und VOR der Betreiberleiste, die
   ihre Tinte mit derselben Spezifität später setzt. */
.topbar .dropdown__menu, .sidebar .dropdown__menu, .setup__bar .dropdown__menu, .booking__bar .dropdown__menu { background: var(--surface); -webkit-backdrop-filter: none; backdrop-filter: none; }
/* Am Telefon hängt das breite Menü an der Glocke, rechts neben ihr steht
   noch der Darstellungsschalter: 330 px ab der Glocke ragten bei 375 px
   23 px links aus dem Fenster. Unter 480 px richtet es sich deshalb an der
   Kopfleiste aus (Glocke nicht mehr Bezugskasten), 12 px vom rechten Rand. */
@media (max-width: 479px) {
  .topbar .dropdown:has(> .dropdown__menu--wide) { position: static; }
  .topbar .dropdown__menu--wide { right: .75rem; width: min(330px, calc(100% - 1.5rem)); max-width: none; }
}
.dropdown__item {
  display: flex; align-items: center; gap: var(--space-3); width: 100%; text-align: left;
  min-height: 2.25rem; padding: var(--space-2) var(--space-3); border-radius: var(--radius-xs); font-size: var(--fs-md); color: var(--text-muted);
  transition: background-color var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
.dropdown__item svg { width: 16px; height: 16px; opacity: .8; flex: none; }
.dropdown__item:hover { background: color-mix(in srgb, var(--text) 6%, transparent); color: var(--text); }
.dropdown__item--danger { color: var(--danger); }
.dropdown__divider { height: 1px; background: var(--border); margin: var(--space-1) 0; }
.dropdown__label { padding: var(--space-2) var(--space-3) var(--space-1); font-size: var(--fs-xs); font-weight: 500; text-transform: none; letter-spacing: 0; color: var(--text-subtle); }
@media (max-width: 1023px) { .dropdown__item { min-height: 2.75rem; } }

/* ---------- 13. Feedback ---------- */
.toasts { position: fixed; z-index: 200; bottom: var(--space-5); right: var(--space-5); display: flex; flex-direction: column; gap: var(--space-2); max-width: min(92vw, 400px); }
.toast {
  display: flex; align-items: flex-start; gap: var(--space-3);
  padding: var(--space-3) var(--space-4); border-radius: var(--radius);
  background: var(--glass-surface); border: 1px solid var(--border);
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  box-shadow: inset 0 1px 0 var(--glass-edge), var(--glass-shadow);
  --text-subtle: var(--text-muted);
  animation: toast-in .3s var(--ease);
}
.toast svg { width: 19px; height: 19px; flex: none; margin-top: 1px; }
.toast__body { font-size: var(--fs-md); color: var(--text); flex: 1; line-height: var(--lh-snug); padding-top: 1px; }
.toast--success svg { color: var(--success); }
.toast--error svg { color: var(--danger); }
.toast--info svg { color: var(--info); }
.toast--warning svg { color: var(--warning); }
@keyframes toast-in { from { opacity: 0; transform: translateY(12px) scale(.97); } to { opacity: 1; transform: none; } }

.alert {
  display: flex; gap: var(--space-3); padding: var(--space-4) var(--space-5); border-radius: var(--radius);
  border: 1px solid var(--border); background: var(--surface-2); font-size: var(--fs-md); line-height: var(--lh-body);
}
.alert svg { width: 18px; height: 18px; flex: none; margin-top: 2px; }
/* Fett gesetzte Wörter im Hinweis tragen die Farbe des Hinweises; stand
   bisher als `style="color:inherit"` an jedem <strong>. */
.alert strong { color: inherit; }
.alert--error { background: var(--danger-soft); border-color: transparent; color: var(--danger); }
.alert--success { background: var(--success-soft); border-color: transparent; color: var(--success); }
.alert--warning { background: var(--warning-soft); border-color: transparent; color: var(--warning); }
.alert--info { background: var(--info-soft); border-color: transparent; color: var(--info); }

.empty {
  display: flex; flex-direction: column; align-items: center; gap: var(--space-2);
  padding: clamp(2rem, 5vw, 3.5rem) var(--space-6); text-align: center;
}
.empty__icon {
  width: 56px; height: 56px; border-radius: var(--radius); display: grid; place-items: center;
  background: var(--surface-2); color: var(--text-subtle); margin-bottom: var(--space-2);
}
.empty__icon svg { width: 24px; height: 24px; }
.empty h3 { font-size: var(--fs-lg); }
.empty p { max-width: 42ch; font-size: var(--fs-md); }

.skeleton { background: linear-gradient(90deg, var(--surface-2) 25%, var(--surface-3) 50%, var(--surface-2) 75%); background-size: 200% 100%; animation: shimmer 1.4s infinite; border-radius: var(--radius-xs); }
@keyframes shimmer { to { background-position: -200% 0; } }

/* ---------- 14. Tabs & Navigation ---------- */
/* Reiter. Passen sie nicht in eine Zeile, gilt:
   – mit Maus (Rechner): sie brechen um. Zwölf Reiter der Einstellungen
     stehen dann in zwei Zeilen, statt dass „System" unsichtbar rechts
     hinter dem Rand liegt (B4/N5).
   – mit dem Finger: die Leiste scrollt seitlich, und ein Verlauf am Rand
     zeigt, dass es weitergeht. Den Rand setzt app.js (`data-ueberlauf`),
     denn nur das Skript weiß, auf welcher Seite noch etwas liegt. */
.tabs { display: flex; gap: var(--space-1); padding-bottom: var(--space-2); border-bottom: 1px solid var(--border); overflow-x: auto; scrollbar-width: none; -webkit-overflow-scrolling: touch; overscroll-behavior-x: contain; }
.tabs::-webkit-scrollbar { display: none; }
.tabs[data-ueberlauf="rechts"] { -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 3rem), transparent); mask-image: linear-gradient(to right, #000 calc(100% - 3rem), transparent); }
.tabs[data-ueberlauf="links"] { -webkit-mask-image: linear-gradient(to left, #000 calc(100% - 3rem), transparent); mask-image: linear-gradient(to left, #000 calc(100% - 3rem), transparent); }
.tabs[data-ueberlauf="beide"] { -webkit-mask-image: linear-gradient(to right, transparent, #000 3rem, #000 calc(100% - 3rem), transparent); mask-image: linear-gradient(to right, transparent, #000 3rem, #000 calc(100% - 3rem), transparent); }
@media (hover: hover) and (pointer: fine) {
  .tabs { flex-wrap: wrap; overflow-x: visible; }
}
/* Reiter seit 1.18.0 als Pillen: der gewählte schwebt (--glass-tint,
   Lichtkante, --shadow-xs) statt einen Strich unter sich zu tragen. Die
   Haarlinie der Leiste bleibt, mit 8 px Luft unter den Pillen. */
.tab {
  display: inline-flex; align-items: center;
  padding: var(--space-2) var(--space-4); font-size: var(--fs-md); font-weight: 500; color: var(--text-muted);
  border-radius: var(--radius-full); white-space: nowrap;
  transition: color var(--dur) var(--ease), background-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.tab:hover { color: var(--text); background: color-mix(in srgb, var(--text) 5%, transparent); }
.tab.is-active { color: var(--text); background: var(--glass-tint); font-weight: 600; box-shadow: inset 0 1px 0 var(--glass-edge), var(--shadow-xs); }
.tab__count { font-size: var(--fs-xs); color: var(--text-subtle); margin-left: var(--space-1); font-weight: 500; font-variant-numeric: tabular-nums; }
@media (max-width: 1023px) { .tab { min-height: 2.75rem; } }

/* Einstellungen (1.17): am Rechner die Bereiche als senkrechte Liste links
   (Stil Systemeinstellungen), am Telefon die Reiterleiste. Beide Leisten
   schalten denselben Alpine-Zustand `tab`. `.einstellungen.split` schlägt
   `.split--side` (320 px ab 1200 px), das im Markup als Rückfall steht –
   deshalb steht dieser Block NACH Abschnitt 6.
   Zwischen 1024 und 1199 px steht neben der Seitenleiste nur ~700 px Platz:
   mit der Liste links blieben dem Inhalt 483 px – Felder abgeschnitten, die
   Tabelle unter „System" (544 px) scrollte (gemessen, Integration 2. Welle).
   Dort gilt deshalb die Reiterleiste über dem vollen Inhalt; mit der Maus
   brechen die Reiter um (Abschnitt 14 oben). */
.einstellungen__nav .nav-item { width: 100%; text-align: left; }
@media (min-width: 1200px) {
  .einstellungen.split { grid-template-columns: 13.5rem minmax(0, 1fr); gap: var(--space-8); align-items: start; }
  .einstellungen__nav { position: sticky; top: calc(var(--topbar-h) + var(--space-5)); }
}
@media (min-width: 1024px) and (max-width: 1199px) {
  .einstellungen__reiter.mobile-only { display: block; }
  .einstellungen__nav { display: none; }
}
@media (max-width: 1199px) {
  .einstellungen.split { gap: var(--space-5); }
}

.breadcrumb { display: flex; align-items: center; gap: var(--space-2); font-size: var(--fs-sm); color: var(--text-subtle); flex-wrap: wrap; }
.breadcrumb a:hover { color: var(--text); }
.breadcrumb svg { width: 14px; height: 14px; opacity: .6; }
/* Am Telefon ist der Zurück-Verweis oft der einzige Weg zurück. 20 px hoch
   trifft man mit dem Daumen nicht zuverlässig; die Schriftgröße bleibt, der
   antippbare Bereich wächst. */
@media (max-width: 780px) {
  .breadcrumb { min-height: 2.25rem; }
  .breadcrumb a { display: inline-flex; align-items: center; gap: .3rem; padding: .45rem 0; min-height: 44px; }
  /* Weitere Tippziele unter 44 px (gemessen am Telefon): Segmentschalter
     Liste/Kacheln/Board und Deutsch/English 31 px, Schalter „Preis auf
     Anfrage" 26 px, Aufklapper „Welche Listen?" 22 px, Fußlink im Portal
     15 px. Die Schrift bleibt, der antippbare Bereich wächst. Die `.btn`-Form
     steht mit, weil `.btn-group a.btn` sonst gewinnt. */
  .btn-group a, .btn-group button, .btn-group a.btn, .btn-group button.btn { min-height: 44px; }
  .switch { min-height: 44px; }
  details > summary { padding-block: .75rem; }
  .portal-fuss a { display: inline-flex; align-items: center; min-height: 44px; }
}
/* Am Telefon sind Anrufen und Schreiben keine Nebensache, sondern das, wofür
   man die Kundenakte überhaupt aufmacht. 21 px hohe Zeilen trifft man nicht. */
@media (max-width: 780px) {
  .kontaktzeile { min-height: 2.5rem; padding: .3rem 0; }
}

.pagination { display: flex; align-items: center; justify-content: center; gap: var(--space-1); padding: var(--space-5) 0; }
.pagination a, .pagination span {
  min-width: 40px; height: 40px; display: grid; place-items: center; padding: 0 var(--space-3);
  border-radius: var(--radius-full); font-size: var(--fs-md); color: var(--text-muted); font-variant-numeric: tabular-nums;
}
.pagination a:hover { background: color-mix(in srgb, var(--text) 6%, transparent); color: var(--text); }
.pagination .is-active { background: var(--text); color: var(--surface); font-weight: 600; }
html[data-theme="dark"] .pagination .is-active { background: var(--text); color: var(--bg); }
@media (max-width: 1023px) { .pagination a, .pagination span { min-width: 44px; height: 44px; } }

/* ---------- 15. Zeitleiste & Listen ---------- */
.timeline { display: flex; flex-direction: column; gap: 0; }
.timeline__item { display: flex; gap: var(--space-3); padding-bottom: var(--space-5); position: relative; }
.timeline__item:not(:last-child)::before {
  content: ""; position: absolute; left: 15px; top: 36px; bottom: 4px; width: 1px; background: var(--border-strong);
}
.timeline__dot {
  width: 32px; height: 32px; border-radius: 50%; flex: none; display: grid; place-items: center;
  background: var(--surface-2); color: var(--text-muted); border: 1px solid var(--border); z-index: 1;
}
.timeline__dot svg { width: 15px; height: 15px; }
.timeline__body { flex: 1; min-width: 0; padding-top: .3125rem; }
.timeline__title { font-size: var(--fs-md); font-weight: 500; line-height: var(--lh-snug); }
.timeline__meta { font-size: var(--fs-sm); color: var(--text-subtle); margin-top: 2px; }

.list { display: flex; flex-direction: column; }
/* Die Trennlinie einer Liste beginnt dort, wo der Text beginnt – eingerückt
   wie in den Einstellungen des iPhones. Als Hintergrundbild gezogen, damit
   der Farbwechsel beim Überfahren sie nicht verdeckt. */
.list__item {
  display: flex; align-items: center; gap: var(--space-3); padding: var(--space-3) var(--card-pad);
  min-height: 3rem;
  border-bottom: 0;
  background-image: linear-gradient(var(--border), var(--border));
  background-size: calc(100% - var(--card-pad)) 1px; background-position: right bottom; background-repeat: no-repeat;
  transition: background-color var(--dur) var(--ease);
}
.list__item:last-child { background-image: none; }
/* Steht die Liste schon im gepolsterten Kartenkörper, rückt sie nicht noch
   einmal ein (Kundenakte „Letzte Belege": 48 px statt 24 px vom Rand). */
.card__body > .list > .list__item { padding-inline: 0; background-size: 100% 1px; }
.list__item:hover { background-color: color-mix(in srgb, var(--text) 2.5%, transparent); }
/* Als Spalte, nicht als Fließtext: `text-overflow: ellipsis` an .list__title
   wirkt nur an einem Blockkasten. Als inline-Element ragte ein langer Titel
   einfach heraus, statt gekürzt zu werden. */
.list__main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.list__title { font-weight: 500; font-size: var(--fs-base); line-height: var(--lh-snug); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Zeilen mit Knöpfen rechts (Suchprofil-Treffer: Badge + zwei Knöpfe): dem
   Titel blieben in der Kundenakte 256 von 683 px, „NW-2026-021 · Elbvilla in
   Blanken…" (gemessen 11.09.2026). Dort bricht der Titel um, statt zu kürzen. */
.list__title--umbruch { white-space: normal; overflow: visible; text-overflow: clip; overflow-wrap: anywhere; }
.list__sub { font-size: var(--fs-sm); color: var(--text-subtle); line-height: var(--lh-snug); }

/* ---------- 16. Kanban ---------- */
.board { display: flex; gap: 1rem; overflow-x: auto; padding-bottom: 1rem; scroll-snap-type: x proximity; }
.board__column {
  flex: 0 0 clamp(260px, 27vw, 320px); scroll-snap-align: start;
  background: var(--surface-2); border-radius: var(--radius-lg); padding: var(--space-3);
  display: flex; flex-direction: column; gap: var(--space-2); max-height: calc(100vh - 260px);
}
.board__head { display: flex; align-items: center; gap: var(--space-2); padding: var(--space-1) var(--space-2) var(--space-2); }
.board__head h4 { font-size: var(--fs-md); text-transform: none; letter-spacing: 0; color: var(--text); font-weight: 600; }
.board__count { margin-left: auto; font-size: var(--fs-xs); color: var(--text-subtle); font-variant-numeric: tabular-nums; }
.board__list { display: flex; flex-direction: column; gap: var(--space-2); overflow-y: auto; flex: 1; padding-bottom: var(--space-1); }
.task-card {
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
  padding: var(--space-3) var(--space-4); box-shadow: var(--shadow-xs); cursor: pointer;
  transition: box-shadow var(--dur) var(--ease), border-color var(--dur) var(--ease);
  display: flex; flex-direction: column; gap: var(--space-2);
}
.task-card:hover { box-shadow: var(--shadow); border-color: var(--border-strong); }
.task-card__title { font-size: var(--fs-md); font-weight: 500; line-height: var(--lh-snug); }
.task-card__meta { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; font-size: var(--fs-xs); color: var(--text-subtle); }
.task-card.is-client { border-left: 3px solid var(--accent-2); }
.task-card.is-overdue .task-card__due { color: var(--danger); font-weight: 600; }

/* Ziehbare Karten: Griff oben rechts, gedrehte Karte beim Ziehen,
   Zielspalte leuchtet, gesperrte Spalten (Kundenportal) treten zurück. */
.task-card[draggable="true"] { position: relative; }
.task-card__grip {
  position: absolute; top: .55rem; right: .5rem; color: var(--text-subtle);
  cursor: grab; opacity: .45; transition: opacity var(--dur) var(--ease);
}
.task-card__grip svg { width: 15px; height: 15px; }
.task-card[draggable="true"]:hover .task-card__grip { opacity: 1; }
.task-card[draggable="true"] .task-card__title { padding-right: 1.4rem; }
.task-card.is-dragging { opacity: .45; transform: rotate(1.5deg) scale(.98); cursor: grabbing; }
.board__list.is-ziel {
  outline: 2px dashed var(--accent); outline-offset: 3px;
  border-radius: var(--radius); background: color-mix(in srgb, var(--accent) 6%, transparent);
}
.board__list.is-gesperrt { opacity: .4; }
@media (prefers-reduced-motion: reduce) {
  .task-card.is-dragging { transform: none; }
}

/* ---------- 16c. Übersicht anpassen ---------- */
.dash-widget { position: relative; }
.dash-widget__griff, .dash-widget__weg { display: none; }
.dash.is-anpassen .dash-widget {
  outline: 2px dashed var(--border); outline-offset: 4px; border-radius: var(--radius-lg);
  cursor: grab;
}
.dash.is-anpassen .dash-widget.is-dragging { opacity: .5; cursor: grabbing; }
.dash.is-anpassen .dash-widget__griff {
  display: flex; position: absolute; top: .6rem; right: 2.6rem; z-index: 2;
  color: var(--text-subtle); cursor: grab;
}
.dash.is-anpassen .dash-widget__griff svg { width: 17px; height: 17px; }
.dash.is-anpassen .dash-widget__weg {
  display: inline-flex; position: absolute; top: .35rem; right: .35rem; z-index: 2;
}
/* Im Anpassen-Modus fängt die Karte die Klicks – nicht ihre Links. */
.dash.is-anpassen .dash-widget section { pointer-events: none; }
.dash-leiste {
  background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--radius-lg);
  padding: .85rem 1rem; margin-bottom: 1.1rem;
}

/* ---------- 16b. Positionseditor ---------- */
.items-list { display: flex; flex-direction: column; }
.item-row {
  display: flex; flex-direction: column; gap: .55rem;
  padding: 1rem clamp(1rem, 2vw, 1.35rem);
  border-bottom: 1px solid var(--border);
  transition: background var(--dur) var(--ease);
}
.item-row:last-child { border-bottom: 0; }
.item-row:hover { background: var(--surface-inset); }
.item-row--note { background: var(--surface-inset); }
.item-row__head { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; }
.item-row__index {
  width: 26px; height: 26px; flex: none; display: grid; place-items: center;
  border-radius: var(--radius-full); background: var(--surface-3);
  font-size: var(--fs-xs); font-weight: 600; color: var(--text-muted); font-variant-numeric: tabular-nums;
}
.item-row__type { width: 9rem; flex: none; }
.item-row__title { flex: 1 1 13rem; min-width: 13rem; font-weight: 500; }
.item-row__tools { display: flex; gap: 2px; flex: none; margin-left: auto; }
.item-row__numbers {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(104px, 1fr));
  gap: var(--space-2) var(--space-3); align-items: end;
}
.item-field { display: flex; flex-direction: column; gap: var(--space-1); min-width: 0; }
.item-field > span {
  font-size: var(--fs-xs); text-transform: none; letter-spacing: 0;
  color: var(--text-subtle); font-weight: 500;
}
.item-row__sum {
  display: flex; flex-direction: column; gap: .25rem; align-items: flex-end;
  justify-content: flex-end; min-width: 7rem; padding-bottom: .55rem;
}
.item-row__sum strong { font-size: 1rem; font-variant-numeric: tabular-nums; letter-spacing: -0.02em; }

/* ---------- 17. Kalender ---------- */
.calendar { border: 1px solid var(--border); border-radius: var(--radius-lg); overflow: hidden; background: var(--surface); }
.calendar__head { display: grid; grid-template-columns: repeat(7, 1fr); background: var(--surface-2); }
.calendar__head div { padding: var(--space-2); font-size: var(--fs-xs); text-transform: none; letter-spacing: 0; color: var(--text-subtle); font-weight: 500; text-align: center; }
.calendar__grid { display: grid; grid-template-columns: repeat(7, 1fr); }
.calendar__day {
  min-height: clamp(92px, 12vh, 132px); padding: var(--space-2);
  border-right: 1px solid var(--border); border-bottom: 1px solid var(--border);
  display: flex; flex-direction: column; gap: var(--space-1); overflow: hidden; min-width: 0;
}
.calendar__day:nth-child(7n) { border-right: 0; }
.calendar__day.is-outside { background: var(--surface-inset); }
/* Ohne Deckkraft: --text-subtle auf --surface-inset hält 5,0:1 (dunkel 5,8); mit 0,6 waren es 2,37. */
.calendar__day.is-outside .calendar__num { color: var(--text-subtle); }
.calendar__day.is-today .calendar__num { background: var(--accent); color: var(--accent-on); }
.calendar__num { font-size: var(--fs-xs); font-weight: 600; width: 24px; height: 24px; display: grid; place-items: center; border-radius: 50%; color: var(--text-muted); font-variant-numeric: tabular-nums; }
.cal-event {
  font-size: var(--fs-xs); line-height: 1.35; padding: 2px var(--space-2); border-radius: var(--radius-xs); font-weight: 500;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  background: var(--surface-2); color: var(--text); border-left: 3px solid var(--accent);
}
.cal-event:hover { background: var(--surface-3); }
.calendar__more { font-size: var(--fs-xs); color: var(--text-subtle); padding-left: var(--space-1); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* Am Telefon passen in einen Tag gut 45 px. Dort standen Termine als
   „Au…" in 9,9 px – lesen konnte man nichts. Jetzt ist ein Termin ein
   Punkt in seiner Farbe, wie im Monatsblatt des iPhones: die Farbe steht
   im Markup als linker Rand, und ein Kasten, der genau so breit ist wie
   dieser Rand, ist ein Punkt. Der Monat zeigt, WANN etwas ist; WAS, zeigen
   Woche und Liste. Der Name bleibt als Titel und für Vorleseprogramme.
   Nachbesserung: Der Server gibt je Tag drei Einträge aus und dann
   „+N weitere". Das darf am Telefon nicht verschwinden – drei Punkte für
   sechs Termine wären eine falsche Zahl. Es bleibt stehen und bricht am
   Leerzeichen: in einem schmalen Tag (43 px) ist nur die erste Zeile „+3"
   zu sehen, auf breiteren Schirmen das ganze „+3 weitere"; vorgelesen wird
   immer der volle Text. Und: ein Punkt von 7 px ist kein Tippziel. Die
   Punkte nehmen deshalb keine Berührung an, getippt wird der ganze Tag
   (mindestens 43 × 64 px) – er legt wie am Rechner einen Termin an diesem
   Tag an; Einträge öffnen Woche und Liste. */
@media (max-width: 720px) {
  .calendar__day { min-height: 64px; padding: var(--space-1); flex-flow: row wrap; align-content: flex-start; gap: 4px; }
  .calendar__day .calendar__num { margin-right: calc(100% - 24px); }
  .calendar__day .cal-event {
    width: 7px; height: 7px; flex: none; padding: 0; margin: 0;
    font-size: 0; line-height: 0; color: transparent;
    border-left-width: 7px; border-radius: 50%; background: transparent;
    pointer-events: none;
  }
  .calendar__day .calendar__more {
    display: block; flex: 0 1 auto; min-width: 0; padding: 0;
    height: 1rem; line-height: 1rem; white-space: normal; overflow: hidden;
    font-weight: 600; color: var(--text-muted); font-variant-numeric: tabular-nums;
  }
}

/* ---------- 18. Upload ---------- */
.dropzone {
  border: 1.5px dashed var(--border-strong); border-radius: var(--radius-lg);
  padding: clamp(1.5rem, 4vw, 2.75rem); text-align: center; background: var(--surface-inset);
  transition: border-color var(--dur) var(--ease), background-color var(--dur) var(--ease); cursor: pointer;
}
.dropzone:hover, .dropzone.is-dragging { border-color: var(--accent); background: var(--accent-soft); }
.dropzone svg { width: 30px; height: 30px; color: var(--text-subtle); margin-inline: auto; margin-bottom: .6rem; }

.file-item {
  display: flex; align-items: center; gap: .8rem; padding: .7rem .85rem;
  border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface);
  transition: border-color var(--dur) var(--ease);
}
.file-item:hover { border-color: var(--border-strong); }
.file-item__icon {
  width: 38px; height: 38px; border-radius: var(--radius-xs); flex: none; display: grid; place-items: center;
  background: var(--surface-2); color: var(--text-muted); overflow: hidden;
}
.file-item__icon svg { width: 18px; height: 18px; }
.file-item__icon img { width: 100%; height: 100%; object-fit: cover; }

/* ---------- 18b. Logo-Auswahl ---------- */
.logo-slot {
  position: relative; display: grid; place-items: center;
  min-height: 108px; padding: .9rem;
  border: 1.5px dashed var(--border-strong); border-radius: var(--radius);
  background: var(--surface-inset); cursor: pointer; overflow: hidden;
  transition: border-color var(--dur) var(--ease), background var(--dur) var(--ease);
}
.logo-slot:hover, .logo-slot.is-dragging { border-color: var(--accent); background: var(--accent-soft); }
.logo-slot img { max-height: 84px; max-width: 100%; width: auto; object-fit: contain; }
/* Karo-Muster, damit auch transparente Logos erkennbar bleiben */
.logo-slot::before {
  content: ""; position: absolute; inset: 0; opacity: .35; pointer-events: none;
  background-image:
    linear-gradient(45deg, var(--surface-3) 25%, transparent 25%),
    linear-gradient(-45deg, var(--surface-3) 25%, transparent 25%),
    linear-gradient(45deg, transparent 75%, var(--surface-3) 75%),
    linear-gradient(-45deg, transparent 75%, var(--surface-3) 75%);
  background-size: 14px 14px;
  background-position: 0 0, 0 7px, 7px -7px, -7px 0;
}
.logo-slot > * { position: relative; z-index: 1; }
.logo-slot--dark { background: #14161a; border-color: rgba(255,255,255,.22); }
.logo-slot--dark::before { opacity: .12; }
.logo-slot--dark .logo-slot__empty { color: rgba(255,255,255,.6); }
.logo-slot__empty {
  display: flex; flex-direction: column; align-items: center; gap: .4rem;
  color: var(--text-subtle); font-size: var(--fs-sm); text-align: center;
}
.logo-slot__empty svg { width: 22px; height: 22px; }
.logo-slot__badge {
  position: absolute; top: .5rem; right: .5rem; z-index: 2;
  font-size: var(--fs-xs); font-weight: 600; letter-spacing: 0;
  padding: .18rem .5rem; border-radius: var(--radius-full);
  background: var(--accent); color: var(--accent-on);
}

/* ---------- 19. Projektfenster (Kundenansicht) ---------- */
.portal-hero {
  position: relative; overflow: hidden; border-radius: var(--radius-xl);
  padding: clamp(1.75rem, 4.5vw, 3.5rem);
  background: var(--surface); border: 1px solid var(--border); box-shadow: var(--shadow);
}
.portal-hero::before {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(135deg, color-mix(in srgb, var(--brand-client, var(--accent)) 12%, transparent), transparent 62%);
  pointer-events: none;
}
.portal-hero__logo { max-height: 56px; width: auto; margin-bottom: 1.35rem; }
.portal-hero__content { position: relative; }

/* Kopf und Fuß des Kundenportals – vorher Inline-Stile in layouts/portal.php.
   Der gewählte Punkt der Navigation hatte keine Regel, nur einen Inline-Stil. */
/* 44 px: die Marke ist am Telefon der Weg zurück zum Empfang (gemessen 28 px). */
.portal-marke { gap: var(--space-3); min-width: 0; min-height: 44px; }
.portal-marke__logo { height: 28px; width: auto; max-width: 132px; object-fit: contain; }
.portal-nav { margin-left: var(--space-6); gap: 2px; }
.portal-nav .btn.is-active { --btn-bg: color-mix(in srgb, var(--text) 7%, transparent); --btn-fg: var(--text); }
.portal-fuss { padding-top: 0; padding-bottom: var(--space-8); }
.portal-fuss__zeile { padding-top: var(--space-5); }
.portal-fuss__logo { height: 18px; width: auto; opacity: .55; }

.deliverable {
  display: flex; flex-direction: column; overflow: hidden;
  border: 1px solid var(--border); border-radius: var(--radius-lg); background: var(--surface);
  transition: box-shadow var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.deliverable:hover { box-shadow: var(--shadow); border-color: var(--border-strong); }
.deliverable__media {
  aspect-ratio: 16 / 10; background: var(--surface-2); position: relative; overflow: hidden;
  display: grid; place-items: center;
}
.deliverable__media img { width: 100%; height: 100%; object-fit: cover; }
.deliverable__media svg { width: 34px; height: 34px; color: var(--text-subtle); }
.deliverable__body { padding: var(--space-4) var(--space-5); display: flex; flex-direction: column; gap: var(--space-2); flex: 1; }
.deliverable__type { font-size: var(--fs-xs); text-transform: none; letter-spacing: 0; color: var(--text-subtle); font-weight: 500; }
.deliverable--featured { grid-column: span 2; }
@media (max-width: 720px) { .deliverable--featured { grid-column: span 1; } }

/* ---------- 20. Öffentliche Belegseite ---------- */
.doc-page { max-width: 940px; margin-inline: auto; padding: clamp(1rem, 3vw, 2.5rem) 1rem 6rem; }
.doc-sheet {
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-xl);
  box-shadow: var(--shadow-lg); overflow: hidden;
}
.doc-sheet__head { padding: clamp(1.5rem, 4vw, 2.75rem); border-bottom: 1px solid var(--border); }
.doc-sheet__body { padding: clamp(1.25rem, 3.5vw, 2.75rem); }
.doc-actions {
  position: sticky; bottom: 0; z-index: 30;
  display: flex; gap: .6rem; flex-wrap: wrap; justify-content: center;
  padding: var(--space-4); margin-top: var(--space-5);
  /* Seit 1.18.0 Glas in der Kartenfarbe: der Balken klebt unten und der
     Beleg läuft unter ihm durch – genau der Fall, für den Glas gemacht ist.
     90 % Deckung, gerechnet gegen Weiß und Schwarz (Notiz 1.18). */
  background: var(--glass-surface); border: 1px solid var(--border);
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  box-shadow: inset 0 1px 0 var(--glass-edge), var(--shadow);
  border-radius: var(--radius-lg);
  --text-subtle: var(--text-muted);
}
/* Vorschau der E-Mail-Signatur. Hier gelten die Regeln des Mailprogramms,
   nicht die der Anwendung: der globale Bild- und Tabellenreset wird
   zurückgenommen, sonst rechnet der Browser die Logospalte auf 0 px. */
.sig-preview { background: #ffffff; padding: 18px; border-radius: 10px; overflow: hidden; }
.sig-preview img { max-width: none; width: auto; height: auto; }
.sig-preview table { width: auto; }
.sig-preview a { text-decoration: none; }
.signature-preview > img, .signature-preview details > img { max-width: 100%; height: auto; }
.signature-preview__hash { overflow-wrap: anywhere; }

.signature-pad {
  border: 1.5px dashed var(--border-strong); border-radius: var(--radius);
  background: var(--surface-inset); touch-action: none; width: 100%; height: 170px; cursor: crosshair;
}

/* ---------- 21. Login ---------- */
.auth {
  min-height: 100vh; min-height: 100dvh; display: grid; place-items: center; padding: 1.5rem;
}
.auth__card {
  width: min(100%, 440px);
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-xl); box-shadow: var(--shadow-xl);
  padding: clamp(1.75rem, 4vw, 2.75rem);
}
.auth__logo { max-height: 40px; margin-bottom: 1.75rem; }
.auth__split { display: grid; min-height: 100vh; min-height: 100dvh; grid-template-columns: 1fr; }
@media (min-width: 1024px) { .auth__split { grid-template-columns: 1.05fr .95fr; } }
.auth__aside {
  display: none; position: relative; overflow: hidden; padding: 3.5rem;
  background: linear-gradient(150deg, #10150c, color-mix(in srgb, var(--accent) 40%, #10150c));
  color: #fff; flex-direction: column; justify-content: space-between;
}
@media (min-width: 1024px) { .auth__aside { display: flex; } }
.auth__aside h2, .auth__aside p { color: #fff; }
.auth__aside p { color: rgba(255,255,255,.78); }
/* Vorher Inline-Stile in layouts/auth.php. */
.auth__brand { margin-bottom: var(--space-7); }
.auth__brand img { max-width: 250px; height: auto; }
.auth__wordmark { font-size: 1.6rem; letter-spacing: -.01em; }
/* 0,85 statt 0,66: auf dem hellen Ende des Verlaufs (40 % Akzent) hielt die
   kleine Schrift mit Hellblau nur 4,22:1; jetzt 5,81 (Gold 6,24, Oliv 9,67). */
.auth__aside-eyebrow { color: rgba(255,255,255,.85); }
.auth__aside-title { font-size: clamp(1.9rem, 1.3rem + 1.9vw, 2.9rem); margin-bottom: var(--space-4); }
.auth__aside-text { max-width: 38ch; font-size: var(--fs-lg); }
.auth__aside-links { gap: var(--space-6); color: rgba(255,255,255,.85); font-size: var(--fs-sm); }

/* ---------- 21b. Posteingang ---------- */
/* Vorschläge sind Entwürfe, keine Meldungen. Deshalb ruhige Flächen und
   keine Signalfarben – auffällig wird nur, was eine Entscheidung braucht. */
/* Zurückgenommen über die Farbe, nicht über Deckkraft: 60 % von --text-muted
   ergaben 2,57:1. --text-subtle hält ≥ 4,5:1; im gewählten Chip die Chipfarbe. */
.chip__count { font-variant-numeric: tabular-nums; font-weight: 620; color: var(--text-subtle); }
.chip.is-active .chip__count { color: inherit; }

.inbox-card { display: flex; align-items: flex-start; gap: .9rem; padding: 1rem 1.15rem; }
.inbox-card__icon {
  width: 36px; height: 36px; flex: none; border-radius: var(--radius-xs);
  background: var(--surface-2); color: var(--text-muted); display: grid; place-items: center;
}
.inbox-card__icon svg { width: 17px; height: 17px; }
.inbox-card__main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: .1rem; }
.inbox-card__kind { font-size: var(--fs-xs); text-transform: none; letter-spacing: 0; color: var(--text-subtle); font-weight: 500; }
/* Zwei Zeilen statt einer: am Telefon hieß der Betreff sonst „Re: Rückfrage zur Terminbuch…". */
.inbox-card__title { font-weight: 500; color: var(--text); overflow: hidden; overflow-wrap: anywhere; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; }
.inbox-card__meta { display: flex; flex-wrap: wrap; gap: 2px var(--space-4); font-size: var(--fs-sm); color: var(--text-subtle); margin-top: 2px; }
.inbox-card__meta > span { display: inline-flex; align-items: center; gap: .3rem; min-width: 0; max-width: 100%; }
.inbox-card__meta svg { width: 13px; height: 13px; flex: none; opacity: .8; }
.inbox-card__side { display: flex; align-items: center; gap: .5rem; flex: none; align-self: center; }
.inbox-card__chevron { display: flex; color: var(--text-subtle); }
.inbox-card__chevron svg { width: 17px; height: 17px; }
@media (max-width: 560px) { .inbox-card__chevron { display: none; } }

/* Die eingegangene Nachricht: sichtbar zitiert, damit sie nicht mit dem
   Entwurf verwechselt wird. Lange Mails scrollen im eigenen Feld. */
.mail-quote {
  max-height: 24rem; overflow-y: auto; overflow-wrap: break-word;
  background: var(--surface-inset); border: 1px solid var(--border);
  border-left: 3px solid var(--border-strong); border-radius: var(--radius-sm);
  padding: .85rem 1rem; font-size: .875rem; line-height: 1.65; color: var(--text-muted);
}

.letter {
  background: var(--surface-inset); border: 1px solid var(--border); border-radius: var(--radius-sm);
  padding: 1.1rem 1.2rem; font-size: .9rem; line-height: 1.7; color: var(--text); overflow-wrap: break-word;
}

.action { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg); box-shadow: var(--shadow-sm); overflow: hidden; }
.action__head { display: flex; align-items: center; gap: var(--space-2); padding: var(--space-3) var(--space-5); background: var(--surface-2); border-bottom: 1px solid var(--border); }
.action__head svg { width: 17px; height: 17px; flex: none; color: var(--text-muted); }
.action__title { font-weight: 600; font-size: var(--fs-md); }
.action__body { padding: var(--space-5); }
/* Die Vorschlagsspalte ist schmaler als eine Belegseite: die Positions-
   tabelle bekommt hier eine kleinere Mindestbreite, damit nichts abge-
   schnitten wird. Unterhalb von 781px greift die Kartendarstellung. */
@media (min-width: 781px) { .action .table-wrap > .table { min-width: 30rem; } }
/* Auf dem Telefon wird die Tabelle zur Karte. In der schmalen Spalte reicht
   eine Wertespalte, sonst wird der letzte Betrag abgeschnitten. */
@media (max-width: 780px) {
  .action .table--responsive tr { grid-template-columns: minmax(0, 1fr); }
  .action .table--responsive td.is-primary { display: block; }
  .action .table--responsive td.is-primary > .text-sm { font-weight: 400; }
  .action .table--responsive td::before { text-align: left; }
}

/* Wertepaare: eine durchgezogene Haarlinie statt der gestrichelten – die
   Striche waren das unruhigste Muster auf jeder Stammdatenkarte. */
.pair { display: flex; justify-content: space-between; align-items: baseline; gap: var(--space-4); padding: var(--space-2) 0; font-size: var(--fs-md); line-height: var(--lh-snug); border-bottom: 1px solid var(--border); }
.pair:last-child { border-bottom: 0; }
.pair__label { color: var(--text-muted); flex: none; }
.pair__value { text-align: right; min-width: 0; color: var(--text); overflow-wrap: break-word; }

.rule { display: flex; align-items: flex-start; gap: .5rem; }
.rule .badge { flex: none; margin-top: .1rem; }
/* Regelzeile in den Einstellungen: Text links, Schalter rechts. */
.rule__body { display: flex; align-items: baseline; gap: .5rem; flex-wrap: wrap; flex: 1; min-width: 0; }
.rule__text { font-size: .9rem; color: var(--text); overflow-wrap: break-word; min-width: 0; }
.rule.is-off { opacity: .5; }
.rule.is-off .rule__text { text-decoration: line-through; }

.diff { border-left: 3px solid var(--border-strong); padding-left: .9rem; }
.diff--neu { border-left-color: var(--success); }
.diff--weg { border-left-color: var(--danger); }
.diff--geaendert { border-left-color: var(--accent); }
.diff__values { display: grid; gap: .6rem; grid-template-columns: minmax(0, 1fr); }
@media (min-width: 760px) { .diff__values { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); } }
.diff__value {
  background: var(--surface-inset); border: 1px solid var(--border); border-radius: var(--radius-xs);
  padding: .5rem .7rem; font-size: .82rem; line-height: 1.55; white-space: pre-wrap; overflow-wrap: break-word;
}
.diff__value--old { color: var(--text-subtle); }

/* Die Begründung darf man nicht verstecken, sie muss aber auch nicht
   dauernd offen stehen – deshalb ein einfaches details-Element. */
.why { border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--surface-inset); }
.why > summary { display: flex; align-items: center; gap: var(--space-2); padding: var(--space-3) var(--space-4); cursor: pointer; font-size: var(--fs-md); font-weight: 500; color: var(--text-muted); list-style: none; }
.why > summary::-webkit-details-marker { display: none; }
.why > summary:hover { color: var(--text); }
.why > summary svg { width: 15px; height: 15px; flex: none; transition: transform var(--dur) var(--ease); }
.why[open] > summary svg { transform: rotate(90deg); }
.why__body { padding: 0 .9rem .9rem 2.05rem; font-size: .85rem; line-height: 1.65; color: var(--text-muted); overflow-wrap: break-word; }

.route { background: var(--surface-inset); border: 1px solid var(--border); border-radius: var(--radius); padding: 1.1rem 1.2rem; }
.route h4 { font-size: .95rem; }
.route--strong { background: var(--accent-soft); border-color: var(--border-accent); }
.route--strong p { color: var(--text); }

.result { display: flex; align-items: flex-start; gap: .75rem; padding: .8rem .9rem; background: var(--surface-inset); border: 1px solid var(--border); border-radius: var(--radius-sm); }
.result__icon { width: 30px; height: 30px; flex: none; border-radius: var(--radius-xs); background: var(--surface-2); color: var(--text-muted); display: grid; place-items: center; }
.result__icon svg { width: 16px; height: 16px; }

/* Nachrichten ohne Vorschlag: auf dem Telefon gehört die Schaltfläche unter
   den Text, sonst bleiben für den Betreff keine zwanzig Zeichen übrig. */
.pending-item { align-items: flex-start; gap: 1rem; }
.pending-item .list__title { white-space: normal; }
@media (max-width: 640px) {
  .pending-item { flex-direction: column; align-items: stretch; gap: .7rem; }
  .pending-item .btn { width: 100%; justify-content: center; }
}

/* ---------- 22. Utilities ---------- */
/* Die alten Stufen bleiben mit ihren Namen, rücken aber ins 4-px-Raster –
   und dabei eine Spur auseinander (mt-3: 17,6 → 20 px, mb-4: 25,6 → 28 px).
   Das ist der Hebel, der die 700 Stellen in den Ansichten erreicht, ohne
   eine davon anzufassen. Für neue Arbeit gelten die Klassen mit „s" (unten),
   deren Zahl dem Token entspricht: .mt-s4 = --space-4 = 16 px. */
.mt-0{margin-top:0}.mt-1{margin-top:var(--space-2)}.mt-2{margin-top:var(--space-3)}.mt-3{margin-top:var(--space-5)}.mt-4{margin-top:var(--space-7)}.mt-6{margin-top:var(--space-10)}
.mb-0{margin-bottom:0}.mb-1{margin-bottom:var(--space-2)}.mb-2{margin-bottom:var(--space-3)}.mb-3{margin-bottom:var(--space-5)}.mb-4{margin-bottom:var(--space-7)}.mb-6{margin-bottom:var(--space-10)}
.p-0{padding:0}.p-2{padding:var(--space-3)}.p-3{padding:var(--space-4)}.p-4{padding:var(--space-6)}
.gap-1{gap:var(--space-2)}.gap-2{gap:var(--space-3)}.gap-3{gap:var(--space-4)}.gap-4{gap:var(--space-6)}
.flex{display:flex}.grid-c{display:grid}.inline-flex{display:inline-flex}.block{display:block}.hidden{display:none}
.flex-1{flex:1;min-width:0}.flex-none{flex:none}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}
.items-center{align-items:center}.items-start{align-items:flex-start}.items-end{align-items:flex-end}.items-baseline{align-items:baseline}
.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}
.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}
.text-xs{font-size:var(--fs-xs)}.text-sm{font-size:var(--fs-md)}.text-base{font-size:var(--fs-base)}.text-lg{font-size:var(--fs-lg)}.text-xl{font-size:var(--fs-xl)}.text-2xl{font-size:1.625rem}
.font-medium{font-weight:500}.font-semibold{font-weight:600}.font-bold{font-weight:650}
.muted{color:var(--text-muted)}.subtle{color:var(--text-subtle)}.text-danger{color:var(--danger)}.text-success{color:var(--success)}.text-warning{color:var(--warning)}.text-accent{color:var(--accent-text)}
.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.clamp-2{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.clamp-3{display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}
.w-full{width:100%}.h-full{height:100%}
.rounded{border-radius:var(--radius)}.rounded-full{border-radius:var(--radius-full)}
.border{border:1px solid var(--border)}.border-t{border-top:1px solid var(--border)}.border-b{border-bottom:1px solid var(--border)}
.bg-surface{background:var(--surface)}.bg-surface-2{background:var(--surface-2)}.bg-inset{background:var(--surface-inset)}
.relative{position:relative}.absolute{position:absolute}.sticky{position:sticky}
.overflow-hidden{overflow:hidden}.overflow-auto{overflow:auto}
.cursor-pointer{cursor:pointer}
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
[x-cloak]{display:none!important}

/* ---------- 22b. Hilfsklassen 1.17 ----------
   Für die zweite Welle: sie ersetzen die häufigsten Inline-Stile der
   Ansichten (`margin:0` 34×, `color:inherit` 40×, `min-width:0` 13×,
   `white-space:nowrap` 23×, `flex-direction:column;gap:.15rem` …).
   Beispiele und Zuordnung: docs/notizen/oberflaeche-1.17.md. */
/* Abstand oben/unten und Lücken – die Zahl ist die Stufe der Skala. */
.mt-s0{margin-top:0}.mt-s1{margin-top:var(--space-1)}.mt-s2{margin-top:var(--space-2)}.mt-s3{margin-top:var(--space-3)}.mt-s4{margin-top:var(--space-4)}.mt-s5{margin-top:var(--space-5)}.mt-s6{margin-top:var(--space-6)}.mt-s8{margin-top:var(--space-8)}.mt-s10{margin-top:var(--space-10)}.mt-s12{margin-top:var(--space-12)}
.mb-s0{margin-bottom:0}.mb-s1{margin-bottom:var(--space-1)}.mb-s2{margin-bottom:var(--space-2)}.mb-s3{margin-bottom:var(--space-3)}.mb-s4{margin-bottom:var(--space-4)}.mb-s5{margin-bottom:var(--space-5)}.mb-s6{margin-bottom:var(--space-6)}.mb-s8{margin-bottom:var(--space-8)}.mb-s10{margin-bottom:var(--space-10)}.mb-s12{margin-bottom:var(--space-12)}
.gap-s0{gap:0}.gap-s1{gap:var(--space-1)}.gap-s2{gap:var(--space-2)}.gap-s3{gap:var(--space-3)}.gap-s4{gap:var(--space-4)}.gap-s5{gap:var(--space-5)}.gap-s6{gap:var(--space-6)}.gap-s8{gap:var(--space-8)}
.m-0{margin:0}
/* Layout */
.stack--xs { gap: var(--space-1); }
.cluster { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-3); }
.row--end { justify-content: flex-end; }
.row--start { align-items: flex-start; }
.row--baseline { align-items: baseline; }
.min-w-0 { min-width: 0; }
.shrink-0 { flex-shrink: 0; }
.liste-plain { list-style: none; margin: 0; padding: 0; }
.aufzaehlung { list-style: disc; margin: 0; padding-left: 1.25rem; display: flex; flex-direction: column; gap: var(--space-1); }
.aufzaehlung li::marker { color: var(--text-subtle); }
/* Schrift */
.nowrap { white-space: nowrap; }
.pre-line { white-space: pre-line; }
.pre-wrap { white-space: pre-wrap; overflow-wrap: anywhere; }
.tabular { font-variant-numeric: tabular-nums; }
.umbruch { overflow-wrap: anywhere; }
.silben { overflow-wrap: break-word; hyphens: auto; -webkit-hyphens: auto; }
.text-strong { color: var(--text); }
.text-inherit, .color-inherit { color: inherit; }
.text-muted { color: var(--text-muted); }
.text-subtle { color: var(--text-subtle); }
.weight-regular { font-weight: 400; }
/* Filterzeile der Objektliste: das Suchfeld nimmt den Rest, die Auswahlfelder
   eine feste Grundbreite. Ohne Grundbreite schrumpfte das Suchfeld in der
   umbrechenden Zeile auf null (vorher Inline-Stile min-/max-width). */
.filterleiste__suche { flex: 1 1 12.5rem; min-width: 0; }
.filterleiste__feld { flex: 0 1 11rem; min-width: 8rem; }
/* Video-Standbild in der Objektakte: YouTube liefert 4:3 mit schwarzen
   Balken, Web-Exposé und PDF schneiden sie weg – die Akte ebenso. */
.standbild-16x9 { display: block; width: 100%; aspect-ratio: 16 / 9; object-fit: cover; border-radius: var(--radius); }

/* Kennzahlenreihe (.kennzahlen, an .grid.grid--4, .grid--2 bzw. .grid--5):
   am Telefon eine waagerecht wischbare Reihe statt gestapelter Karten.
   Vier Karten untereinander füllten den ersten Schirm (Übersicht: Liste ab
   914 px); ein 2×2-Raster brach die Beträge („23.170,60 / €"). Die zweite
   Karte schaut am Rand heraus – das zeigt, dass es weitergeht. Die Reihe läuft
   bis an den Bildschirmrand und rastet an der Seitenkante ein. Am Rechner
   gilt weiter das Raster. Gemessen am 14.09.2026 (Bauer „uebersicht").
   Falle: der negative Rand ist der Seitenrand von .page (Abschnitt 4,
   clamp(1rem, 3vw, 2.5rem)) – wer den ändert, ändert ihn hier mit. Das
   Polster oben/unten ist Platz für den Kartenschatten, den overflow sonst
   abschneidet. */
@media (max-width: 640px) {
  .grid.kennzahlen {
    grid-template-columns: none; grid-auto-flow: column; grid-auto-columns: minmax(12.5rem, 1fr);
    overflow-x: auto; overscroll-behavior-x: contain; scroll-snap-type: x mandatory; scrollbar-width: none;
    margin-inline: calc(-1 * clamp(1rem, 3vw, 2.5rem)); padding: 2px clamp(1rem, 3vw, 2.5rem) 6px;
    scroll-padding-inline: clamp(1rem, 3vw, 2.5rem);
  }
  .grid.kennzahlen::-webkit-scrollbar { display: none; }
  .grid.kennzahlen > * { scroll-snap-align: start; }
}

/* ---------- 23. Mobil ---------- */
.mobile-only { display: none; }
/* Der Menüknopf am Telefon.

   `flex: none` ist kein Beiwerk: in der Kopfzeile steht neben ihm der
   Seitentitel, und auf einer Seite mit langem Titel („Mediterráneo Living
   S.L. bearbeiten") drückte der Titel den Knopf von 40 auf 28 Pixel
   zusammen. Derselbe Fehler wie bei den Symbolen in 1.6.1, nur eine Ebene
   höher: ein Bedienelement, das sich vom Text verdrängen lässt. */
.sidebar__toggle { display: none; flex: none; }

@media (max-width: 1023px) {
  /* Die Schublade ist deckend; ihr Schatten erst, wenn sie offen ist – der
     Schatten der geschlossenen Schublade lag sonst als grauer Streifen am
     linken Bildrand. */
  /* Die geschlossene Schublade ist nur verschoben, nicht weg: ohne
     `visibility: hidden` lagen 17–32 Tab-Stopps unsichtbar vor dem Inhalt,
     und Vorleseprogramme lasen die ganze Navigation vor. Beim Schließen
     wartet `visibility` das Hinausgleiten ab (Verzögerung = --dur), beim
     Öffnen gilt sie sofort. Am Rechner (ab 1024 px) gilt nichts davon. */
  .sidebar {
    transform: translateX(-100%); width: min(84vw, 300px); background: var(--surface);
    -webkit-backdrop-filter: none; backdrop-filter: none; box-shadow: none;
    visibility: hidden; transition: transform var(--dur) var(--ease), visibility 0s linear var(--dur);
  }
  .sidebar.is-open { transform: none; box-shadow: var(--shadow-xl); visibility: visible; transition: transform var(--dur) var(--ease), visibility 0s; }
  /* Beim Tabben rollt der Browser das Ziel an den Fensterrand – ohne
     Polster genau unter die feste Unterleiste. */
  html { scroll-padding-bottom: calc(var(--tabbar-h) + env(safe-area-inset-bottom) + var(--space-4)); }
  .main { margin-left: 0; }
  .sidebar__toggle { display: inline-flex; }
  .mobile-only { display: initial; }
  .desktop-only { display: none !important; }
  /* Genau so viel, wie die untere Leiste hoch ist, plus Luft. Vorher waren
     es 6rem und damit 30 Pixel zu viel – auf einer kurzen Seite reichte das,
     um sie scrollbar zu machen, ohne dass es etwas zu scrollen gab. */
  /* Platz für die Tab-Leiste **und** den schwebenden Knopf darüber. Ohne
     den zweiten Summanden liegt der Knopf auf der letzten Zeile der Liste,
     und man kann sie nicht wegscrollen. */
  .page { padding-bottom: calc(var(--tabbar-h) + env(safe-area-inset-bottom) + 4.25rem); }
}

@media (max-width: 640px) {
  /* 16 px Grundschrift am Telefon. Innenabstände von Kopf, Körper und Fuß
     einer Karte kommen gemeinsam aus --card-pad (Token-Block oben) – vorher
     standen hier drei Einzelwerte, und der Fuß lief einmal um vier Pixel
     aus der Flucht. */
  body { font-size: 16px; }
  /* Dialoge kommen am Telefon von unten, mit einem Griff oben. */
  .modal__panel { border-radius: var(--radius-xl) var(--radius-xl) 0 0; align-self: flex-end; max-height: 92vh; width: 100%; padding-bottom: env(safe-area-inset-bottom); }
  .modal__panel::before { content: ""; display: block; width: 36px; height: 5px; border-radius: var(--radius-full); background: var(--border-strong); margin: var(--space-2) auto 0; }
  .modal { place-items: end center; padding: 0; }
  .modal__header, .modal__body, .modal__footer { padding-inline: var(--space-5); }
  .toasts { left: var(--space-4); right: var(--space-4); bottom: var(--space-4); max-width: none; }
  .page-head__actions { width: 100%; }
  .page-head__actions .btn { flex: 1; }
}

/* Untere Navigationsleiste auf Mobilgeräten: Glas in der Kartenfarbe, 90 %
   (vorher 82). Die Beschriftungen sind 12 px – deshalb hier wie auf jedem
   Glas --text-muted statt --text-subtle. */
.tabbar {
  display: none; position: fixed; bottom: 0; left: 0; right: 0; z-index: 50;
  background: var(--glass-surface);
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  border-top: 1px solid var(--border);
  box-shadow: inset 0 1px 0 var(--glass-edge);
  --text-subtle: var(--text-muted);
  padding: var(--space-1) var(--space-2) calc(var(--space-1) + env(safe-area-inset-bottom));
}
.tabbar__inner { display: flex; justify-content: space-around; align-items: stretch; gap: 2px; }
.tabbar__item {
  flex: 1; min-width: 0; min-height: 3.25rem; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
  padding: 2px; border-radius: var(--radius-sm); color: var(--text-subtle); font-size: var(--fs-xs); font-weight: 500; line-height: 1.2;
  transition: color var(--dur-fast) var(--ease);
}
/* Sechs Punkte auf 375 px sind je 58 px breit, „Dokumente" braucht 66 px:
   gekürzt stand dort „Dokum…". Jetzt bricht die Beschriftung an der Silbe in
   eine zweite Zeile („Doku-mente"). Zwei Zeilen passen in die Leiste, ohne
   --tabbar-h zu überschreiten (22 + 2 + 2 × 13,8 + 4 = 55,6 px). */
.tabbar__item span { max-width: 100%; text-align: center; line-height: 1.15; overflow-wrap: anywhere; hyphens: auto; -webkit-hyphens: auto; }
.tabbar__item svg { width: 22px; height: 22px; }
.tabbar__item.is-active { color: var(--accent-text); }
/* Der gewählte Punkt steht auf einer DECKENDEN Pille, nicht auf Glas: seine
   Beschriftung ist --accent-text, und die ist gegen --surface-2 gerechnet
   (head.php). Auf Glas über einem schwarzen Foto läge der Grund darunter
   dunkler als der Rechengrund, und eine Markenfarbe, die dort gerade 4,5:1
   erreicht, fiele auf 4,4. Hell ist die Pille darum GENAU der Rechengrund
   (--surface-2) mit einer Haarlinie (--border): --surface war sie bis zur
   Gegenprüfung 1.18.0 und stand auf dem 90-%-Weiß der Leiste unsichtbar
   (1,01:1; Befund pruef3 #2) – jetzt 1,12:1 gegen das Glas, dazu die Linie,
   eine leise Pille. Dunkel --surface-inset, dunkler als der Rechengrund, ohne
   Linie (wie gebaut). Damit hält die Garantie aus head.php für jede Farbe,
   die eine Agentur einträgt: sieben Probefarben, schlechtester Fall 4,53
   (hell, Gelb) / 5,33 (dunkel, Grau). */
.tabbar__item.is-active { background: var(--surface-2); box-shadow: inset 0 1px 0 var(--glass-edge), 0 0 0 1px var(--border), var(--shadow-xs); }
html[data-theme="dark"] .tabbar__item.is-active { background: var(--surface-inset); box-shadow: inset 0 1px 0 var(--glass-edge), var(--shadow-xs); }
/* Der Rückfall ohne Unschärfe steht für alle Glasflächen gemeinsam am Ende
   des Stilblatts (Abschnitt „Glas 1.18: Rückfälle"). */
@media (max-width: 1023px) { .tabbar { display: block; } }

/* ---------- 24. Druck ---------- */
@media print {
  .sidebar, .topbar, .tabbar, .doc-actions, .btn, .no-print { display: none !important; }
  .main { margin: 0; }
  body { background: #fff; background-image: none; }
  .card, .doc-sheet { box-shadow: none; border: 0; }
  .page { padding: 0; max-width: none; }
}

/* =========================================================================
   Verbindliche Beauftragung
   Die Pflichtangaben stehen unmittelbar über der Schaltfläche und müssen
   „klar und verständlich in hervorgehobener Weise" erscheinen (§ 312j Abs. 2
   BGB, Art. 98.2 TRLGDCU). Das ist hier eine Gestaltungsvorgabe mit
   Rechtsfolge, kein Geschmack: der Kasten hebt sich deshalb sichtbar vom
   übrigen Formular ab und steht immer als erstes im Blickfeld.
   ========================================================================= */
.order-facts {
  border: 1px solid var(--border-accent);
  background: var(--accent-soft);
  border-radius: var(--radius);
  padding: 1rem 1.1rem;
}
.order-facts .pair { padding-block: .3rem; }
.order-facts .pair + .pair { border-top: 1px solid color-mix(in srgb, var(--accent) 14%, transparent); }
.order-facts .pair__value { font-weight: 600; }

.fieldset .req, .label .req { color: var(--danger); }

/* Die Schaltfläche trägt ausschließlich die gesetzliche Formel – der EuGH
   stellt allein auf ihren Text ab (C-249/21). Alles Erklärende steht daneben. */
.btn--order { font-weight: 700; letter-spacing: .005em; }
.order-submit { display: flex; flex-direction: column; align-items: flex-end; gap: .35rem; }
.order-submit__ref { font-size: .78rem; color: var(--text-subtle); }

.modal__footer--order { align-items: center; flex-wrap: wrap; }
@media (max-width: 560px) {
  .modal__footer--order { flex-direction: column-reverse; align-items: stretch; }
  /* `column-reverse` zeigt das KLEINSTE `order` unten. Mit `order: -1` aus
     der Grundregel stand die Kurzfassung der Pflichtangaben am Telefon unter
     „Abbrechen" – nach der Schaltfläche statt davor (§ 312j Abs. 2 BGB).
     Mit dem größten `order` steht sie oben: Kurzfassung, Bestellen, Abbrechen. */
  .modal__footer--order > .order-recap { order: 1; }
  .order-submit { align-items: stretch; }
  .order-submit .btn { width: 100%; justify-content: center; }
  .order-submit__ref { text-align: center; }
}

.policy {
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface-2);
}
.policy > summary {
  padding: var(--space-3) var(--space-4); cursor: pointer; font-size: var(--fs-md); font-weight: 600;
  list-style: none;
}
.policy > summary::-webkit-details-marker { display: none; }
.policy > summary::before { content: "▸ "; color: var(--text-subtle); }
.policy[open] > summary::before { content: "▾ "; }
.policy__body {
  padding: 0 .9rem .9rem; font-size: .82rem; line-height: 1.65; color: var(--text-muted);
  max-height: 20rem; overflow: auto;
}

/* Das Annahmeprotokoll in der Belegansicht. Bewusst nüchtern und
   maschinenhaft: es ist ein Nachweis, keine Zeitleiste. */
.proof { border: 1px solid var(--border); border-radius: var(--radius-sm); overflow: hidden; }
.proof + .proof { margin-top: .6rem; }
.proof__head {
  display: flex; gap: .6rem; align-items: center; flex-wrap: wrap;
  padding: .6rem .8rem; background: var(--surface-2); font-size: .85rem;
}
.proof__body { padding: .7rem .8rem; display: grid; gap: .3rem; }
.proof__row { display: grid; grid-template-columns: minmax(7rem, 12rem) 1fr; gap: .6rem; font-size: .8rem; }
.proof__row dt { color: var(--text-subtle); }
.proof__row dd { color: var(--text); overflow-wrap: anywhere; }
.proof__text {
  margin-top: .5rem; font-size: .76rem; line-height: 1.6; white-space: pre-wrap;
  background: var(--surface-inset); border: 1px solid var(--border); border-radius: var(--radius-xs);
  padding: .6rem .7rem; max-height: 18rem; overflow: auto; color: var(--text-muted);
}
@media (max-width: 640px) {
  .proof__row { grid-template-columns: 1fr; gap: .1rem; }
}

/* =========================================================================
   Der Empfang – die Startseite des Kundenbereichs
   =========================================================================
   Ein Kunde kommt selten hierher und immer aus einem von vier Gründen: ein
   Angebot entscheiden, den Stand sehen, eine Datei abgeben, eine Rechnung
   bezahlen. Deshalb ist diese Seite nicht nach Objektarten sortiert, sondern
   nach der einzigen Frage, die in einer Zusammenarbeit wirklich zählt:
   wer ist am Zug?

   Das ist auch das gestalterische Gerüst. Der schmale Streifen links an jeder
   Karte trägt genau diese Information:
       Gold   – Sie sind am Zug
       Oliv   – wir sind am Zug
       grau   – nichts offen
   Weil Gold sonst nirgends vorkommt, findet das Auge die eigene Aufgabe in
   dem Moment, in dem die Seite erscheint. Ohne Überschrift, ohne Zählerei.
   ========================================================================= */

.lobby { display: grid; gap: clamp(1.25rem, 2.5vw, 2rem); }

/* ---- Empfangsband ---- */
/*
 * Achtung: das Band folgt bewusst NICHT --brand. Diese Farbe wird für den
 * Dunkelmodus aufgehellt (siehe head.php), damit dunkles Oliv auf fast
 * schwarzem Grund nicht verschwindet. Als Fläche hinter weißem Text wird sie
 * dadurch aber viel zu hell – aus dem ruhigen Empfang würde ein grelles
 * Grünfeld. Der Empfang ist eine bewusst dunkle Fläche in beiden
 * Darstellungen, wie eine dunkle Platte auf hellem Papier.
 */
:root {
  --reception-a: #101a06;
  --reception-b: #1d3210;
  --reception-c: #2c4a15;
}
html[data-theme="dark"] {
  --reception-a: #0d1408;
  --reception-b: #16210f;
  --reception-c: #1f2f13;
}
.reception {
  position: relative;
  border-radius: var(--radius-lg);
  background: linear-gradient(160deg, var(--reception-a) 0%, var(--reception-b) 56%, var(--reception-c) 100%);
  border: 1px solid color-mix(in srgb, #fff 8%, transparent);
  color: #fff;
  padding: clamp(1.4rem, 1rem + 1.6vw, 2.4rem);
  overflow: hidden;
  isolation: isolate;
  /* Der Fokusring ist sonst --accent-text: gegen HELLE Flächen gerechnet.
     Auf dem dunklen Band kam das Blau einer Kundenfarbe auf 1,49:1, Oliv
     auf 1,62. Weiß steht hier unabhängig von der Kundenfarbe bei ≥ 10:1. */
  --focus: #fff;
}
/* Ein flacher Lichtschein von oben rechts, wie Tageslicht in einem Raum.
   Bewusst in warmem Weiß und nicht in Gold: Gold bedeutet in dieser
   Oberfläche „Sie sind am Zug". Als Dekoration verwendet, würde es diese
   Bedeutung verwässern – und der eine Knopf, auf den es ankommt, ginge in
   einer goldenen Fläche unter. */
.reception::after {
  content: ""; position: absolute; inset: -55% -18% auto auto;
  width: 55%; aspect-ratio: 1; border-radius: 50%;
  background: radial-gradient(circle, rgba(255, 252, 235, .09), transparent 66%);
  pointer-events: none; z-index: -1;
}
.reception__eyebrow {
  font-size: var(--fs-sm); font-weight: 500; letter-spacing: 0; text-transform: none;
  color: color-mix(in srgb, #fff 70%, transparent);
}
.reception__greeting {
  font-family: var(--font-display);
  font-size: clamp(1.5rem, 1.1rem + 1.5vw, 2.25rem);
  font-weight: 600; letter-spacing: -0.025em; line-height: 1.12;
  color: #fff; margin-top: .35rem; text-wrap: balance;
}
.reception__sub {
  margin-top: .5rem; font-size: 1rem; line-height: 1.55; max-width: 52ch;
  color: color-mix(in srgb, #fff 76%, transparent);
}

/* Die Konzierge-Zeile: ein Satz, eine Handlung. */
.concierge {
  /* Auf breiten Bildschirmen bleibt der Satz lesbar und der Knopf in seiner
     Nähe – über die volle Breite gezogen stünden beide zu weit auseinander. */
  max-width: 58rem;
  margin-top: clamp(1.1rem, 2vw, 1.6rem);
  display: flex; gap: 1rem; align-items: center; flex-wrap: wrap;
  padding: 1rem 1.15rem;
  border-radius: var(--radius);
  background: color-mix(in srgb, #fff 11%, transparent);
  border: 1px solid color-mix(in srgb, #fff 16%, transparent);
  border-left: 4px solid var(--gold);
}
.concierge--ours { border-left-color: color-mix(in srgb, #fff 45%, transparent); }
.concierge__text { flex: 1 1 22rem; min-width: 0; }
/* Gold ist in dieser Oberfläche die Farbe für „Sie sind am Zug" – also trägt
   auch der Knopf sie. Der sonst übliche Akzent ist die Markenfarbe des Kunden
   und kann alles Mögliche sein; auf dem dunkelgrünen Band wäre das Zufall. */
.concierge .btn--accent {
  background: var(--gold); color: #23200a; border-color: transparent; font-weight: 600;
}
.concierge .btn--accent:hover { background: color-mix(in srgb, var(--gold) 88%, #fff); color: #23200a; }
.concierge .btn--ghost {
  border-color: color-mix(in srgb, #fff 34%, transparent); color: #fff;
  background: color-mix(in srgb, #fff 6%, transparent);
}
.concierge .btn--ghost:hover { background: color-mix(in srgb, #fff 16%, transparent); }
.concierge__label {
  font-size: var(--fs-sm); font-weight: 600; letter-spacing: 0; text-transform: none;
  /* Gold mit Weiß aufgehellt: reines Gold auf dem Band hielt 3,34:1. Mit 55 %
     Gold 4,8:1 hell, 5,4:1 dunkel – die Farbe bleibt als Gold erkennbar. */
  color: color-mix(in srgb, var(--gold) 55%, #fff);
}
.concierge--ours .concierge__label { color: color-mix(in srgb, #fff 72%, transparent); }
.concierge__line { margin-top: 2px; font-size: var(--fs-lg); line-height: 1.45; color: #fff; }
.concierge__line strong { color: #fff; font-weight: 600; }
.concierge .btn { flex: none; }

/* Der ruhige Streifen darunter: was sonst noch offen ist. */
.reception__meta {
  margin-top: 1.1rem; display: flex; flex-wrap: wrap; gap: .4rem .5rem;
}
.tally {
  display: inline-flex; align-items: center; gap: .45rem;
  padding: .35rem .7rem; border-radius: var(--radius-full);
  background: color-mix(in srgb, #fff 9%, transparent);
  border: 1px solid color-mix(in srgb, #fff 13%, transparent);
  font-size: var(--fs-sm); color: color-mix(in srgb, #fff 82%, transparent);
  transition: background-color var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
a.tally:hover { background: color-mix(in srgb, #fff 17%, transparent); border-color: color-mix(in srgb, #fff 28%, transparent); }
.tally svg { width: 15px; height: 15px; opacity: .8; }
.tally__count { font-variant-numeric: tabular-nums; font-weight: 600; color: #fff; }
.tally--yours { border-color: color-mix(in srgb, var(--gold) 55%, transparent); }
.tally--yours .tally__count { color: color-mix(in srgb, var(--gold) 55%, #fff); }

/* ---- Wer ist am Zug: der Streifen an Karten ---- */
.move { position: relative; padding-left: 1.1rem; }
.move::before {
  content: ""; position: absolute; left: 0; top: .15rem; bottom: .15rem; width: 3px;
  border-radius: 3px; background: var(--surface-3);
}
.move--yours::before { background: var(--gold); }
.move--ours::before  { background: var(--accent); }

/* ---- Projektplatten ---- */
.plates { display: grid; gap: 1rem; grid-template-columns: repeat(auto-fill, minmax(min(100%, 20rem), 1fr)); }
.plate {
  position: relative; display: flex; flex-direction: column; gap: .55rem;
  padding: 1.15rem 1.25rem 1.25rem;
  border-radius: var(--radius);
  background: var(--surface);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-xs);
  transition: box-shadow var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.plate::before {
  content: ""; position: absolute; left: 0; top: 1.15rem; bottom: 1.15rem; width: 3px;
  border-radius: 0 3px 3px 0; background: var(--surface-3);
}
.plate--yours::before { background: var(--gold); }
.plate--ours::before  { background: var(--accent); }
.plate:hover { box-shadow: var(--shadow); border-color: var(--border-strong); }
.plate__head { display: flex; justify-content: space-between; gap: var(--space-3); align-items: flex-start; }
.plate__name { font-family: var(--font-display); font-size: var(--fs-lg); font-weight: 600; letter-spacing: -0.005em; }
.plate__teaser { font-size: var(--fs-md); color: var(--text-muted); }
.plate__foot { margin-top: auto; padding-top: var(--space-2); display: flex; justify-content: space-between; align-items: center; gap: var(--space-2); font-size: var(--fs-sm); color: var(--text-subtle); }
.plate__bar { height: 5px; border-radius: 3px; background: var(--surface-3); overflow: hidden; }
.plate__bar span { display: block; height: 100%; border-radius: 3px; background: var(--brand-client, var(--accent)); }

/* ---- Abschnittsköpfe im Kundenbereich ---- */
.lobby-head { display: flex; justify-content: space-between; align-items: baseline; gap: 1rem; margin-bottom: .85rem; }
.lobby-head h2 { font-size: var(--fs-xl); letter-spacing: -0.012em; }
.lobby-head p { font-size: var(--fs-md); margin-top: 2px; }

/* ---- Einlauf beim Öffnen: ein einziger, kurzer Auftritt ---- */
@media (prefers-reduced-motion: no-preference) {
  .lobby > * { animation: lobby-rise .5s var(--ease) both; }
  .lobby > *:nth-child(2) { animation-delay: .06s; }
  .lobby > *:nth-child(3) { animation-delay: .12s; }
  .lobby > *:nth-child(n+4) { animation-delay: .16s; }
}
@keyframes lobby-rise {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: none; }
}

@media (max-width: 620px) {
  /* Ohne das dehnt sich der Textblock über seine Grundbreite von 22rem und
     reißt eine leere Fläche zwischen Satz und Knopf auf. */
  .concierge { flex-direction: column; align-items: stretch; gap: .85rem; }
  .concierge__text { flex: 0 1 auto; }
  .concierge .btn { width: 100%; justify-content: center; }
  .reception__meta { gap: .35rem; }
  /* 40 px wie die Chips am Telefon – die Zähler sind Links (gemessen 33 px). */
  .tally { font-size: var(--fs-sm); padding: .3125rem .75rem; min-height: 2.5rem; }
}

/* Kurzfassung der Pflichtangaben unmittelbar über der Bestellschaltfläche.
   Der ausführliche Kasten steht oben im Dialog; bei kleinem Bildschirm ist er
   beim Klicken weggescrollt. § 312j Abs. 2 BGB verlangt die Angaben aber
   „unmittelbar bevor der Verbraucher seine Bestellung abgibt". */
.order-recap {
  flex: 1 0 100%;
  width: 100%;
  order: -1;
  display: flex; flex-wrap: wrap; align-items: baseline; gap: .25rem .6rem;
  padding: .6rem .8rem; margin-bottom: .25rem;
  border-radius: var(--radius-sm);
  background: var(--accent-soft);
  font-size: .85rem; line-height: 1.4;
}
.order-recap__what { font-weight: 640; color: var(--text); }
.order-recap__sum  { font-weight: 700; color: var(--text); }
.order-recap__note { color: var(--text-muted); flex-basis: 100%; font-size: var(--fs-sm); }

/* =========================================================================
   Betreiberbereich
   -------------------------------------------------------------------------
   Ein eigener Raum, kein Reiter. Wer hier arbeitet, arbeitet nicht in seiner
   Agentur, sondern an einem Produkt für andere – und diese beiden Rollen zu
   verwechseln ist die Ursache der meisten Unfälle in Mehrmandantensystemen.

   Das Erkennungszeichen ist deshalb bewusst eines, das sich nicht mitdenken
   lässt: eine tiefdunkle Leiste, in beiden Modi gleich. Sie sieht in keinem
   Zustand aus wie die normale Seitenleiste. Gold kommt hier ausdrücklich
   nicht vor – es bedeutet in dieser Oberfläche „Sie sind am Zug", und der
   Betreiberbereich ist kein Vorgang, der auf eine Entscheidung wartet.
   ========================================================================= */
.shell--operator {
  --op-ink:      #10150c;
  --op-ink-2:    #1a2113;
  --op-line:     rgba(233, 238, 224, .12);
  --op-text:     #e9eee0;
  --op-muted:    #9aa38c;
}

.sidebar--operator {
  background: var(--op-ink);
  border-right-color: var(--op-line);
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
  box-shadow: none;
  color: var(--op-text);
  /* Die Leiste ist in beiden Modi dunkel; --accent-text ist für helle
     Flächen gerechnet (Oliv genau 3,0:1, auf dem Überfahr-Grund 2,68). */
  --focus: var(--op-text);
}
.sidebar--operator .sidebar__wordmark { color: var(--op-text); }
/* Rollenlabel „Betreiber": --text-subtle ist für helle Flächen abgedunkelt
   und kam auf der dunklen Leiste auf 3,51:1. */
.sidebar--operator .subtle { color: var(--op-muted); }
.sidebar--operator .sidebar__wordmark span { color: var(--op-muted); }
.sidebar--operator .sidebar__section { color: var(--op-muted); }
.sidebar--operator .sidebar__footer { border-top-color: var(--op-line); }

.sidebar--operator .nav-item { color: var(--op-muted); }
.sidebar--operator .nav-item:hover { background: var(--op-ink-2); color: var(--op-text); }
.sidebar--operator .nav-item.is-active { background: var(--op-ink-2); color: var(--op-text); box-shadow: inset 0 1px 0 rgba(233, 238, 224, .08); }
.sidebar--operator .nav-item.is-active::before { background: var(--op-text); }
.sidebar--operator .nav-item.is-active svg { color: var(--op-text); }
.sidebar--operator .nav-item .flex-1 .font-semibold { color: var(--op-text) !important; }
.sidebar--operator .avatar { background: var(--op-ink-2); color: var(--op-text); }

.sidebar--operator .dropdown__menu {
  background: var(--op-ink);
  border-color: var(--op-line);
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
  box-shadow: inset 0 1px 0 rgba(233, 238, 224, .08), var(--glass-shadow);
  color: var(--op-text);
}
.sidebar--operator .dropdown__item { color: var(--op-muted); }
.sidebar--operator .dropdown__item:hover { background: var(--op-ink-2); color: var(--op-text); }
.sidebar--operator .dropdown__divider { background: var(--op-line); }

/* Das Zeichen des Betreibers im Kopf der Leiste: eine Marke, kein Logo. */
.op-mark {
  width: 30px; height: 30px; flex: none;
  display: grid; place-items: center;
  border-radius: var(--radius-xs);
  background: var(--op-ink-2);
  border: 1px solid var(--op-line);
  color: var(--op-text, #e9eee0);
  font-weight: 600; font-size: var(--fs-sm); letter-spacing: 0;
}

/* -------------------------------------------------------------------------
   Das Band während eines Blicks in einen fremden Mandanten.
   Es steht über allem, in derselben Tinte wie die Betreiberleiste: dieselbe
   Farbe heißt hier dieselbe Rolle. Ohne dieses Band würde man nach zwei
   Klicks vergessen, dass man zu Gast ist – und genau daraus entstehen die
   Einträge, die man später niemandem erklären kann.
   ------------------------------------------------------------------------- */
.peek {
  position: sticky; top: 0; z-index: 70;
  display: flex; align-items: center; flex-wrap: wrap; gap: .5rem .9rem;
  padding: .55rem clamp(1rem, 3vw, 1.75rem);
  /* Glas in der Betreibertinte (90 %): das Band klebt oben, der Inhalt läuft
     darunter durch. Gerechnet gegen Weiß: die Notiz #9aa38c hält 5,4:1. */
  background: color-mix(in srgb, #10150c 90%, transparent);
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  color: #e9eee0;
  font-size: .85rem; line-height: 1.4;
  box-shadow: inset 0 1px 0 rgba(233, 238, 224, .08), 0 1px 0 rgba(233, 238, 224, .12);
}
.peek__icon { display: flex; opacity: .8; }
.peek__icon svg { width: 16px; height: 16px; }
.peek__text { flex: 1 1 16rem; min-width: 0; }
.peek__who { font-weight: 600; }
.peek__note { color: #9aa38c; }
.peek .btn {
  --btn-bg: rgba(233, 238, 224, .12);
  --btn-fg: #e9eee0;
  --btn-border: rgba(233, 238, 224, .22);
  padding: .3rem .7rem; font-size: .8125rem;
}
.peek .btn:hover { --btn-bg: rgba(233, 238, 224, .2); }

/* Im Dunkeln liegt die Betreibertinte fast auf dem Seitengrund – das Band
   verschwände. Es soll aber genau nicht zu übersehen sein, also wird es hier
   heller als die Seite statt dunkler. Die Rolle bleibt dieselbe, nur die
   Richtung des Kontrasts dreht sich. */
html[data-theme="dark"] .peek {
  background: color-mix(in srgb, #222b19 90%, transparent);
  box-shadow: inset 0 1px 0 rgba(233, 238, 224, .08), 0 1px 0 rgba(233, 238, 224, .16);
}
html[data-theme="dark"] .peek__note { color: #b0b9a2; }

@media (max-width: 620px) {
  .peek { font-size: .8rem; }
  .peek__note { flex-basis: 100%; }
}

/* =========================================================================
   Geführte Einrichtung
   -------------------------------------------------------------------------
   Eine Spalte, kein Menü. Wer hier ist, hat genau eine Aufgabe; alles, was
   daneben stünde, wäre eine Ablenkung von ihr. Die Schrittleiste zeigt
   nicht nur, wo man ist, sondern auch, wie wenig noch kommt – das ist der
   Grund, aus dem jemand weitermacht.
   ========================================================================= */
.setup { min-height: 100vh; min-height: 100dvh; display: flex; flex-direction: column; }

.setup__bar {
  display: flex; align-items: center; gap: var(--space-3);
  min-height: var(--topbar-h); padding: var(--space-2) clamp(1rem, 4vw, 2rem);
  border-bottom: 1px solid var(--border);
  background: var(--glass-bg);
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  box-shadow: inset 0 1px 0 var(--glass-edge);
  --text-subtle: var(--text-muted);
  position: sticky; top: 0; z-index: 40;
}

.setup__body {
  flex: 1;
  width: 100%; max-width: 62rem;
  margin: 0 auto;
  padding: clamp(1.5rem, 4vw, 3rem) clamp(1rem, 4vw, 2rem) 4rem;
}

.setup__legal {
  padding: 1.25rem clamp(1rem, 4vw, 2rem) 2rem;
  text-align: center; font-size: .8rem; color: var(--text-subtle);
}

/* Die Schrittleiste. Erledigte Schritte bleiben sichtbar – zurückgelegter
   Weg ist das beste Argument gegen den Abbruch. */
.setup__steps {
  display: flex; flex-wrap: wrap; align-items: center;
  /* Engere Lücken und Verbinder: mit sechs beschrifteten Schritten brach die
     Leiste bei 1440 px um – „Immobilien" stand allein in Zeile zwei, davor ein
     Strich ins Leere (≈ 1124 px Bedarf in 928 px). */
  gap: .35rem clamp(.375rem, 1vw, .75rem);
  margin-bottom: clamp(1.5rem, 3vw, 2.5rem);
}
.setup__step { display: flex; align-items: center; gap: .5rem; min-width: 0; }
.setup__step + .setup__step::before {
  content: ""; width: clamp(.5rem, 1.2vw, 1rem); height: 1px;
  background: var(--border-strong); margin-right: clamp(.375rem, 1vw, .75rem);
}
.setup__dot {
  width: 26px; height: 26px; flex: none;
  display: grid; place-items: center;
  border-radius: var(--radius-full);
  border: 1px solid var(--border-strong);
  background: var(--surface);
  font-size: var(--fs-xs); font-weight: 600; color: var(--text-subtle); font-variant-numeric: tabular-nums;
}
.setup__dot svg { width: 14px; height: 14px; }
.setup__step-label { font-size: var(--fs-md); color: var(--text-subtle); white-space: nowrap; }

.setup__step.is-done .setup__dot {
  background: var(--accent); border-color: var(--accent); color: var(--accent-on);
}
.setup__step.is-done .setup__step-label { color: var(--text-muted); }

/* Der aktuelle Schritt ist die Stelle, an der etwas von einem erwartet
   wird – der einzige Ort auf dieser Seite, an dem Gold richtig ist. */
.setup__step.is-current .setup__dot {
  background: var(--gold); border-color: var(--gold); color: #23200a;
  box-shadow: 0 0 0 4px var(--gold-soft);
}
.setup__step.is-current .setup__step-label { color: var(--text); font-weight: 600; }

.setup__head { margin-bottom: clamp(1.25rem, 3vw, 2rem); }
.setup__head h1 {
  font-size: clamp(1.6rem, 1.2rem + 1.4vw, 2.2rem);
  letter-spacing: -0.03em; margin: .35rem 0 .5rem;
  text-wrap: balance;
}
.setup__head .lead { max-width: 52ch; }

.setup__foot {
  display: flex; align-items: center; justify-content: space-between;
  flex-wrap: wrap; gap: 1rem;
  padding-top: .5rem;
}

@media (max-width: 620px) {
  .setup__step-label { display: none; }
  .setup__step.is-current .setup__step-label { display: inline; }
  /* Der Verbinder hat rechts schon die Lücke des Schritts; ohne den Zusatzrand
     passen sechs Punkte bei 390 px in eine Zeile (vorher „6" allein darunter). */
  .setup__step + .setup__step::before { margin-right: 0; }
  .setup__foot { flex-direction: column-reverse; align-items: stretch; }
  .setup__foot .btn { justify-content: center; }
  .setup__foot .row { justify-content: center; }
}

/* =========================================================================
   Buchungsstrecke und Rechtstexte
   -------------------------------------------------------------------------
   Die einzigen Seiten, die jemand sieht, bevor er Kunde ist. Sie tragen
   deshalb die Marke des Betreibers und nicht die eines Mandanten – und sie
   dürfen ruhiger sein als die Anwendung: hier wird gelesen und entschieden,
   nicht gearbeitet.
   ========================================================================= */
.booking { min-height: 100vh; min-height: 100dvh; display: flex; flex-direction: column; }

.booking__bar {
  display: flex; align-items: center; gap: var(--space-3);
  min-height: var(--topbar-h); padding: var(--space-2) clamp(1rem, 4vw, 2rem);
  border-bottom: 1px solid var(--border);
  background: var(--glass-bg);
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  box-shadow: inset 0 1px 0 var(--glass-edge);
  --text-subtle: var(--text-muted);
  position: sticky; top: 0; z-index: 40;
}

.booking__langs { display: flex; gap: 2px; }
.booking__lang {
  padding: .3125rem .5rem; border-radius: var(--radius-sm);
  font-size: var(--fs-xs); font-weight: 600; letter-spacing: .02em;
  color: var(--text-subtle);
}
.booking__lang:hover { background: var(--surface-2); color: var(--text); }
.booking__lang.is-active { background: var(--surface-3); color: var(--text); }

.booking__body {
  flex: 1; width: 100%; max-width: 74rem;
  margin: 0 auto;
  padding: clamp(1.75rem, 4vw, 3.5rem) clamp(1rem, 4vw, 2rem) 4rem;
}

.booking__head { margin-bottom: clamp(1.75rem, 4vw, 3rem); max-width: 44rem; }
.booking__head--tight { margin-bottom: clamp(1.25rem, 3vw, 2rem); }
.booking__head h1 {
  font-size: clamp(1.8rem, 1.3rem + 2vw, 2.7rem);
  letter-spacing: -0.035em; line-height: 1.1;
  margin: .35rem 0 .75rem; text-wrap: balance;
}

.booking__foot { border-top: 1px solid var(--border); padding: 1.5rem clamp(1rem, 4vw, 2rem) 2.5rem; }
.booking__foot-inner {
  max-width: 74rem; margin: 0 auto;
  display: flex; flex-wrap: wrap; gap: .75rem 1.5rem;
  align-items: center; justify-content: space-between;
  font-size: .85rem; color: var(--text-subtle);
}

/* ---------------- Die Stufen ---------------- */
.plan-grid {
  display: grid; gap: clamp(1rem, 2vw, 1.5rem);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 250px), 1fr));
  align-items: stretch;
}

.plan-card {
  display: flex; flex-direction: column;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: clamp(1.25rem, 2vw, 1.75rem);
  box-shadow: var(--shadow-sm);
  transition: box-shadow var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.plan-card:hover { box-shadow: var(--shadow); border-color: var(--border-strong); }
.plan-card__head h2 { font-size: 1.3rem; letter-spacing: -0.02em; }
.plan-card__for { font-size: .875rem; color: var(--text-muted); margin-top: .2rem; }

.plan-card__price { display: flex; align-items: baseline; gap: .5rem; flex-wrap: wrap; margin: 1.15rem 0 1.25rem; }
.plan-card__amount {
  font-size: clamp(1.9rem, 1.5rem + 1.2vw, 2.4rem); font-weight: 700;
  letter-spacing: -0.04em; font-variant-numeric: tabular-nums;
}
.plan-card__unit { font-size: .8rem; line-height: 1.35; color: var(--text-muted); }

.plan-card__list { display: flex; flex-direction: column; gap: .45rem; flex: 1; margin-bottom: 1.25rem; }
.plan-card__list li { display: flex; align-items: flex-start; gap: .5rem; font-size: .9rem; line-height: 1.45; }
.plan-card__list svg { width: 16px; height: 16px; flex: none; margin-top: 2px; color: var(--accent-text); }
.plan-card__list li.subtle svg { color: var(--text-subtle); }

/* Umfang: was die Stufe fasst, nicht was sie kann. Eigener Block, eigene
   Schrift, kein Haken – der Unterschied soll ohne Erklärung lesbar sein. */
.plan-card__scope {
  border-top: 1px solid var(--border); padding-top: .8rem; margin-bottom: 1.25rem;
}
.plan-card__scope-label {
  display: block; font-size: var(--fs-xs); font-weight: 500; letter-spacing: 0;
  text-transform: none; color: var(--text-subtle); margin-bottom: var(--space-1);
}
.plan-card__scope-list { display: flex; flex-wrap: wrap; gap: .3rem .9rem; }
.plan-card__scope-list li {
  font-size: .85rem; color: var(--text-muted); font-variant-numeric: tabular-nums;
}

/* ---------------- Der Kasten neben dem Formular ---------------- */
@media (min-width: 1100px) {
  .booking__summary { position: sticky; top: 5.5rem; }
}

/* Der Gesamtbetrag ist die wichtigste Zeile der Seite und darf deshalb auch
   so aussehen. Die offene Fassung daneben ist bewusst KEIN Betrag und auch
   keine Zahl in Grau – sie ist ein Wort, damit niemand sie für eine hält. */
.pair--total .pair__value { font-size: 1.15rem; font-weight: 640; }
.pair__value--offen {
  font-size: .85rem; font-weight: 550; color: var(--text-muted);
  font-style: normal; letter-spacing: .01em;
}
/* Beim Nachrechnen dämpfen statt springen: die Zahlen bleiben stehen, treten
   aber zurück, bis die neue Antwort da ist. */
.order-facts { transition: opacity .15s ease; }
.order-facts.is-rechnet { opacity: .55; }
.order-facts .numeric { font-variant-numeric: tabular-nums; }
.order-facts__fehler {
  margin-top: .6rem; font-size: .82rem; line-height: 1.5;
  color: var(--danger); background: var(--danger-soft);
  padding: .5rem .65rem; border-radius: 8px;
}
.order-recap__sum--offen { font-size: .9rem; font-weight: 550; color: var(--text-muted); }

/* Drei Wörter mit einem Trennstrich dazwischen. Die Betonung liegt auf dem
   Schritt, in dem man steht; der erledigte tritt zurück, der kommende ist
   nur Ausblick. Mehr braucht eine Strecke aus drei Schritten nicht. */
.booking__schritte {
  display: flex; align-items: center; flex-wrap: wrap; gap: .5rem;
  margin-top: 1.1rem; font-size: .8rem; letter-spacing: .01em;
}
.booking__schritte li { display: flex; align-items: center; gap: .5rem; color: var(--text-subtle); }
.booking__schritte li + li::before {
  content: ""; width: 1.4rem; height: 1px; background: var(--border); flex: none;
}
.booking__schritte .is-fertig { color: var(--text-muted); }
.booking__schritte .is-hier { color: var(--accent-text); font-weight: 620; }

/* Die Zwischenseite zum Zahlungsdienstleister. Sie soll ruhig aussehen und
   in der Sekunde, die sie zu sehen ist, nichts fordern. */
.weiterleitung { display: grid; place-items: center; padding: clamp(2rem, 8vw, 6rem) 1rem; }
.weiterleitung__karte { max-width: 26rem; text-align: center; }
.weiterleitung__zeichen {
  display: inline-grid; place-items: center; width: 3rem; height: 3rem;
  border-radius: var(--radius-full); background: var(--accent-soft); color: var(--accent-text);
  margin-bottom: 1rem;
}
.weiterleitung__zeichen svg { width: 22px; height: 22px; }
.weiterleitung__karte h1 { font-size: 1.35rem; letter-spacing: -.02em; margin-bottom: .5rem; }

.booking__note { margin-top: clamp(2.5rem, 5vw, 4rem); }
.booking__note h2 { font-size: 1.25rem; letter-spacing: -0.02em; margin-bottom: 1.25rem; }
.booking__note h3 {
  display: flex; align-items: center; gap: .5rem;
  font-size: .95rem; font-weight: 640; margin-bottom: .4rem;
}
.booking__note h3 svg { width: 17px; height: 17px; color: var(--accent-text); flex: none; }
.booking__note p { font-size: .9rem; line-height: 1.6; color: var(--text-muted); }

.booking__done { max-width: 34rem; margin: clamp(1rem, 5vw, 3rem) auto; text-align: center; }
.booking__done h1 { font-size: clamp(1.6rem, 1.3rem + 1.4vw, 2.2rem); letter-spacing: -0.03em; margin: .75rem 0 .5rem; }
/* Das Symbol über dem zentrierten Text („Gerade nicht möglich") stand links:
   .result__icon ist ein Rasterkasten, text-align erreicht ihn nicht. */
.booking__done .result__icon { margin-inline: auto; }

/* ---------------- Fließtext der Rechtsdokumente ---------------- */
/* Das Textmaß gilt für den Fließtext, nicht für den ganzen Block: Tabellen
   in Rechtstexten haben bis zu vier Spalten und werden in 68 Zeichen
   unlesbar schmal. Deshalb bekommt jedes Kind das Maß – die Tabellen
   ausgenommen. */
.prose { max-width: none; }
.prose > * { max-width: 68ch; }
.prose > .table-wrap { max-width: none; }
.prose h2 { font-size: 1.35rem; letter-spacing: -0.02em; margin: 2rem 0 .6rem; text-wrap: balance; }
.prose h3 { font-size: 1.075rem; font-weight: 650; margin: 1.6rem 0 .5rem; text-wrap: balance; }
.prose h4 { font-size: .95rem; font-weight: 650; margin: 1.2rem 0 .4rem; }
.prose > :first-child { margin-top: 0; }
.prose p { margin-bottom: .9rem; line-height: 1.68; }
.prose ul, .prose ol { margin: 0 0 1rem 1.35rem; display: flex; flex-direction: column; gap: .4rem; }
.prose ul { list-style: disc; }
.prose ol { list-style: decimal; }
.prose li { line-height: 1.6; padding-left: .2rem; }
.prose li::marker { color: var(--text-subtle); }
.prose strong { font-weight: 650; }
.prose code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: .875em; background: var(--surface-2);
  padding: .1rem .35rem; border-radius: 5px;
}
.prose blockquote {
  border-left: 3px solid var(--accent);
  background: var(--surface-2);
  padding: .9rem 1.1rem; margin: 0 0 1.1rem;
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
}
.prose blockquote p:last-child { margin-bottom: 0; }

/* ---------- Handbuch ---------- */
/* Verzeichnis links, Text rechts. Das Verzeichnis bleibt stehen, während man
   liest – eines, das man zum Weiterblättern erst wieder hochscrollen muss,
   benutzt beim zweiten Mal niemand. */
.handbuch { display: grid; grid-template-columns: minmax(0, 15rem) minmax(0, 1fr); gap: 1.5rem; align-items: start; }
.handbuch__inhalt { position: sticky; top: 1rem; }
.handbuch__klapp { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); }
.handbuch__summary {
  cursor: pointer; list-style: none; padding: var(--space-3) var(--space-4);
  font-size: var(--fs-sm); font-weight: 500; letter-spacing: 0; text-transform: none;
  color: var(--text-subtle); display: flex; align-items: center; justify-content: space-between; gap: .5rem;
}
.handbuch__summary::-webkit-details-marker { display: none; }
.handbuch__summary::after { content: '+'; font-size: 1rem; line-height: 1; }
.handbuch__klapp[open] .handbuch__summary::after { content: '–'; }
.handbuch__liste {
  list-style: none; margin: 0; padding: 0 .5rem .6rem;
  max-height: calc(100vh - 8rem); overflow-y: auto;
}
.handbuch__liste a {
  display: flex; gap: .5rem; align-items: baseline;
  padding: .35rem .55rem; border-radius: var(--radius-xs);
  font-size: .8375rem; line-height: 1.35; color: var(--text-muted);
}
.handbuch__liste a:hover { background: var(--surface-2); color: var(--text); }
.handbuch__nr { font-variant-numeric: tabular-nums; color: var(--text-subtle); flex: none; min-width: 1.2em; text-align: right; }
.handbuch__text { padding: 1.5rem 1.75rem; }
/* Ein Sprung soll die Überschrift nicht an den oberen Rand kleben. */
.handbuch__text :where(h2, h3) { scroll-margin-top: 1.5rem; }
.handbuch__text h2 { padding-top: 1.2rem; border-top: 1px solid var(--border); }
.handbuch__text > h2:first-child { border-top: 0; padding-top: 0; }
.handbuch__text h2 + h3 { margin-top: 1rem; }

@media (max-width: 900px) {
  /* `minmax(0, 1fr)` und nicht `1fr`: ein Rasterfeld hat von Haus aus
     `min-width: auto` und wächst mit seinem breitesten Kind. Im Handbuch
     stehen Tabellen mit 46 rem Mindestbreite – daraus wurde eine Spalte von
     771 px auf einem 390 px breiten Telefon, und die ganze Seite ließ sich
     seitwärts schieben. Die Tabelle scrollt jetzt in sich selbst. */
  .handbuch { grid-template-columns: minmax(0, 1fr); }
  .handbuch__inhalt { position: static; }
  .handbuch__liste { max-height: 55vh; }
  /* Am Telefon 44 px je Kapitel (gemessen 29 px bei 26 Kapiteln). */
  .handbuch__liste a { min-height: 44px; align-items: center; }
  .handbuch__text { padding: 1.1rem; }
}
.prose hr { border: 0; border-top: 1px solid var(--border); margin: 2rem 0; }
.prose .table-wrap { margin-bottom: 1.2rem; }
/* Tabellen in Fließtext sind Inhalt, nicht Layout: die Angaben im Impressum,
   die Liste der Unterauftragsverarbeiter, die Übersicht der Maßnahmen. Die
   allgemeine Mindestbreite von 46rem passt nicht in ein 68 Zeichen breites
   Textmaß – die Tabelle scrollte dann waagerecht und schnitt ausgerechnet
   die Anschrift ab. Hier darf sie umbrechen statt zu scrollen. */
.prose .table-wrap > .table { min-width: 0; width: 100%; }
/* Vier Spalten brauchen mehr als das Textmaß. Nur die Tabelle bricht aus,
   der Fließtext behält seine 68 Zeichen. */
.prose .table-wrap { width: min(100%, 52rem); }
.prose table { font-size: .9rem; }
.prose th, .prose td { white-space: normal; overflow-wrap: break-word; }
.prose thead:empty, .prose thead tr:has(th:empty:only-child) { display: none; }

@media (max-width: 620px) {
  .booking__foot-inner { flex-direction: column; align-items: flex-start; }
  .plan-card__amount { font-size: 1.9rem; }
}

/* ---------- Postabruf: die Fortschrittszeile ----------
   Erscheint nur, während geholt wird, und liegt über der ganzen Breite unter
   der Kopfzeile. Neben der Schaltfläche stand sie zuerst – dort schob sie die
   Kopfzeile auseinander, sobald sie auftauchte, und ein springendes Layout
   beim Klicken lässt jeden Vorgang unruhig wirken. */
.abruf { position: relative; }
.abruf__bar {
  height: 4px; border-radius: var(--radius-full); background: var(--border);
  overflow: hidden;
}
.abruf__fill {
  display: block; height: 100%; border-radius: var(--radius-full);
  background: var(--accent);
  transition: width .45s cubic-bezier(.4, 0, .2, 1);
}
.abruf__text {
  margin: .35rem 0 0; font-size: .78rem; color: var(--text-subtle);
  font-variant-numeric: tabular-nums;
}
.abruf--fehler .abruf__fill { background: var(--danger); }
.abruf--fehler .abruf__text { color: var(--danger); }
@media (prefers-reduced-motion: reduce) {
  .abruf__fill { transition: none; }
}

/* ==================== Der Begleiter ====================
   Ein Fenster neben der Seite, kein Vollbild und kein Balken, der etwas
   wegschiebt. Es liegt über allem, aber nur, solange es offen ist. */
.begleiter { position: fixed; right: 1.25rem; bottom: 1.25rem; z-index: 60; }
/* Beim Scrollen tritt der Knopf zur Seite – er schwebt über fremdem Inhalt,
   und der Daumen, der scrollt, will ihn ohnehin gerade nicht drücken. */
.begleiter { transition: transform .2s var(--ease, ease), opacity .2s ease; }
.begleiter.is-weg { transform: translateY(120%) scale(.9); opacity: 0; pointer-events: none; }
@media (prefers-reduced-motion: reduce) {
  .begleiter { transition: opacity .2s ease; }
  .begleiter.is-weg { transform: none; opacity: 0; }
}

/* Der Knopf soll auffallen, ohne zu schreien: Akzentfarbe, ein Funke, und
   ein Schein in derselben Farbe statt eines grauen Schattens. Ein grauer
   Kreis unter vielen grauen Flächen wird schlicht übersehen – und was man
   nicht sieht, benutzt man nicht. */
.begleiter__knopf {
  width: 3.25rem; height: 3.25rem; border-radius: var(--radius-full); border: 0;
  /* Der Funke liegt auf der Akzentfläche – welche Schriftfarbe darauf lesbar
     ist, rechnet head.php aus. Weiß auf Gold kam auf 2,2; man sah ihn kaum. */
  background: var(--accent); color: var(--accent-on); cursor: pointer;
  display: grid; place-items: center;
  box-shadow: 0 6px 20px color-mix(in srgb, var(--accent) 40%, transparent),
              0 2px 6px rgba(22, 32, 11, .16);
  transition: box-shadow var(--dur) ease, filter var(--dur) ease;
}
.begleiter__knopf:hover {
  filter: brightness(1.06);
  box-shadow: 0 10px 28px color-mix(in srgb, var(--accent) 50%, transparent),
              0 3px 8px rgba(22, 32, 11, .18);
}
.begleiter__knopf:focus-visible { outline: 3px solid var(--focus); outline-offset: 3px; }
/* Offen ist er ruhig: dann redet das Fenster, nicht der Knopf. */
.begleiter__knopf.is-offen {
  background: var(--surface); color: var(--text); border: 1px solid var(--border);
  box-shadow: var(--shadow);
}
.begleiter__knopf svg { width: 22px; height: 22px; }
.begleiter__knopf svg path:first-child { fill: currentColor; fill-opacity: .18; }

.begleiter__panel {
  position: absolute; right: 0; bottom: 3.9rem;
  width: min(26rem, calc(100vw - 2.5rem));
  height: min(34rem, calc(100vh - 8rem));
  display: flex; flex-direction: column;
  background: var(--glass-surface); border: 1px solid var(--border); border-radius: var(--radius-lg);
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  box-shadow: inset 0 1px 0 var(--glass-edge), var(--shadow-xl); overflow: hidden;
  --text-subtle: var(--text-muted);
}

.begleiter__kopf {
  display: flex; flex-direction: column; gap: var(--space-2);
  padding: var(--space-3) var(--space-3) var(--space-3) var(--space-4); border-bottom: 1px solid var(--border);
}
.begleiter__kopf-zeile { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); }
.begleiter__marke {
  display: inline-flex; align-items: center; gap: var(--space-2);
  font-size: var(--fs-md); font-weight: 600; letter-spacing: 0;
}
.begleiter__marke-zeichen {
  display: grid; place-items: center; width: 1.5rem; height: 1.5rem; border-radius: var(--radius-full);
  background: color-mix(in srgb, var(--accent) 16%, transparent); color: var(--accent-text);
}
.begleiter__marke-zeichen svg { width: 14px; height: 14px; }
.begleiter__modi { display: flex; gap: 2px; background: var(--surface-2); border-radius: var(--radius-full); padding: 3px; }
.begleiter__modus {
  border: 0; background: transparent; color: var(--text-muted); cursor: pointer;
  font-size: var(--fs-sm); font-weight: 500; padding: .3125rem .75rem; border-radius: var(--radius-full);
}
.begleiter__modus.is-active { background: var(--surface); color: var(--text); box-shadow: var(--shadow-xs); }

.begleiter__lauf {
  flex: 1; overflow-y: auto; padding: .9rem; display: flex; flex-direction: column; gap: .8rem;
  /* Am Ende des Verlaufs soll nicht die Seite dahinter weiterscrollen. */
  overscroll-behavior: contain; -webkit-overflow-scrolling: touch;
}
.begleiter__leer { padding: .6rem .2rem; }
.begleiter__vorschlaege { display: flex; flex-direction: column; gap: .35rem; margin-top: .8rem; align-items: flex-start; }
.begleiter__vorschlaege button {
  border: 1px solid var(--border); background: var(--surface-2); color: var(--text);
  border-radius: var(--radius-full); padding: .3125rem .75rem; font-size: var(--fs-sm); cursor: pointer; text-align: left;
}
.begleiter__vorschlaege button:hover { border-color: var(--accent-text); }

.begleiter__zug { display: flex; flex-direction: column; gap: .4rem; max-width: 100%; }
.begleiter__zug--mensch { align-items: flex-end; }
.begleiter__text {
  margin: 0; font-size: var(--fs-md); line-height: 1.55; white-space: pre-wrap;
  overflow-wrap: break-word; max-width: 92%;
}
.begleiter__zug--mensch .begleiter__text {
  background: var(--accent); color: var(--accent-on); padding: var(--space-2) var(--space-3); border-radius: 16px 16px 4px 16px;
}
.begleiter__zug--assistent .begleiter__text {
  background: var(--surface-2); padding: var(--space-2) var(--space-3); border-radius: 16px 16px 16px 4px;
}
/* Ausgezeichnete Antworten: dieselbe Blase, aber ohne pre-wrap – die
   Absätze bringen ihren Abstand selbst mit. */
.begleiter__text--reich { white-space: normal; }
.begleiter__text--reich > :first-child { margin-top: 0; }
.begleiter__text--reich > :last-child { margin-bottom: 0; }
.begleiter__text--reich p { margin: 0 0 .5rem; }
.begleiter__text--reich ul,
.begleiter__text--reich ol { margin: .35rem 0 .5rem; padding-left: 1.1rem; }
.begleiter__text--reich li { margin: .15rem 0; }
.begleiter__text--reich code {
  font-size: .82em; background: color-mix(in srgb, var(--text) 8%, transparent);
  padding: .05rem .3rem; border-radius: 4px;
}
.begleiter__text--reich h1, .begleiter__text--reich h2,
.begleiter__text--reich h3, .begleiter__text--reich h4 {
  font-size: .9rem; margin: .5rem 0 .25rem;
}
.begleiter__text--reich table { width: 100%; font-size: .8rem; border-collapse: collapse; margin: .35rem 0; }
.begleiter__text--reich th, .begleiter__text--reich td {
  text-align: left; padding: .2rem .35rem; border-bottom: 1px solid var(--border);
}

.begleiter__fehler { margin: 0; font-size: var(--fs-sm); color: var(--danger); }
.begleiter__quellen { margin: 0; font-size: var(--fs-xs); color: var(--text-subtle); }

/* Ein Vorschlag sieht nicht aus wie eine Antwort, sondern wie etwas, das
   noch aussteht: eigener Rahmen, eigener Grund, zwei Knöpfe. */
.begleiter__aktion {
  border: 1px solid var(--border); border-left: 3px solid var(--accent);
  border-radius: var(--radius-sm); padding: var(--space-2) var(--space-3); background: var(--surface);
}
.begleiter__aktion.is-uebernommen { border-left-color: var(--success); opacity: .8; }
.begleiter__aktion.is-verworfen { border-left-color: var(--border); opacity: .55; }
.begleiter__aktion-kopf { display: flex; justify-content: space-between; align-items: baseline; gap: var(--space-2); font-size: var(--fs-sm); }
.begleiter__aktion-status { font-size: var(--fs-xs); color: var(--text-subtle); }
.begleiter__aktion-text { margin: var(--space-1) 0 0; font-size: var(--fs-sm); color: var(--text-subtle); overflow-wrap: break-word; }

.begleiter__eingabe { border-top: 1px solid var(--border); padding: var(--space-2); display: flex; gap: var(--space-2); align-items: flex-end; }
.begleiter__eingabe textarea {
  flex: 1; resize: none; border: 1px solid var(--border); border-radius: var(--radius-sm);
  padding: var(--space-2) var(--space-3); font: inherit; font-size: var(--fs-md); background: var(--surface-2); color: var(--text);
}
.begleiter__eingabe textarea:focus { outline: 2px solid var(--focus); outline-offset: 1px; }
@media (max-width: 1023px) { .begleiter__eingabe textarea { font-size: 16px; } }
.begleiter__eingabe-knoepfe { display: flex; gap: .35rem; align-items: center; }

.begleiter__mikro {
  width: 2rem; height: 2rem; border-radius: var(--radius-full); border: 1px solid var(--border);
  background: var(--surface); color: var(--text-subtle); cursor: pointer;
  display: grid; place-items: center; position: relative;
}
.begleiter__mikro svg { width: 15px; height: 15px; }
.begleiter__mikro.is-aufnahme { background: var(--danger); color: #fff; border-color: transparent; }
.begleiter__mikro-zeit {
  position: absolute; bottom: 115%; left: 50%; transform: translateX(-50%);
  font-size: var(--fs-xs); background: var(--danger); color: #fff; padding: 0 .375rem;
  border-radius: var(--radius-full); font-variant-numeric: tabular-nums;
}
.begleiter__vorlesen {
  border: 0; background: transparent; color: var(--text-subtle); cursor: pointer;
  padding: .1rem; display: inline-grid; place-items: center;
}
.begleiter__vorlesen svg { width: 15px; height: 15px; }
.begleiter__vorlesen:hover { color: var(--accent-text); }

/* Auf dem Telefon sitzt unten die Navigationsleiste. Der Knopf saß bisher
   darauf – anklickbar war dann mal er, mal die Leiste darunter. */
@media (max-width: 1023px) {
  .begleiter { bottom: calc(var(--tabbar-h) + env(safe-area-inset-bottom) + .6rem); }
}
@media (max-width: 560px) {
  .begleiter { right: .75rem; }
  .begleiter__panel {
    width: calc(100vw - 1.5rem);
    height: min(28rem, calc(100vh - 13rem));
    height: min(28rem, calc(100dvh - 13rem));
  }
}
@media (prefers-reduced-motion: reduce) {
  .begleiter__knopf { transition: none; }
}

/* ============================================================
   GoBD: Verfahrensdokumentation
   ============================================================
   Der Text entsteht im Dienst als HTML und wird hier eingehängt.
   Deshalb hat er keine eigenen Klassen an jedem Element – gestaltet
   wird über den Rahmen. Wer den Erzeuger ändert, muss hier nichts
   nachziehen. */

.grid--end { align-items: end; }

.verfahren { border-top: 1px solid var(--border); padding-top: 1.5rem; }
.verfahren .vd__teil + .vd__teil { margin-top: 2.25rem; }
.verfahren h2 {
    font-size: 1.05rem;
    padding-bottom: .45rem;
    border-bottom: 2px solid var(--border);
    margin: 0 0 .9rem;
}
.verfahren h3 { font-size: .92rem; margin: 1.4rem 0 .5rem; color: var(--text-soft); }
.verfahren p  { margin: 0 0 .85rem; line-height: 1.6; }
.verfahren th[scope="row"] { width: 34%; font-weight: 600; }
.verfahren code { font-size: .88em; overflow-wrap: anywhere; }
/* Die Tabellen der Verfahrensdokumentation sind Fließtext mit Zeilenköpfen,
   keine Datensätze. Als Karte (`.table--responsive`) wurde jede Zelle ein
   Flexkasten, die Tabelle wuchs auf 638 px in einer 358 px breiten Karte,
   und die Karte schnitt den Rest ab. Jetzt stehen sie in `.table-wrap
   .vd__tabelle` (Gobd/Verfahren.php) – ohne die Mindestbreite der
   Datentabellen (46 rem), sonst liefe am Telefon jeder Absatz 736 px breit
   zum Wischen. Sie brechen um; passt eine doch nicht, scrollt die Fläche
   sichtbar mit Schatten. */
.vd__tabelle > .table { min-width: 0; }
/* Spaltenköpfe der Datentabellen bleiben einzeilig (`.table th`) – hier sind
   es Wörter wie „Aufbewahrungsfrist", und die Tabelle hielt sie 509 px breit. */
.vd__tabelle th { white-space: normal; hyphens: auto; -webkit-hyphens: auto; }
.vd__tabelle th[scope="row"] { vertical-align: top; }

/* Die Stellen, die der Betrieb selbst beantworten muss. Sie sollen beim
   Blättern auffallen – auch auf Papier, deshalb ein Rahmen und keine
   Hintergrundfarbe allein. */
.vd__offen {
    border: 1px solid var(--warning);
    border-left-width: 3px;
    border-radius: var(--radius-sm);
    background: var(--warning-soft);
    padding: 1rem 1.15rem;
    margin: 1rem 0;
}
.vd__offen-kopf {
    font-weight: 600;
    color: var(--warning);
    margin: 0 0 .6rem !important;
    font-size: var(--fs-md);
    text-transform: none;
    letter-spacing: 0;
}
.vd__offen dl { margin: 0; display: flex; flex-direction: column; gap: .55rem; }
.vd__offen dt { font-weight: 600; }
.vd__offen dd { margin: 0; color: var(--text-soft); }

/* ---------- Einwilligungsfrage der Google-Ads-Messung (Buchungsstrecke) ---------- */
.ads-consent {
    position: fixed;
    inset: auto 1rem 1rem 1rem;
    z-index: 70;
    display: flex;
    justify-content: flex-end;
    pointer-events: none;
}
/* `hidden` muss gewinnen. Jede Autorenregel schlägt die Browser-Vorgabe
   `[hidden] { display: none }` — das display:flex oben hielt den Kasten
   deshalb dauerhaft sichtbar: vor der Entscheidung des Skripts und auch
   nach dem Klick (der intern längst wirkte). Ohne diese Zeile gibt es
   keinen Weg, den Kasten je wieder loszuwerden. */
.ads-consent[hidden] { display: none; }
.ads-consent__card {
    pointer-events: auto;
    max-width: 26rem;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow-lg);
    padding: var(--space-4) var(--space-5);
}
.ads-consent__card strong { font-size: .95rem; }
.ads-consent__card p {
    margin: .4rem 0 .8rem;
    font-size: .85rem;
    line-height: 1.45;
    color: var(--text-soft);
}

/* 1.21.0 Kern – Vorlagenpflege: die Liste der Platzhalter und Bedingungen bricht auf dem
   Telefon um, statt die Seite zu verbreitern ({{verkaeufer.nationalitaet}} ist lang). */
.vkern-liste { width: 100%; table-layout: fixed; }
.vkern-liste td:first-child { width: 42%; }
.vkern-liste td, .vkern-liste code { white-space: normal; overflow-wrap: anywhere; }
/* 1.21.0 Verträge – der Assistent, die Vertragsseite, das Teilungsgeschäft.
   Ruhig und deckend (keine Glasfläche): Schritte als Reiterleiste, Klauseln
   durch eine Haarlinie getrennt, die zweite Sprache abgesetzt. */
.mv-schritte { margin-bottom: var(--space-4); }
.mv-schritte__nr {
    display: inline-grid; place-items: center; min-width: 1.5rem; height: 1.5rem;
    border: 1px solid var(--border-strong); border-radius: var(--radius-full);
    font-size: .8rem; font-variant-numeric: tabular-nums;
    /* Nachbesserung 1.21.0 (o22): im Flex-Reiter fällt das Leerzeichen weg – die Nummer klebte am Wort. */
    margin-inline-end: .375rem;
}
.tab.is-active .mv-schritte__nr { border-color: currentColor; }
.mv-liste { margin: var(--space-1) 0 0; padding-left: 1.2rem; }
.mv-teil { margin-top: var(--space-4); }
.mv-klausel { border-top: 1px solid var(--border); padding-top: var(--space-3); min-width: 0; }
.mv-klausel__kopf { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); margin-bottom: var(--space-2); }
.mv-klausel__nr { color: var(--text-muted); font-variant-numeric: tabular-nums; }
.mv-klausel__knopf { margin-left: auto; }
.mv-klausel__lesen { color: var(--text-soft); line-height: 1.55; overflow-wrap: anywhere; }
.mv-klausel__vorschau { white-space: pre-line; overflow-wrap: anywhere; line-height: 1.55; color: var(--text-soft); }
.mv-klausel__sp2 { margin-top: var(--space-2); padding-left: var(--space-3); border-left: 2px solid var(--border); color: var(--text-muted); font-style: italic; }
.mv-klausel__text { min-height: 5rem; line-height: 1.5; }
.mv-beispiel { padding: var(--space-3) var(--space-4); border: 1px dashed var(--border-strong); border-radius: var(--radius); }
.mv-beispiel__zeilen { display: flex; flex-wrap: wrap; gap: var(--space-2) var(--space-5); font-variant-numeric: tabular-nums; }
.mv-leiste {
    position: sticky; bottom: 0; z-index: 5;
    display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--space-2);
    padding: var(--space-3) 0; background: var(--bg); border-top: 1px solid var(--border);
}
.mv-leiste .btn { min-height: 44px; }
/* Am Telefon liegt die Tab-Leiste unten – die Knopfleiste klebt darüber, nicht darunter. */
@media (max-width: 1023px) { .mv-leiste { bottom: calc(var(--tabbar-h) + env(safe-area-inset-bottom)); } }
@media (max-width: 640px) { .mv-leiste__stand { display: none; } }
.mv-objektwahl { display: grid; gap: var(--space-1); max-height: 22rem; overflow-y: auto; }
.mv-teilung-form { padding-top: var(--space-3); border-top: 1px solid var(--border); }
/* Nachbesserung 1.21.0 (Bereich A2): Speicherleiste, Kartenköpfe am Telefon, Vorlagenpflege eingeklappt. */
/* Kartenkopf mit langem Knopf (Kundenakte): der Titel behält 12rem, der Knopf bricht um (o1). */
.mv-kopf > h2 { flex: 1 1 12rem; }
/* Wortlaut und Vorlagenpflege: „Speichern“ klebt am unteren Rand (o7, o8). Die Karte clippt ohne
   Scrollbox (overflow: clip) – mit overflow: hidden klebte nichts. */
.mv-wortlaut-karte { overflow: clip; }
@supports not (overflow: clip) { .mv-wortlaut-karte { overflow: visible; } }
.mv-speicherleiste {
    display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--space-2) var(--space-3);
}
.mv-speicherleiste .btn { min-height: 44px; }
/* Runde 3 (O5): auf der Vertragsseite klebt die Leiste nur, wenn es etwas zu speichern gibt
   (Änderung oder „Zahlen prüfen“, Klasse is-klebend) – sonst steht sie am Ende des Wortlauts und
   verdeckt beim Lesen nichts. Die Vorlagenpflege (vkern-leiste) klebt immer: dort ist sie der
   einzige Weg zum Speichern und nur eine Zeile hoch. */
.mv-speicherleiste.is-klebend, .vkern-leiste { position: sticky; bottom: 0; z-index: 5; }
@media (max-width: 1023px) { .mv-speicherleiste.is-klebend, .vkern-leiste { bottom: calc(var(--tabbar-h) + env(safe-area-inset-bottom)); } }
/* Am Telefon im klebenden Zustand nur Stand und Knopf in einer Zeile – der lange Satz steht oben im Hinweis. */
@media (max-width: 640px) {
    .mv-speicherleiste.is-klebend { flex-wrap: nowrap; }
    .mv-speicherleiste.is-klebend .mv-speicherleiste__satz { display: none; }
}
.vkern-leiste { padding: var(--space-3) 0; background: var(--bg); border-top: 1px solid var(--border); }
.vkern-klausel > summary { list-style: none; cursor: pointer; }
.vkern-klausel > summary::-webkit-details-marker { display: none; }
.vkern-klausel:not([open]) > summary { border-bottom: 0; }
.vkern-klausel__pfeil { flex: none; transition: transform var(--dur) var(--ease); }
.vkern-klausel[open] .vkern-klausel__pfeil { transform: rotate(90deg); }
/* Der Anteil der Partneragentur ist ein Ergebnis, kein Eingabefeld (o20). */
.mv-ausgabe { display: block; padding: .4rem 0; font-weight: 600; font-variant-numeric: tabular-nums; }
.mv-hinweis-warnung { display: flex; gap: var(--space-1); align-items: flex-start; color: var(--warning); }
.mv-hinweis-warnung svg { width: 14px; height: 14px; flex: none; margin-top: 2px; }
/* Nachbesserung 1.21.0 Runde 3 (Bereich U): Fokusring der Klauseln, Kartentitel in jeder Breite. */
/* O0: Eine Klausel der Vorlagenpflege ist eine <details class="card">; .card schneidet mit
   overflow: hidden alles außerhalb ab – der Hausring (2 px Abstand nach außen) war unsichtbar.
   Innen liegend bleibt er ganz, eingeklappt wie aufgeklappt. Den Radius trägt der Kopf selbst
   (der Ring folgt ihm) – nie im :focus-visible (Regel 1.17: der Fokus ändert keinen Radius). */
.vkern-klausel > summary { border-radius: calc(var(--radius-lg) - 1px); }
.vkern-klausel[open] > summary { border-bottom-left-radius: 0; border-bottom-right-radius: 0; }
.vkern-klausel > summary:focus-visible { outline-offset: -4px; }
/* O4: Ein Kartentitel schrumpft nie unter sein längstes Wort. `.card__header h2 { flex: 1;
   min-width: 0 }` (Grundlage 0 %) ließ den Titel neben Untertitel und Knöpfen auf wenige Pixel
   fallen – je nach Breite (414, 430, 480, 560 px …), nicht nur bei 390. Mit min-content brechen
   die Nachbarn in die nächste Zeile, sobald der Titel sonst zu schmal würde; wo Platz ist, bleibt
   alles, wie es war. Gilt für jeden Kartenkopf. */
.card__header > h2, .card__header > h3 { min-width: min-content; }
/* 1.21.0 Interessentenregistrierung – Objektwahl, Formular, Registrierung, öffentliche
   Bestätigung /r/{token}. Farben nur aus Tokens, keine Glasfläche, Grundregel vor Modifikator. */
.reg-zeile { align-items: flex-start; }
.reg-zeile--gesperrt { background-color: var(--surface-2); }
.reg-zeile--gesperrt .font-medium { color: var(--text-muted); }
.reg-sperre { color: var(--text-soft); display: flex; gap: var(--space-1); align-items: baseline; flex-wrap: wrap; }
.reg-sperre svg { width: 14px; height: 14px; flex: none; }
.reg-karte__abschnitt { padding-bottom: 0; }
.reg-einwilligung { border-color: var(--border-strong); }
.reg-hinweis { display: flex; gap: var(--space-2); align-items: flex-start; }
.reg-hinweis svg { width: 16px; height: 16px; flex: none; margin-top: 2px; }
.reg-brief { display: flex; flex-direction: column; gap: var(--space-3); padding: var(--space-4); border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--surface-inset); }
.reg-brief__zeile { display: flex; flex-wrap: wrap; gap: var(--space-2); align-items: baseline; overflow-wrap: anywhere; }
.reg-brief__zeile .label { margin: 0; }
.reg-brief__anrede { font-weight: 500; }
.reg-brief__text { min-height: 14rem; line-height: 1.55; }
.reg-mail summary { cursor: pointer; color: var(--text-soft); }
.reg-daten { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 14rem), 1fr)); gap: var(--space-3) var(--space-5); margin: 0; }
.reg-daten > div { min-width: 0; }
.reg-daten dt { font-size: .8rem; color: var(--text-muted); margin-bottom: 2px; }
.reg-daten dd { margin: 0; overflow-wrap: anywhere; }
.reg-daten--pub { grid-template-columns: repeat(auto-fill, minmax(min(100%, 12rem), 1fr)); }
.reg-wortlaut { overflow-wrap: anywhere; }
.reg-pruefsumme { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; overflow-wrap: anywhere; }
.reg-pub__kopf { gap: var(--space-5); align-items: flex-start; flex-wrap: wrap; }
.reg-pub__logo { height: 30px; margin-bottom: .9rem; }
.reg-pub__nummer { text-align: right; }
.reg-pub__titel { font-size: clamp(1.3rem, 1.1rem + .8vw, 1.8rem); margin: var(--space-5) 0 0; }
.reg-pub__wortlaut { margin: 0; padding: var(--space-4) var(--space-5); border-left: 3px solid var(--border-strong); background: var(--surface-inset); border-radius: 0 var(--radius-sm) var(--radius-sm) 0; line-height: 1.6; overflow-wrap: anywhere; }
.reg-pub__form { padding-top: var(--space-2); }
.reg-pub__knoepfe .btn { min-height: 44px; }
.reg-pub__kontakt a { overflow-wrap: anywhere; }
@media (max-width: 560px) {
  .reg-pub__nummer { text-align: left; }
  .reg-pub__knoepfe .btn { flex: 1 1 100%; justify-content: center; }
}

/* =========================================================================
   Glas 1.18: die Rückfälle
   -------------------------------------------------------------------------
   Zwei Fälle, in denen jede Glasfläche deckend wird – in der Kartenfarbe
   (die Betreibertinte bleibt Tinte):
   1. Der Browser kennt keine Unschärfe (Safari bis 17 nur mit -webkit-,
      ältere Firefox gar nicht): ohne sie wäre Glas nur eine halb
      durchsichtige Fläche, auf der Text mit dem Inhalt darunter ringt.
   2. Der Mensch hat „Transparenz reduzieren" eingeschaltet (macOS, iOS,
      Windows): dann ist Glas keine Frage des Geschmacks, sondern eine
      Bitte – und die wird erfüllt, einschließlich des Dialog-Hintergrunds.
   Der Block steht am Ende, weil er jede Glasregel darüber schlagen muss;
   die Betreiberleiste nimmt er aus (sie ist nie Glas). Der Prüfstand zählt
   nach, dass jede Glasfläche in beiden Blöcken steht.
   ========================================================================= */
@supports not ((backdrop-filter: blur(2px)) or (-webkit-backdrop-filter: blur(2px))) {
  .sidebar:not(.sidebar--operator), .topbar, .setup__bar, .booking__bar, .tabbar,
  .dropdown__menu, .modal__header, .modal__footer, .toast,
  .begleiter__panel, .doc-actions, .card--glass { background: var(--surface); }
  .peek { background: #10150c; }
  html[data-theme="dark"] .peek { background: #222b19; }
}
@media (prefers-reduced-transparency: reduce) {
  .sidebar:not(.sidebar--operator), .topbar, .setup__bar, .booking__bar, .tabbar,
  .dropdown__menu, .modal__header, .modal__footer, .toast,
  .begleiter__panel, .doc-actions, .card--glass { background: var(--surface); -webkit-backdrop-filter: none; backdrop-filter: none; }
  .peek { background: #10150c; -webkit-backdrop-filter: none; backdrop-filter: none; }
  html[data-theme="dark"] .peek { background: #222b19; }
  .backdrop { background: color-mix(in srgb, #10150c 55%, transparent); -webkit-backdrop-filter: none; backdrop-filter: none; }
  .topbar__search .input { background: var(--surface-2); }
}

/* Seit 1.36.0: zugängliche Mehrfachauswahl in der Projektaufgabenliste. */
.task-bulk { display:flex; align-items:center; flex-wrap:wrap; gap:12px 20px; margin-bottom:16px; padding:16px; border:1px solid var(--border); border-radius:var(--radius); background:var(--surface); }
.task-bulk__summary { display:flex; flex:1 1 220px; flex-direction:column; gap:4px; min-width:0; }
.task-bulk__all { display:flex; align-items:center; gap:8px; min-height:44px; cursor:pointer; }
.task-bulk__all[hidden] { display:none; }
.task-bulk__all input, .task-bulk__choice input { width:20px; height:20px; flex-shrink:0; accent-color:var(--accent); }
.task-bulk__choice { display:flex; align-items:center; justify-content:center; flex:0 0 44px; min-height:44px; cursor:pointer; }
.task-bulk__title { display:flex; align-items:center; gap:6px; min-width:0; }
.task-bulk__title > div { min-width:0; overflow-wrap:anywhere; }
.task-bulk input:focus-visible { outline:2px solid var(--accent); outline-offset:4px; }
@media (max-width:600px) {
  .task-bulk { padding:12px; gap:10px; }
  .task-bulk__all, .task-bulk > button { width:100%; }
}

/* Rückmeldungen sollen auch mit großen Schriften lesbar und schließbar bleiben. */
.toasts { max-height: 45vh; max-height: 45dvh; overflow-y: auto; overscroll-behavior: contain; }
.toasts:empty { display: none; }
.toast { align-items: center; }
.toast__body { min-width: 0; overflow-wrap: anywhere; }
.toast .toast__close { display: inline-grid; place-items: center; align-self: flex-start; flex: none; width: 2.75rem; height: 2.75rem; border: 0; color: var(--text); background: transparent; cursor: pointer; border-radius: var(--radius); margin: -.3rem -.45rem -.3rem 0; }
.toast .toast__close svg { width: 1rem; height: 1rem; color: inherit; margin: 0; }
.toast .toast__close:is(:hover,:focus-visible) { background: var(--surface-2); }
.toast__close:focus-visible { outline: 2px solid var(--accent-text); outline-offset: -3px; }
@media(prefers-reduced-motion:reduce) { .toasts .toast { animation: none; transition: none; } }
[data-field-summary] a { color:inherit; text-decoration:underline; text-underline-offset:.16em; }
[data-field-summary]:focus-visible { outline:2px solid var(--danger); outline-offset:2px; }
