/*
 * onehome.css — OneHome-Look, Etappe 16f (05.10.2026)
 *
 * Nutzer-Entscheidung: Variante A („Rot vollflächig“) aus der abgenommenen Vorschau
 * `onehome-demo-vorschau.html`, Stand „Vorschlag OneHome“. Der graue SaaS-Look aus 16e
 * wurde vom Betreiber verworfen („sieht null nach OneHome aus“). Alle Werte unten stammen
 * aus der Vorschau (dort wiederum aus dem OneHome-Portal: Vodafone-Rot #e60000, Verlauf
 * #e60000 → #c1000f → #a3000d, Seitenleisten-Knopf #ba1217, weiße Karten mit rot
 * verlaufender Haarlinie, Inter). Neue Werte wurden nicht erfunden – mit drei bewussten
 * Ausnahmen, alle wegen der AA-Kontraste, die aus 16e bleiben müssen (Messung im
 * Etappenprotokoll docs/etappen/16f-onehome-look.md):
 *   1. Text auf Rot ist reines Weiß. Das gedämpfte Weiß der Vorschau (78 %) erreicht auf
 *      #e60000 nur 3,2:1.
 *   2. Kleiner Text nimmt nie `--oh-text-blass` (#8e8e93, 3,3:1), sondern `--oh-text-leise`
 *      (#6e6e73, 5,1:1). Das Blasse bleibt Feldrändern und Trennern vorbehalten – dort
 *      erfüllt es 3:1 nach WCAG 1.4.11, wie der Feldrand aus 16e.
 *   3. Pillen „ok“/„warn“ schreiben in einer dunkleren Stufe derselben Farbe (4,7:1 statt
 *      3,9 bzw. 3,4:1). Die Demo-Pille auf Rot ist dunkel getönt statt hell (6,3:1 statt
 *      4,2:1).
 *
 * Farben NUR als Tokens in :root. Die Mandantenfarbe (Etappe 21a, 07.10.2026) tauscht die
 * fünf Akzent-Tokens (`--oh-accent`, `--oh-accent-dunkel`, `--oh-accent-tief`,
 * `--oh-seitenknopf`, `--oh-accent-hell`) über ein eigenes kleines Stylesheet
 * (`/erscheinungsbild/akzent-rrggbb.css`, Akzentfarbe::stylesheet()); alles Abgeleitete
 * (weiche Flächen, Verlauf, Aurora, Kantenverlauf, Fokus) rechnet per color-mix() aus ihnen
 * und steht in der Regel `:root, [data-akzent-vorschau]`, damit der Vorschaukasten der
 * Erscheinungsbild-Seite es mit seinen eigenen Akzent-Tokens neu berechnet (abgeleitete
 * Custom Properties werden dort ausgewertet, wo sie deklariert sind). Fehler- und
 * Warnfarben bleiben fest rot – auch bei blauem Akzent. Darunter steht keine einzige Farbe
 * mehr. „Rot“ in `.auf-rot`/`--auf-rot-*` heißt seit 21a „auf dem Akzent“. Die Tokens
 * `--page-bg`, `--aurora` und `--edge` heißen wie in der Vorschau, damit beide
 * vergleichbar bleiben.
 *
 * Nur hell. Das Portal ist hell, die Vorschau ebenso; der Dunkelmodus aus 16e passte zum
 * grauen Look und ist mit ihm entfallen (offener Punkt im Protokoll).
 *
 * CSP (src/Kern/Sicherheit/SicherheitsHeader.php: default-src 'self'): keine data:-URLs.
 * Korn, Auswahlpfeil und Symbole liegen deshalb als Dateien unter /img/, Inter unverändert
 * selbst gehostet unter /fonts/inter/ (SIL OFL, Etappe 14).
 *
 * Aus 16e übernommen und nur neu eingefärbt: Fokusrahmen (:focus-visible), erklärte leere
 * Zustände (.leer), Meldungen mit Rolle (role=alert/status), Tabellen, die auf Handybreite
 * in sich scrollen statt die Seite zu verbreitern (kein waagrechtes Scrollen bei 375 px).
 */

@font-face {
  font-family: 'Inter';
  src: url('/fonts/inter/InterVariable.woff2') format('woff2-variations'),
       url('/fonts/inter/InterVariable.woff2') format('woff2');
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Inter';
  src: url('/fonts/inter/InterVariable-Italic.woff2') format('woff2-variations'),
       url('/fonts/inter/InterVariable-Italic.woff2') format('woff2');
  font-weight: 100 900;
  font-style: italic;
  font-display: swap;
}

/* ---------- Tokens (Farbwerte nur hier) ---------- */
:root {
  /* Akzent – der einzige Teil, den eine Mandantenfarbe tauscht. */
  --oh-accent: #e60000;
  --oh-accent-dunkel: #c1000f;
  --oh-accent-tief: #a3000d;
  --oh-seitenknopf: #ba1217;
  --oh-accent-hell: #ff1a1a;

  /* Neutrale Werte aus der Vorschau. */
  --oh-text: #1d1d1f;
  --oh-text-2: #3a3a42;
  --oh-text-leise: #6e6e73;
  --oh-text-blass: #8e8e93;
  --oh-symbol: #6b6b75;
  --oh-weiss: #fff;
  /* Etappe 21d (09.10.2026), Nutzer-Entscheidung Variante A: Kachel unter dem Firmenlogo bewusst
     fest weiss – ein fremdes Logo kann jede Farbe haben (auch die Akzentfarbe), auf Weiss bleibt
     es lesbar. Kein Akzent-, kein Dunkelmodus-Wert. */
  --logo-kachel: #fff;
  --oh-schwarz: #000;
  --oh-flaeche: #fff;
  --oh-flaeche-2: #ececef;
  --oh-hover: #f5f5f7;
  --oh-zeile-hover: #fafafb;
  --oh-linie: rgba(0, 0, 0, .1);
  --oh-linie-stark: rgba(0, 0, 0, .18);
  --oh-seitenlinie: #e7e7ec;

  /* Zustände. `-text` = AA-Stufe für kleine Schrift auf der weichen Fläche. */
  --oh-ok: #248a3d;
  --oh-ok-text: #1e7b36;
  --oh-ok-weich: rgba(36, 138, 61, .1);
  --oh-warn: #b97200;
  --oh-warn-text: #946000;
  --oh-warn-weich: rgba(185, 114, 0, .1);
  --oh-gut: #7b8499;
  --oh-gut-text: #5d667a;
  --oh-gut-weich: rgba(123, 132, 153, .13);
  /* Etappe 21a (07.10.2026), Nutzer-Entscheidung: Fehler bleiben IMMER rot, unabhängig von
     der Mandantenfarbe – die Werte sind die bisherigen des roten Akzents, jetzt fest. */
  --oh-fehler: #e60000;
  --oh-fehler-text: #c1000f;
  --oh-fehler-weich: rgba(230, 0, 0, .08);
  --oh-knopf-glanz: inset 0 1px 0 rgba(255, 255, 255, .35);

  /* Auf Rot (seit 21a: auf dem Akzent – Name bleibt, weiß auf jeder zulässigen Akzentfarbe). */
  /* Dienstplan wie im Portal (16f-Nachschliff, Werte aus dp_styles()). */
  --dp-frueh: #3d4f91;
  --dp-spaet: #6b3b5e;
  --dp-ganztag: #52616f;
  /* Etappe 20a (07.10.2026): vierte Lage „Sonder“ (Schichtform.lage) und Schatten des Kontextmenüs. */
  --dp-sonder: #8a5a2b;
  --dp-menue-schatten: 0 10px 30px rgba(0, 0, 0, .18);
  --dp-urlaub-flaeche: #eaf6ee;
  --dp-urlaub-rand: #8fc9a1;
  /* 21a: Krank ist ein Warnzustand und bleibt rot (aus --oh-fehler, nicht aus dem Akzent). */
  --dp-krank-rand: color-mix(in srgb, var(--oh-fehler) 32%, transparent);
  --dp-frei-flaeche: #fbf3d5;
  --dp-frei-rand: #d9be6b;
  --auf-rot: #fff;
  --auf-rot-linie: rgba(255, 255, 255, .18);
  --auf-rot-flaeche: rgba(255, 255, 255, .14);
  --auf-rot-flaeche-hover: rgba(255, 255, 255, .22);
  --auf-rot-rand: rgba(255, 255, 255, .4);
  --auf-rot-pille: rgba(0, 0, 0, .16);
  /* Wasserzeichen-Haus der Anmeldung (16f-Nachschliff): 6 % Weiss, Weiss-auf-Rot bleibt >= 4,69:1. */
  --auf-rot-wasserzeichen: rgba(255, 255, 255, .06);
  --schleier: rgba(0, 0, 0, .32);
  --schatten: 0 1px 2px rgba(29, 0, 4, .06), 0 12px 28px -24px rgba(40, 0, 4, .35);
  --schatten-anmeldung: 0 1px 2px rgba(29, 0, 4, .08), 0 24px 48px -30px rgba(40, 0, 4, .55);
  --schatten-leiste: 0 0 40px rgba(0, 0, 0, .25);
  --schatten-menue: 0 1px 2px rgba(29, 0, 4, .08), 0 16px 32px -18px rgba(40, 0, 4, .4);

  /* Etappe 18a (05.10.2026): Seitenkopf, Demo-Leiste, Führungsband (Vorschau „Demo-Ausbau“). */
  --auf-rot-leise: rgba(255, 255, 255, .66);
  --auf-rot-pille-text: rgba(255, 255, 255, .88);
  --auf-rot-pille-rand: rgba(255, 255, 255, .22);
  --auf-rot-pille-rand-hover: rgba(255, 255, 255, .45);
  --auf-rot-zahl: rgba(255, 255, 255, .85);
  --auf-rot-reiter: rgba(255, 255, 255, .16);
  --auf-rot-reiter-rand: rgba(255, 255, 255, .2);
  --kopf-wasserzeichen: rgba(255, 255, 255, .07);
  --demo-leiste: #1d1d1f;
  --demo-leiste-feld: #2c2c30;
  --demo-leiste-rand: #48484e;
  --demo-leiste-leise: rgba(255, 255, 255, .75);
  --demo-leiste-linie: rgba(255, 255, 255, .35);
  --fuehrung-flaeche: #fff8e8;
  --fuehrung-rand: rgba(185, 114, 0, .3);
  --fuehrung-text: #4a3a14;
  --fuehrung-stark: #2b2208;

  /* Etappe 18e (06.10.2026): Einstiegsseite, Tableiste, Platzhalter (Vorschau „Demo Paket 3“).
     Nur Ableitungen bestehender Werte – keine neue Farbe. */
  --auf-rot-karte: rgba(255, 255, 255, .1);
  --auf-rot-text: rgba(255, 255, 255, .82);
  --auf-rot-fein: rgba(255, 255, 255, .6);
  --tableiste-hoehe: 62px;

  /* Maße. */
  --r-karte: 12px;
  --r-ui: 9px;
  --r-feld: 8px;
  --r-pille: 999px;
  --r-buehne: 18px;
  --leiste-breite: 248px;
  --kopf-hoehe: 64px;
  --inhalt-breite: 1080px;
  --rand: clamp(16px, 3vw, 32px);
  --karte-innen: 20px;
  --font: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}

/* Abgeleitet aus dem Akzent. Etappe 21a (07.10.2026): eigene Regel, damit der Vorschaukasten
   der Erscheinungsbild-Seite ([data-akzent-vorschau], Akzent-Tokens aus vorschau-rrggbb.css
   oder per JS) alles neu ableitet – ein in :root deklariertes color-mix() wäre dort schon
   fertig gerechnet. Die Aurora (bisher drei feste Rottöne) folgt jetzt dem Akzent:
   tief 67 % / 58 % mit Schwarz und hell mit 16 % Weiß treffen bei #e60000 die alten Werte
   (110,0,12 / 94,0,12 / 255,59,48) auf wenige Stufen genau. */
:root, [data-akzent-vorschau] {
  --oh-accent-weich: color-mix(in srgb, var(--oh-accent) 8%, transparent);
  --oh-accent-hauch: color-mix(in srgb, var(--oh-accent) 3.5%, transparent);
  --oh-accent-ring: color-mix(in srgb, var(--oh-accent) 12%, transparent);
  --page-bg: linear-gradient(135deg, var(--oh-accent) 0%, var(--oh-accent-dunkel) 52%, var(--oh-accent-tief) 100%);
  --aurora:
    radial-gradient(60% 70% at 8% 0%, color-mix(in srgb, color-mix(in srgb, var(--oh-accent-tief) 67%, var(--oh-schwarz)) 55%, transparent), transparent 70%),
    radial-gradient(55% 65% at 100% 30%, color-mix(in srgb, color-mix(in srgb, var(--oh-accent-tief) 58%, var(--oh-schwarz)) 50%, transparent), transparent 72%),
    radial-gradient(45% 50% at 70% 100%, color-mix(in srgb, color-mix(in srgb, var(--oh-accent-hell) 84%, var(--oh-weiss)) 22%, transparent), transparent 70%);
  --edge: linear-gradient(150deg,
    color-mix(in srgb, var(--oh-accent) 50%, transparent),
    color-mix(in srgb, var(--oh-accent) 6%, transparent) 38%,
    color-mix(in srgb, var(--oh-accent-tief) 40%, transparent) 100%);
  --oh-knopf: linear-gradient(180deg, var(--oh-accent-hell), var(--oh-accent-dunkel));
  --oh-knopf-hover: linear-gradient(180deg, color-mix(in srgb, var(--oh-accent-hell) 92%, var(--oh-schwarz)), color-mix(in srgb, var(--oh-accent-dunkel) 90%, var(--oh-schwarz)));
  --dp-heute-kopf: color-mix(in srgb, var(--oh-accent) 10%, var(--oh-flaeche-2));
  --schatten-stempel: 0 6px 16px -4px color-mix(in srgb, var(--oh-accent-dunkel) 55%, transparent);
  /* Optik-Scheibe 1 (17.10.2026): Zebra-Fläche der Tabellen. Sehr leise aus dem Akzent
     getönt (wie OneHomes warm getönter Zeilenhover), damit sie sich vom neutralen Hover
     `--oh-zeile-hover` noch unterscheidet. Reine Ableitung, kein neuer Farbwert; steht hier,
     weil sie dem Akzent folgt und der Vorschaukasten sie neu rechnen muss. */
  --oh-zeile-zebra: color-mix(in srgb, var(--oh-accent) 4%, var(--oh-flaeche));
}

/* ================= Grundlage ================= */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
html, body { margin: 0; padding: 0; }
body {
  font-family: var(--font);
  /* Optik-Scheibe 1 (17.10.2026): Grundschrift von 14/1.45 auf 15/1.5 gehoben – dieselbe
     ruhigere Lesbarkeit wie OneHome. Bewusst nur hier: fast alle Bausteine setzen ihre Größen
     in px und bleiben dadurch unberührt, es skaliert allein der ungesetzte Fließtext (p, li,
     dl, Felder ohne eigene Größe) und die em-Abstände (Listen). Kein Baustein hängt an der
     Body-Größe als Rastermaß, das Layout bleibt also stehen; nur der Textumfluss wird minimal
     länger. */
  font-size: 15px;
  line-height: 1.5;
  color: var(--oh-text);
  background: var(--oh-flaeche);
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}
h1 { font-size: clamp(21px, 3.4vw, 24px); font-weight: 650; letter-spacing: -.2px; line-height: 1.2; margin: 0 0 12px; }
h2 { font-size: clamp(15.5px, 2.2vw, 17px); font-weight: 650; letter-spacing: -.2px; margin: 24px 0 10px; }
h3 { font-size: 14px; font-weight: 650; margin: 18px 0 6px; }
p { margin: 0 0 12px; }
small, .klein { font-size: 12.5px; color: var(--oh-text-leise); }
strong, b { font-weight: 650; }
.untertitel { color: var(--oh-text-leise); margin: 0 0 16px; }
a { color: var(--oh-accent-dunkel); text-decoration: none; text-underline-offset: 2px; font-weight: 550; }
a:hover { text-decoration: underline; }
ul, ol { padding-left: 1.25em; margin: 0 0 12px; }
li { margin-bottom: 4px; }
dl { margin: 0 0 16px; }
dt { font-weight: 650; font-size: 13px; margin-top: 10px; }
dt:first-child { margin-top: 0; }
dd { margin: 2px 0 0; color: var(--oh-text-leise); }
code { font-family: var(--font-mono); font-size: .86em; background: var(--oh-flaeche-2); padding: 1px 5px; border-radius: 5px; }
pre { font-family: var(--font-mono); font-size: 12.5px; background: var(--oh-hover); border: 1px solid var(--oh-linie); border-radius: var(--r-feld); padding: 10px 12px; overflow-x: auto; max-width: 100%; }
pre code { background: transparent; padding: 0; }
[hidden] { display: none !important; }
svg.sym { width: 18px; height: 18px; flex: 0 0 18px; display: block; }

.unsichtbar {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0, 0, 0, 0);
  white-space: nowrap; border: 0;
}
.sprung { position: absolute; left: 12px; top: -60px; z-index: 50; background: var(--oh-flaeche); color: var(--oh-text); padding: 8px 12px; border-radius: var(--r-ui); box-shadow: var(--schatten-menue); }
.sprung:focus { top: 12px; }

/* ---------- Fokus (Tastatur), aus 16e ----------
   Nur bei Tastaturfokus. Auf Weiß der Akzent (4,8:1), auf Rot Weiß (4,8:1 und mehr). */
a:focus-visible, button:focus-visible, summary:focus-visible,
input:focus-visible, select:focus-visible, textarea:focus-visible {
  outline: 2px solid var(--oh-accent);
  outline-offset: 2px;
  border-radius: var(--r-feld);
}
.buehne a:focus-visible, .buehne summary:focus-visible, .buehne button:focus-visible,
.ohne-shell a:focus-visible, .ohne-shell button:focus-visible { outline-color: var(--auf-rot); }
.karte a:focus-visible, .karte button:focus-visible, .karte summary:focus-visible,
.karte input:focus-visible, .karte select:focus-visible, .karte textarea:focus-visible,
.seite:not(.seite-frei) > * a:focus-visible, .seite:not(.seite-frei) > * button:focus-visible,
.seite:not(.seite-frei) > * summary:focus-visible, .seite:not(.seite-frei) input:focus-visible,
.seite:not(.seite-frei) select:focus-visible, .seite:not(.seite-frei) textarea:focus-visible,
.stat-karte a:focus-visible, .anmeldung-karte a:focus-visible, .anmeldung-karte button:focus-visible,
.kopf-konto .nav-gruppe-inhalt a:focus-visible, .kopf-konto .nav-gruppe-inhalt button:focus-visible { outline-color: var(--oh-accent); }

/* ================= Shell: weißes L (Seitenleiste + Kopfleiste), rote Bühne ================= */
body.mit-shell {
  display: grid;
  grid-template-columns: var(--leiste-breite) minmax(0, 1fr);
  grid-template-rows: var(--kopf-hoehe) minmax(0, 1fr);
  min-height: 100vh;
}
.seitenleiste {
  grid-row: 1 / 3;
  grid-column: 1;
  position: sticky;
  top: 0;
  height: 100vh;
  overflow-y: auto;
  background: var(--oh-flaeche);
  display: flex;
  flex-direction: column;
  padding: 12px 12px 12px;
  z-index: 30;
}
.leiste-marke {
  position: relative;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px 8px;
  background: var(--oh-seitenknopf);
  color: var(--auf-rot);
  border-radius: 10px;
  padding: 10px 12px;
  margin-bottom: 8px;
  min-height: 44px;
  min-width: 0;
  /* Die Seitenleiste ist eine Flex-Spalte mit 100vh; ist die Navigation hoeher, schrumpfte
     der zweizeilige Kasten mit und schnitt den Mandantennamen ab (Sichtpruefung 09.10.2026). */
  flex: none;
}
.leiste-marke:hover { text-decoration: none; filter: brightness(1.05); }
.leiste-marke[aria-current="page"] { box-shadow: inset 0 0 0 2px var(--auf-rot-rand); }
.marke-haus { width: 22px; height: 22px; display: block; flex: none; }
.marke-wort { height: 17px; width: auto; display: block; flex: none; }
/* Etappe 21c (08.10.2026), Nutzer-Entscheidung „Kopfzeile Fassung A“: OnePOS-Logo vorn,
   Mandantenname dazu. Die Seitenleiste ist nur 248 px breit; in einer Zeile blieb dem Namen
   neben Logo und Demo-Pille praktisch kein Platz („Dem…“), und die als Eckschild gesetzte
   Pille ragte über den Knopfrand (Sichtpruefung 09.10.2026). Darum zweizeilig: oben Zeichen,
   Wortmarke und ggf. Pille, darunter der Mandantenname über die volle Breite, lange Namen
   per Ellipse. Der Trenner entfaellt hier, die Zeilen trennen schon. Die Demo-Pille ist nur
   bei einer Demo-Instanz da (demo_aktiv()), umrandet statt gefuellt, damit sie neben der
   weissen Wortmarke nicht mit ihr verschmilzt. */
.leiste-marke .marke-trenner { display: none; }
.marke-trenner { width: 1px; align-self: stretch; min-height: 14px; background: var(--auf-rot-rand); flex: none; }
.marke-mandant {
  order: 3;
  flex: 1 0 100%;
  font-size: 12px;
  font-weight: 550;
  line-height: 1.3;
  opacity: .9;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
}
/* Etappe 21d (09.10.2026), Nutzer-Entscheidung Variante A: Firmenlogo statt der Namenszeile auf
   weisser Kachel, volle Breite unter Zeichen und Wortmarke (gleiche Zeile 3 wie .marke-mandant),
   ~38 px hoch, Logo hoechstens 26 px hoch und ~150 px breit, Seitenverhaeltnis bleibt. */
.marke-logo {
  order: 3;
  flex: 1 0 100%;
  display: flex;
  align-items: center;
  min-height: 38px;
  min-width: 0;
  padding: 6px 10px;
  margin-top: 4px;
  border-radius: 8px;
  background: var(--logo-kachel);
}
.marke-logo img { display: block; width: auto; height: auto; max-height: 26px; max-width: min(150px, 100%); object-fit: contain; }
.marke-demo-pille {
  order: 2;
  flex: none;
  margin-left: auto;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .3px;
  text-transform: uppercase;
  padding: 1px 6px;
  border: 1px solid var(--auf-rot-rand);
  border-radius: 999px;
  line-height: 1.3;
}

.leiste-nav { display: flex; flex-direction: column; }
.nav-titel {
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: .05em;
  text-transform: uppercase;
  color: var(--oh-text-leise);
  padding: 12px 12px 4px;
  margin: 0;
}
details.nav-gruppe > summary {
  list-style: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: space-between;
  border-radius: var(--r-feld);
}
details.nav-gruppe > summary::-webkit-details-marker { display: none; }
details.nav-gruppe > summary::after {
  content: "";
  width: 6px; height: 6px;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: rotate(-45deg);
  margin-right: 4px;
  transition: transform .15s ease;
}
details.nav-gruppe[open] > summary::after { transform: rotate(45deg); margin-top: -3px; }
details.nav-gruppe > summary:hover { color: var(--oh-text); }
.nav-gruppe-inhalt { display: flex; flex-direction: column; }
.leiste-nav a {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 8px 12px;
  border-radius: 10px;
  color: var(--oh-text-2);
  font-size: 14px;
  font-weight: 500;
  position: relative;
  text-decoration: none;
}
.leiste-nav a svg.sym { color: var(--oh-symbol); }
.leiste-nav a:hover { background: var(--oh-hover); color: var(--oh-text); text-decoration: none; }
.leiste-nav a[aria-current="page"] { background: var(--oh-accent-weich); color: var(--oh-accent-dunkel); font-weight: 650; }
.leiste-nav a[aria-current="page"] svg.sym { color: var(--oh-accent); }
.leiste-nav a[aria-current="page"]::before { content: ""; position: absolute; left: 0; top: 8px; bottom: 8px; width: 3px; border-radius: 3px; background: var(--oh-accent); }
.leiste-fuss {
  margin-top: auto;
  border-top: 1px solid var(--oh-seitenlinie);
  padding: 12px 6px 0;
  font-size: 12.5px;
}
.leiste-fuss .wer { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; min-width: 0; }
.leiste-fuss .wer b { display: block; font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.leiste-fuss .wer span { color: var(--oh-text-leise); }
.leiste-fuss nav { display: flex; flex-wrap: wrap; gap: 4px 14px; align-items: center; }
.leiste-fuss nav a { color: var(--oh-text-leise); font-weight: 600; }
.leiste-fuss nav a[aria-current="page"] { color: var(--oh-accent-dunkel); }
.leiste-fuss form { margin: 0; }
.avatar {
  width: 32px; height: 32px;
  border-radius: 50%;
  background: var(--oh-flaeche-2);
  color: var(--oh-text-2);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  font-weight: 700;
  flex: none;
}

.kopfleiste {
  grid-row: 1;
  grid-column: 2;
  position: sticky;
  top: 0;
  z-index: 20;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 0 20px;
  background: var(--oh-flaeche);
  border-bottom: 1px solid var(--oh-seitenlinie);
  min-width: 0;
}
.kopf-titel { font-weight: 650; font-size: 15px; letter-spacing: -.2px; margin: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.kopf-luecke { flex: 1; }
.kopf-burger, .kopf-haus { display: none; }
.kopf-burger {
  border: 0;
  background: none;
  padding: 6px;
  margin: 0;
  min-height: 0;
  box-shadow: none;
  color: var(--oh-text);
  border-radius: var(--r-feld);
  cursor: pointer;
}
.kopf-burger:hover { background: var(--oh-hover); }
.kopf-burger svg.sym { width: 22px; height: 22px; flex-basis: 22px; }
/* Etappe 21c (08.10.2026): mobil Zeichen + Mandantenname statt nur dem Haussymbol - gleiche
   Breite wie zuvor reicht nicht mehr, darum auto statt 30px und ein wenig Innenabstand. */
.kopf-haus {
  background: var(--oh-seitenknopf);
  color: var(--auf-rot);
  border-radius: 8px;
  height: 30px;
  padding: 0 8px 0 6px;
  align-items: center;
  justify-content: center;
  gap: 6px;
  flex: none;
  max-width: 40vw;
  min-width: 0;
}
.kopf-haus img { width: 18px; height: 18px; display: block; flex: none; }
.kopf-haus-mandant { font-size: 12px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.kopf-glocke {
  position: relative;
  width: 36px; height: 36px;
  border-radius: 10px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--oh-text-2);
  flex: none;
}
.kopf-glocke:hover { background: var(--oh-hover); text-decoration: none; }
.kopf-glocke[aria-current="page"] { background: var(--oh-accent-weich); color: var(--oh-accent-dunkel); }
.kopf-glocke svg.sym { width: 19px; height: 19px; flex-basis: 19px; }
.glocke-zahl {
  position: absolute;
  top: 3px; right: 2px;
  min-width: 17px; height: 17px;
  border-radius: var(--r-pille);
  background: var(--oh-accent);
  color: var(--auf-rot);
  font-size: 10px;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 4px;
  border: 2px solid var(--oh-flaeche);
  font-variant-numeric: tabular-nums;
}
details.kopf-konto { position: relative; flex: none; }
details.kopf-konto > summary { list-style: none; cursor: pointer; border-radius: 50%; display: block; }
details.kopf-konto > summary::-webkit-details-marker { display: none; }
details.kopf-konto > summary:hover .avatar, details.kopf-konto[open] > summary .avatar { background: var(--oh-accent-weich); color: var(--oh-accent-dunkel); }
.kopf-konto .nav-gruppe-inhalt {
  position: absolute;
  right: 0;
  top: calc(100% + 8px);
  min-width: 220px;
  background: var(--oh-flaeche);
  border: 1px solid var(--oh-seitenlinie);
  border-radius: var(--r-karte);
  box-shadow: var(--schatten-menue);
  padding: 6px;
  z-index: 40;
}
.kopf-konto .konto-name { padding: 8px 10px 6px; font-weight: 650; font-size: 13px; margin: 0; border-bottom: 1px solid var(--oh-seitenlinie); margin-bottom: 4px; }
.kopf-konto .nav-gruppe-inhalt a, .kopf-konto .nav-gruppe-inhalt button {
  display: block;
  width: 100%;
  text-align: left;
  padding: 8px 10px;
  border-radius: var(--r-feld);
  color: var(--oh-text-2);
  font-weight: 500;
  font-size: 13.5px;
  background: transparent;
  border: 0;
  box-shadow: none;
  min-height: 0;
}
.kopf-konto .nav-gruppe-inhalt a:hover, .kopf-konto .nav-gruppe-inhalt button:hover { background: var(--oh-hover); text-decoration: none; }
.kopf-konto .nav-gruppe-inhalt a[aria-current="page"] { color: var(--oh-accent-dunkel); background: var(--oh-accent-weich); }
.kopf-konto form { margin: 4px 0 0; padding-top: 4px; border-top: 1px solid var(--oh-seitenlinie); }

.buehne {
  grid-row: 2;
  grid-column: 2;
  position: relative;
  min-width: 0;
  min-height: calc(100vh - var(--kopf-hoehe));
  border-top-left-radius: var(--r-buehne);
  /* Optik-Scheibe 2 (17.10.2026): Nur noch der Grundverlauf. Die drei Farbwolken der Aurora
     (`--aurora`) liegen jetzt in eigenen, geblurten und langsam wandernden Ebenen
     (siehe „Aurora-Bewegung“ unten) – sonst läge die statische Aurora doppelt unter der
     bewegten. `--aurora` selbst bleibt unverändert und wird weiter für `body.ohne-shell`
     und die Vorschau der Erscheinungsbild-Seite gebraucht. */
  background: var(--page-bg);
  background-attachment: fixed;
  color: var(--auf-rot);
  padding: 0 var(--rand) 48px;
  isolation: isolate;
}
/* Filmkorn wie in der Vorschau, als Datei wegen CSP. */
.buehne::after, body.ohne-shell::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: .06;
  mix-blend-mode: overlay;
  background-image: url("/img/korn.svg");
  z-index: -1;
  border-top-left-radius: inherit;
}
.buehne-inhalt { max-width: var(--inhalt-breite); position: relative; }
.schleier { display: none; }

/* ---------- Aurora-Bewegung (Optik-Scheibe 2, 17.10.2026) ----------
   Gap-Analyse: OneHome hat vier geblurte, langsam wandernde Farbwolken (header.php), OnePOS
   nur den einen statischen Verlauf `--aurora`. Die Bühne ist deshalb in drei absolut gesetzte,
   geblurte Ebenen getrennt – eine je Wolke der bisherigen Aurora. Die Gradienten sind
   wörtlich dieselben color-mix()-Ableitungen aus dem Akzent (kein neuer Farbwert, kein
   Hexwert), nur auf eigene Elemente verteilt:
     ::before der Bühne        = tiefe Wolke oben links
     ::before der Inhaltsspalte = tiefe Wolke rechts
     ::after  der Inhaltsspalte = helle Wolke unten
   Jede Ebene hat ihre eigene, sehr lange Bewegung (46 s / 58 s / 64 s, `ease-in-out`), damit
   die Fläche lebt, ohne zu flimmern oder abzulenken; bewegt wird nur `transform` (billig für
   den Browser), geblurrt wird einmal. `z-index:-1` legt sie hinter den Inhalt, aber über den
   Grundverlauf der Bühne; `position:fixed` entspricht dem bisherigen `background-attachment:
   fixed`. Nur die Arbeitsfläche (`body.mit-shell`): die Ebenen hängen an `.buehne`, das es
   ohne Anmeldung nicht gibt – die Anmeldeseite behält ihren statischen Verlauf (offener
   Punkt, siehe Etappenprotokoll). Bei `prefers-reduced-motion: reduce` steht alles still
   (Grundstellung = der bisherige statische Zustand). */
.buehne::before,
.buehne > .buehne-inhalt::before,
.buehne > .buehne-inhalt::after {
  content: "";
  position: fixed;
  inset: -20%;
  z-index: -1;
  pointer-events: none;
  filter: blur(48px);
  opacity: .85;
}
.buehne::before {
  background: radial-gradient(58% 62% at 12% 6%,
    color-mix(in srgb, color-mix(in srgb, var(--oh-accent-tief) 67%, var(--oh-schwarz)) 55%, transparent),
    transparent 70%);
  animation: oh-aurora-a 46s ease-in-out infinite;
}
.buehne > .buehne-inhalt::before {
  background: radial-gradient(55% 60% at 88% 34%,
    color-mix(in srgb, color-mix(in srgb, var(--oh-accent-tief) 58%, var(--oh-schwarz)) 50%, transparent),
    transparent 72%);
  animation: oh-aurora-b 58s ease-in-out infinite;
}
.buehne > .buehne-inhalt::after {
  background: radial-gradient(48% 52% at 66% 92%,
    color-mix(in srgb, color-mix(in srgb, var(--oh-accent-hell) 84%, var(--oh-weiss)) 22%, transparent),
    transparent 70%);
  animation: oh-aurora-c 64s ease-in-out infinite;
}
@keyframes oh-aurora-a {
  0%, 100% { transform: translate3d(0, 0, 0) scale(1); }
  50% { transform: translate3d(4%, 3%, 0) scale(1.12); }
}
@keyframes oh-aurora-b {
  0%, 100% { transform: translate3d(0, 0, 0) scale(1.06); }
  50% { transform: translate3d(-5%, 4%, 0) scale(1); }
}
@keyframes oh-aurora-c {
  0%, 100% { transform: translate3d(0, 0, 0) scale(1); }
  50% { transform: translate3d(3%, -4%, 0) scale(1.14); }
}
@media (prefers-reduced-motion: reduce) {
  .buehne::before,
  .buehne > .buehne-inhalt::before,
  .buehne > .buehne-inhalt::after { animation: none; }
}

/* ---------- Bannerzone ----------
   Oberhalb des Seiteninhalts, auf Rot. Heute: Demo-Hinweis und Vier-Augen-Warnung. Später
   (Etappe 17a) zusätzlich die Notfall-Ankündigung – ebenfalls role=alert, sieht damit
   ohne weiteres CSS richtig aus. */
.bannerzone { padding-top: 16px; display: flex; flex-direction: column; align-items: flex-start; gap: 8px; }
.bannerzone:not(:has(*)) { display: none; }
.bannerzone > [role="alert"], .bannerzone > [role="status"] { margin: 0; align-self: stretch; }
.demo-hinweis {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin: 0;
  border-radius: var(--r-pille);
  font-size: 12px;
  font-weight: 650;
  padding: 4px 11px;
  background: var(--auf-rot-pille);
  color: var(--auf-rot);
}
.demo-hinweis::before { content: ""; width: 7px; height: 7px; border-radius: 50%; background: currentColor; display: block; }
.meldungen { padding-top: 16px; }
.meldungen > [role] { margin: 0 0 8px; }

/* ================= Seiten ================= */
/* Kopfzone (Eyebrow + weißer Titel auf Rot). Gilt für Sonderseiten mit `.kopfzone` und
   automatisch für die erste <h1> jeder normalen Seite. */
.kopfzone { padding: 26px 0 18px; }
.kopfzone h1, .seite:not(.seite-frei) > h1:first-child { color: var(--auf-rot); margin: 0; }
.eyebrow { display: block; font-size: 11px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--auf-rot); margin: 0 0 4px; }
.kopfzone .untertitel, .seite:not(.seite-frei) > h1:first-child + .untertitel { color: var(--auf-rot); margin: 3px 0 0; font-size: 13.5px; }
.hero { display: flex; align-items: flex-end; gap: 12px; flex-wrap: wrap; }
.hero > .luecke { flex: 1; }
.hero .auf-rot { display: flex; gap: 8px; flex-wrap: wrap; }

/* Normale Seite = eine weiße Karte unter dem roten Titel.
   Warum so (statt ~60 Vorlagen anzufassen): `base.html.twig` legt jeden Seiteninhalt in
   `.seite`. Die erste <h1> (jede Vorlage beginnt so) steht in Rasterzeile 1 auf Rot; die
   Karte selbst ist ein absolut gesetztes ::before, das ab Zeile 2 bis zum Ende des Rasters
   reicht – ein absolut positioniertes Rasterkind nimmt seinen Rasterbereich als Bezug.
   Alle übrigen Kinder bekommen den Karten-Innenabstand. Seiten mit eigenem Aufbau (Heute,
   Dienstplan, Zeiterfassung, Anmeldung) setzen `seite-frei` und bauen ihre Karten selbst. */
.seite { position: relative; }
.seite:not(.seite-frei) {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  align-content: start;
  isolation: isolate;
  padding-bottom: var(--karte-innen);
  color: var(--oh-text);
}
.seite:not(.seite-frei)::before {
  content: "";
  position: absolute;
  grid-column: 1 / -1;
  grid-row: 2 / auto;
  inset: 0;
  z-index: -1;
  border-radius: var(--r-karte);
  border: 1px solid transparent;
  background: linear-gradient(var(--oh-flaeche), var(--oh-flaeche)) padding-box, var(--edge) border-box;
  box-shadow: var(--schatten);
}
.seite:not(.seite-frei):has(> h1:first-child + .untertitel)::before { grid-row: 3 / auto; }
.seite:not(.seite-frei):not(:has(> h1:first-child))::before { grid-row: 1 / auto; }
.seite:not(.seite-frei):not(:has(> h1:first-child)) { padding-top: var(--karte-innen); margin-top: 20px; }
.seite:not(.seite-frei) > * { margin-left: var(--karte-innen); margin-right: var(--karte-innen); min-width: 0; }
.seite:not(.seite-frei) > table, .seite:not(.seite-frei) > .tabelle-scroll { width: calc(100% - 2 * var(--karte-innen)); max-width: calc(100% - 2 * var(--karte-innen)); }
.seite:not(.seite-frei) > h1:first-child { margin: 0; padding: 26px 0 18px; }
.seite:not(.seite-frei) > h1:first-child + .untertitel { margin: -14px 0 18px; }
.seite:not(.seite-frei) > h1:first-child + *,
.seite:not(.seite-frei) > h1:first-child + .untertitel + * { margin-top: var(--karte-innen); }
.seite:not(.seite-frei) > :last-child { margin-bottom: 0; }
.seite:not(.seite-frei) > h2 { padding-top: 16px; border-top: 1px solid var(--oh-linie); }
.seite:not(.seite-frei) > h1:first-child + h2,
.seite:not(.seite-frei) > h1:first-child + .untertitel + h2 { padding-top: 0; border-top: 0; }
.seite-frei { color: var(--auf-rot); }

/* ---------- Karten ---------- */
.karte {
  position: relative;
  border-radius: var(--r-karte);
  border: 1px solid transparent;
  background: linear-gradient(var(--oh-flaeche), var(--oh-flaeche)) padding-box, var(--edge) border-box;
  box-shadow: var(--schatten);
  padding: 18px var(--karte-innen);
  margin: 0 0 12px;
  min-width: 0;
  color: var(--oh-text);
}
.karte > :last-child { margin-bottom: 0; }
.karte h2:first-child, .karte-kopf h2 { margin-top: 0; }
.karte-kopf { display: flex; align-items: center; justify-content: space-between; gap: 10px 12px; flex-wrap: wrap; margin-bottom: 12px; }
.karte-kopf > div { min-width: 0; }
.karte-kopf h2 { margin: 0; }
.karte-unter { font-size: 12.5px; color: var(--oh-text-leise); margin: 2px 0 0; }
.raster-2 { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; margin-bottom: 12px; }
.raster-2 > .karte { margin-bottom: 0; }

/* Kennzahlenreihe */
.stat-reihe { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 12px; margin-bottom: 12px; }
.stat-karte {
  position: relative;
  border-radius: var(--r-karte);
  border: 1px solid transparent;
  background: linear-gradient(var(--oh-flaeche), var(--oh-flaeche)) padding-box, var(--edge) border-box;
  box-shadow: var(--schatten);
  padding: 15px 18px;
  min-width: 0;
  color: var(--oh-text);
  margin: 0;
}
.stat-karte h2, .stat-label { font-size: 11.5px; font-weight: 650; color: var(--oh-text-leise); display: block; margin: 0; letter-spacing: 0; }
.stat-wert { font-size: clamp(23px, 3.4vw, 27px); font-weight: 650; letter-spacing: -.4px; line-height: 1.1; display: block; margin: 4px 0 0; font-variant-numeric: tabular-nums; }
.stat-wert small { font-size: 13px; font-weight: 600; color: var(--oh-text-leise); letter-spacing: 0; margin-left: 3px; }
.stat-wert.text { font-size: 16px; letter-spacing: -.2px; line-height: 1.3; }
.stat-notiz { font-size: 12px; color: var(--oh-text-leise); margin: 6px 0 0; display: block; }
.stat-karte.primaer::before { content: ""; position: absolute; left: 18px; top: 0; width: 26px; height: 4px; border-radius: 0 0 3px 3px; background: var(--oh-accent); }
.stat-karte.primaer .stat-wert { color: var(--oh-accent-dunkel); }
.stat-karte a.flaechenlink::after { content: ""; position: absolute; inset: 0; border-radius: var(--r-karte); }
.stat-karte:has(a.flaechenlink):hover { box-shadow: var(--schatten), 0 0 0 1px var(--oh-accent-ring); }

/* Optik-Scheibe 1 (17.10.2026): Karten heben beim Überfahren den Schatten leicht an
   (`--schatten-menue`, dieselbe Schattenfamilie wie `--schatten`, kein neuer Farbwert).
   Nur eine Hebung der vorhandenen Karte – keine Bewegung, keine Farbe; die Karten mit
   flächigem Link behalten ihren Akzentring (spezifischere Regel oben). */
.karte, .stat-karte { transition: box-shadow .16s ease; }
.karte:hover, .stat-karte:hover { box-shadow: var(--schatten-menue); }

/* ---------- Knöpfe ----------
   Ein Primärknopf je Formular (Leitregel aus 16e); Nebenhandlungen `.sekundaer`. */
button, input[type="submit"], .knopf {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  font-family: var(--font);
  font-size: 13.5px;
  font-weight: 600;
  line-height: 1.2;
  border-radius: var(--r-ui);
  padding: 9px 14px;
  min-height: 38px;
  border: 1px solid transparent;
  cursor: pointer;
  color: var(--auf-rot);
  background: var(--oh-knopf);
  box-shadow: var(--oh-knopf-glanz);
  text-decoration: none;
}
button:hover, input[type="submit"]:hover, .knopf:hover { background: var(--oh-knopf-hover); text-decoration: none; }
button:disabled, input[type="submit"]:disabled { opacity: .5; cursor: not-allowed; }
button.sekundaer, .knopf.sekundaer {
  background: transparent;
  color: var(--oh-text);
  border-color: var(--oh-linie-stark);
  box-shadow: none;
}
button.sekundaer:hover, .knopf.sekundaer:hover { background: var(--oh-flaeche-2); }
button.breit { width: 100%; }
button.gross { padding: 13px 22px; font-size: 15px; }
.knopf.klein, button.klein { padding: 6px 11px; font-size: 12.5px; min-height: 30px; }

/* Optik-Scheibe 7 (19.10.2026): `.knopfreihe` war in der App-Kaskade nicht definiert (nur im
   Nachtsee-Stylesheet der oeffentlichen Einstiegsseite). Mehrere Vorlagen nutzen sie fuer eine
   Reihe von Knoepfen; ohne Definition stapelten sie ohne Abstand. */
.knopfreihe { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; }
/* Auf Rot: Primär weiß mit roter Schrift, sekundär als helle Glasfläche (Vorschau `.auf-rot`). */
.auf-rot .knopf, .auf-rot button { background: var(--oh-flaeche); color: var(--oh-accent-dunkel); box-shadow: none; }
.auf-rot .knopf.sekundaer, .auf-rot button.sekundaer { background: var(--auf-rot-flaeche); color: var(--auf-rot); border-color: var(--auf-rot-rand); }
.auf-rot .knopf.sekundaer:hover, .auf-rot button.sekundaer:hover { background: var(--auf-rot-flaeche-hover); }
.knoepfe { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
.knoepfe form { margin: 0; }
td button, td input[type="submit"] { padding: 5px 11px; min-height: 30px; font-size: 12.5px; }
td form { margin: 0; }

/* Segmentschalter (Woche vor/zurück) */
.segment { display: inline-flex; border: 1px solid var(--oh-linie); border-radius: 10px; overflow: hidden; background: var(--oh-flaeche); }
.segment a, .segment span, .segment button { padding: 6px 11px; font-size: 12.5px; font-weight: 600; color: var(--oh-text-leise); text-decoration: none; display: inline-flex; align-items: center; transition: background .14s ease, color .14s ease; }
.segment > * + * { border-left: 1px solid var(--oh-linie); }
.segment a:hover, .segment button:hover { background: var(--oh-hover); color: var(--oh-text); text-decoration: none; }
.segment [aria-current] { background: var(--oh-accent); color: var(--auf-rot); }
/* Optik-Scheibe 1 (17.10.2026): Segment wie OneHome – Fläche auch auf <button>, der aktive
   Abschnitt dunkelt beim Überfahren leicht nach (`--oh-accent-dunkel`), Fokus liegt innen. */
.segment [aria-current]:hover, .segment .on:hover { background: var(--oh-accent-dunkel); color: var(--auf-rot); }
.segment a:focus-visible, .segment button:focus-visible { outline: 2px solid var(--oh-accent); outline-offset: -2px; }

/* ---------- Formulare ---------- */
form { margin: 0 0 16px; }
label {
  display: flex;
  flex-direction: column;
  gap: 5px;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--oh-text-2);
  margin-bottom: 12px;
  max-width: 360px;
}
select, textarea,
input:not([type]), input[type="text"], input[type="email"], input[type="password"],
input[type="date"], input[type="time"], input[type="number"], input[type="search"],
input[type="tel"], input[type="url"], input[type="datetime-local"], input[type="month"] {
  font-family: var(--font);
  font-size: 14.5px;
  font-weight: 400;
  line-height: 1.35;
  border: 1px solid var(--oh-text-blass);
  border-radius: var(--r-feld);
  padding: 9px 12px;
  min-height: 40px;
  background-color: var(--oh-flaeche);
  color: var(--oh-text);
  max-width: 100%;
  outline: none;
}
select { -webkit-appearance: none; appearance: none; padding-right: 30px; background-image: url("/img/auswahl.svg"); background-repeat: no-repeat; background-position: right 11px center; }
textarea { min-height: 96px; width: 100%; resize: vertical; }
select:focus, textarea:focus, input:focus { border-color: var(--oh-accent); box-shadow: 0 0 0 3px var(--oh-accent-ring); }
input::placeholder, textarea::placeholder { color: var(--oh-text-leise); }
input[type="checkbox"], input[type="radio"] { width: 16px; height: 16px; margin: 0; accent-color: var(--oh-accent); flex: none; }
label:has(> input[type="checkbox"]), label:has(> input[type="radio"]) { flex-direction: row; align-items: center; gap: 8px; font-weight: 500; }
/* Optik-Scheibe 2 (17.10.2026): Der Dateiwähler sieht wie ein Nebenknopf aus (OneHomes
   gestylter `input[type=file]`). Die Regel erweitert nur die vorhandene – Klassenname
   `.datei-waehler` ist derselbe Stil für Vorlagen, die ihn ausdrücklich setzen wollen. */
input[type="file"], .datei-waehler { font-family: var(--font); font-size: 13px; max-width: 100%; color: var(--oh-text-leise); }
input[type="file"]::file-selector-button, .datei-waehler::file-selector-button {
  font-family: var(--font);
  font-size: 13px;
  font-weight: 600;
  line-height: 1.2;
  margin: 0 10px 0 0;
  padding: 7px 12px;
  border: 1px solid var(--oh-linie-stark);
  border-radius: var(--r-feld);
  background: var(--oh-flaeche-2);
  color: var(--oh-text);
  cursor: pointer;
}
input[type="file"]::file-selector-button:hover, .datei-waehler::file-selector-button:hover { background: var(--oh-hover); }
fieldset { border: 1px solid var(--oh-linie); border-radius: var(--r-karte); padding: 12px 16px 4px; margin: 0 0 16px; min-width: 0; }
legend { font-weight: 650; font-size: 12.5px; padding: 0 4px; color: var(--oh-text-2); }
td select, td input:not([type="checkbox"]):not([type="radio"]):not([type="hidden"]) { min-height: 32px; padding: 5px 8px; font-size: 13px; }
td select { padding-right: 26px; }

/* Aufklappbereiche in Seiten (leise Zusatzinfo, wie 16e) */
.seite details > summary, .karte details > summary { cursor: pointer; color: var(--oh-text-leise); font-size: 13px; font-weight: 600; margin: 8px 0; }
.seite details > summary:hover, .karte details > summary:hover { color: var(--oh-text); }
/* Aufklapper als Knopf (Korrektur beantragen): <summary> sieht aus wie ein Nebenknopf. */
details.aufklapp-knopf > summary {
  list-style: none;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  border: 1px solid var(--oh-linie-stark);
  border-radius: var(--r-ui);
  padding: 6px 11px;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--oh-text);
  margin: 0;
}
details.aufklapp-knopf > summary::-webkit-details-marker { display: none; }
details.aufklapp-knopf > summary:hover { background: var(--oh-flaeche-2); color: var(--oh-text); }
details.aufklapp-knopf[open] > summary { background: var(--oh-flaeche-2); }
details.aufklapp-knopf > :not(summary) { margin-top: 14px; }

/* ---------- Tabellen ----------
   Flach in der Karte wie in der Vorschau (`.tbl`). Unter 761 px wie seit Etappe 14:
   `display:block` macht nur die Tabelle zum Scroll-Container, die Seite verbreitert sich
   nicht. */
table {
  width: 100%;
  border-collapse: collapse;
  font-size: 13px;
  font-variant-numeric: tabular-nums;
  margin: 0 0 16px;
  max-width: 100%;
  color: var(--oh-text);
}
th {
  text-align: left;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--oh-text-leise);
  padding: 7px 10px;
  border-bottom: 1px solid var(--oh-linie);
  white-space: nowrap;
  vertical-align: bottom;
}
/* Optik-Scheibe 1 (17.10.2026): Der Tabellenkopf bleibt beim Scrollen stehen (wie OneHomes
   `.csv-table th`). Eigene Fläche `--oh-flaeche` statt durchsichtig, sonst scheinen die
   gescrollten Zeilen durch; `z-index: 2` hält ihn über den Zellen. Nur `thead`, damit
   Zeilenköpfe im Rumpf (`tbody th`) nicht mitkleben. In `.tabelle-scroll` (waagerecht
   scrollend) wirkt der Klebeeffekt nur eingeschränkt – siehe offener Punkt. */
thead th { position: sticky; top: 0; z-index: 2; background: var(--oh-flaeche); }
td { padding: 8px 10px; border-bottom: 1px solid var(--oh-linie); vertical-align: middle; }
tbody th { text-transform: none; letter-spacing: 0; font-size: 13px; color: var(--oh-text); font-weight: 600; white-space: normal; vertical-align: middle; }
tbody tr:last-child td, tbody tr:last-child th { border-bottom: 0; }
tbody tr:hover td, tbody tr:hover th { background: var(--oh-zeile-hover); }
/* Optik-Scheibe 1 (17.10.2026): Zebra über `--oh-zeile-zebra` (leise, aus dem Akzent
   abgeleitet). `:where()` hält die Spezifität der Zellen niedrig, damit die Zustandsregeln
   darunter (`.heute`, `.op-*`, `.dp-*`) weiter gewinnen und der Hover stärker bleibt. */
tbody tr:nth-child(even) :where(td, th) { background: var(--oh-zeile-zebra); }
tfoot td, tfoot th { font-weight: 650; border-top: 1px solid var(--oh-linie-stark); border-bottom: 0; color: var(--oh-text); text-transform: none; letter-spacing: 0; font-size: 13px; padding-top: 9px; }
th:first-child, td:first-child { padding-left: 0; }
th:last-child, td:last-child { padding-right: 0; }
td.r, th.r, .zahl { text-align: right; }
th.heute, td.heute, tr.heute > td { background: var(--oh-accent-hauch); }
th.heute { color: var(--oh-accent-dunkel); }
@media (max-width: 760px) {
  table { display: block; overflow-x: auto; -webkit-overflow-scrolling: touch; position: relative; }
  td { white-space: nowrap; }
}

/* ---------- Pillen und Zustände ---------- */
.pille {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  border-radius: var(--r-pille);
  font-size: 12px;
  font-weight: 650;
  font-style: normal;
  padding: 3px 10px;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
  background: var(--oh-flaeche-2);
  color: var(--oh-text-2);
}
.pille.punkt::before { content: ""; width: 7px; height: 7px; border-radius: 50%; background: currentColor; display: block; }
.pille.ok { background: var(--oh-ok-weich); color: var(--oh-ok-text); }
.pille.warn { background: var(--oh-warn-weich); color: var(--oh-warn-text); }
.pille.gut { background: var(--oh-gut-weich); color: var(--oh-gut-text); }
.pille.bad, .pille.fehler { background: var(--oh-fehler-weich); color: var(--oh-fehler-text); }
/* Status als Text in Zustandsfarbe (16e-Haken `data-status`/`data-zustand`), jetzt aufrecht. */
[data-zustand="ok"]:not(.pille), [data-status="ANWESEND"]:not(.pille), [data-status="AKTIV"]:not(.pille) { color: var(--oh-ok-text); }
[data-zustand="beachten"]:not(.pille), [data-zustand="warn"]:not(.pille) { color: var(--oh-warn-text); }
[data-zustand="kritisch"]:not(.pille), [data-zustand="fehler"]:not(.pille) { color: var(--oh-fehler-text); }
td > svg { vertical-align: middle; margin-left: 8px; border-radius: 2px; background: var(--oh-flaeche-2); color: var(--oh-accent); }

/* ---------- Meldungen ----------
   Auf Weiß wie auf Rot lesbar: deckende helle Fläche mit farbigem Rand. */
[role="alert"], [role="status"] {
  font-style: normal;
  padding: 10px 14px;
  margin: 12px 0;
  border-radius: var(--r-feld);
  border: 1px solid var(--oh-linie);
  border-left-width: 3px;
  background: var(--oh-flaeche);
  font-size: 13.5px;
}
[role="alert"] { color: var(--oh-fehler-text); border-left-color: var(--oh-fehler); background: linear-gradient(var(--oh-fehler-weich), var(--oh-fehler-weich)), var(--oh-flaeche); }
[role="status"] { color: var(--oh-ok-text); border-left-color: var(--oh-ok); background: linear-gradient(var(--oh-ok-weich), var(--oh-ok-weich)), var(--oh-flaeche); }
[role="alert"] a, [role="status"] a { color: inherit; text-decoration: underline; }
/* Optik-Scheibe 1 (17.10.2026): dieselbe Meldungsform auch als Klasse `.alert` (OneHomes
   `.alert`), damit Vorlagen ohne `role` dieselbe Optik bekommen: solide Fläche plus farbige
   linke Kante, Farben nur aus den Zustandstokens. `-erfolg`/`-success` und
   `-fehler`/`-error` sind Doppelnamen (deutsch wie englisch), `-warn`/`-warnung` nutzt den
   Warnton, `-info`/`-hinweis` bleibt neutral. Fehler/Warn bleiben rot bzw. orange. */
.alert {
  font-style: normal;
  padding: 10px 14px;
  margin: 12px 0;
  border-radius: var(--r-feld);
  border: 1px solid var(--oh-linie);
  border-left-width: 3px;
  border-left-color: var(--oh-text-leise);
  background: var(--oh-flaeche);
  color: var(--oh-text);
  font-size: 13.5px;
}
.alert-erfolg, .alert-success { color: var(--oh-ok-text); border-left-color: var(--oh-ok); background: linear-gradient(var(--oh-ok-weich), var(--oh-ok-weich)), var(--oh-flaeche); }
.alert-fehler, .alert-error { color: var(--oh-fehler-text); border-left-color: var(--oh-fehler); background: linear-gradient(var(--oh-fehler-weich), var(--oh-fehler-weich)), var(--oh-flaeche); }
.alert-warn, .alert-warnung { color: var(--oh-warn-text); border-left-color: var(--oh-warn); background: linear-gradient(var(--oh-warn-weich), var(--oh-warn-weich)), var(--oh-flaeche); }
.alert-info, .alert-hinweis { color: var(--oh-text-2); border-left-color: var(--oh-text-leise); }
.alert a { color: inherit; text-decoration: underline; }
/* Hinweise im Fließtext ohne Rolle (`[data-zustand]` auf <p>) bleiben Text. */

/* ---------- Leere Zustände (aus 16e, erklärt statt nackt) ---------- */
.leer {
  padding: 16px 18px;
  margin: 0 0 16px;
  color: var(--oh-text-leise);
  background: var(--oh-hover);
  border: 1px dashed var(--oh-text-blass);
  border-radius: var(--r-karte);
}
.leer strong { display: block; color: var(--oh-text); margin-bottom: 2px; }
.leer p { margin: 0 0 4px; }
.leer p:last-child { margin-bottom: 0; }
/* Optik-Scheibe 1 (17.10.2026): Leerzustand mit dokumentierter Aktionszeile. Vorlagen setzen
   unter den Text eine Handlung – entweder direkt `.leer > .knopf`/`<a>` oder gebündelt in
   `.leer-aktion` (mehrere Knöpfe nebeneinander). Abstand nur, wenn die Zeile da ist. */
.leer .knopf, .leer button, .leer > a { margin-top: 10px; }
.leer .leer-aktion { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin-top: 10px; }
.leer .leer-aktion .knopf, .leer .leer-aktion button, .leer .leer-aktion a { margin-top: 0; }
td.leer, span.leer { background: none; border: 0; padding: 8px 10px; color: var(--oh-text-leise); border-radius: 0; margin: 0; }
td.leer:first-child { padding-left: 0; }

/* ---------- Listen (Woche, Gestempelt) ---------- */
.liste { list-style: none; margin: 0; padding: 0; }
.liste li { display: flex; align-items: center; gap: 12px; padding: 10px 0; border-bottom: 1px solid var(--oh-linie); min-width: 0; margin: 0; }
.liste li:first-child { padding-top: 2px; }
.liste li:last-child { border-bottom: 0; padding-bottom: 0; }
.liste .tag { font-weight: 650; width: 58px; flex: none; font-size: 13px; }
.liste .tag small { display: block; font-weight: 500; color: var(--oh-text-leise); font-size: 11.5px; }
.liste .was { flex: 1; min-width: 0; }
.liste .was b { font-weight: 600; display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-variant-numeric: tabular-nums; }
.liste .was span { color: var(--oh-text-leise); font-size: 12.5px; }
.liste .wann { color: var(--oh-text-leise); font-size: 12px; white-space: nowrap; font-variant-numeric: tabular-nums; }
.liste li.heute .tag { color: var(--oh-accent-dunkel); }
.liste li.frei .was b { color: var(--oh-text-leise); font-weight: 500; }

/* ================= Heute ================= */
.heute-kacheln { display: contents; }

/* ================= Dienstplan wie im Portal (16f-Nachschliff) ================= */
/* Etappe 16f-Nachschliff (05.10.2026), Nutzer-Entscheidung: Optik wie die Teamansicht des
   Portals (dp_styles() in portal/dienstplan_lib/bootstrap.php):
   - feines Raster mit 1-px-Linien, Kopf auf Flaeche-2;
   - Schichtkarten mit farbiger Kopfleiste und Namen als Chips;
   - eigene Person rot umrandet, Abwesenheiten als farbige Pillen.
   Farben nur ueber die --dp-*-Tokens im :root. */
.tabelle-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; max-width: 100%; position: relative; }
.tabelle-scroll > table { display: table; overflow: visible; margin-bottom: 0; }
.dp-grid { border-collapse: collapse; width: 100%; font-size: 12.5px; }
.dp-grid th, .dp-grid td { border: 1px solid var(--oh-linie); padding: 4px 6px; vertical-align: top; text-align: left; }
.dp-grid thead th { background: var(--oh-flaeche-2); color: var(--oh-text-2); font-weight: 700; font-size: 11.5px; white-space: nowrap; }
.dp-grid thead th.heute { background: var(--dp-heute-kopf); color: var(--oh-accent-dunkel); }
.dp-grid td.heute { background: var(--oh-accent-hauch); }
.dp-grid th:first-child, .dp-grid td:first-child { position: sticky; left: 0; z-index: 1; background: var(--oh-flaeche); }
.dp-grid thead th:first-child { background: var(--oh-flaeche-2); }
.dp-grid .dp-shop { font-weight: 700; font-size: 12px; color: var(--oh-text); white-space: nowrap; }
.dp-grid .dp-shop small { display: block; font-weight: 500; font-size: 11px; color: var(--oh-text-leise); }
.dp-grid tfoot td { background: var(--oh-flaeche); font-size: 11.5px; color: var(--oh-text-leise); font-weight: 600; }
.dp-grid td > * + * { margin-top: 4px; }
.dp-team td { min-width: 112px; }
.dp-wochen td { min-width: 104px; }
.dp-tag { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

.dp-slot { border: 1px solid var(--oh-linie); border-radius: 8px; background: var(--oh-flaeche); overflow: hidden; }
.dp-hd {
  display: flex; justify-content: space-between; gap: 6px;
  background: var(--dp-frueh); color: var(--auf-rot);
  font-weight: 700; font-size: 10.5px; line-height: 1.3; padding: 3px 6px;
  border-radius: 7px 7px 0 0; font-variant-numeric: tabular-nums; white-space: nowrap;
}
.dp-slot[data-form="spaet"] .dp-hd { background: var(--dp-spaet); }
.dp-slot[data-form="ganztag"] .dp-hd { background: var(--dp-ganztag); }
.dp-slot[data-form="sonder"] .dp-hd { background: var(--dp-sonder); }
.dp-bd { display: flex; flex-wrap: wrap; gap: 3px; padding: 4px 6px; }
.dp-bez, .dp-ort { flex-basis: 100%; font-size: 11px; color: var(--oh-text-leise); font-weight: 600; }
.dp-ort { color: var(--oh-text-2); }
.dp-chip { display: inline-block; font-size: 11px; font-weight: 600; line-height: 1.4; padding: 1px 6px; border-radius: 6px; background: var(--oh-flaeche-2); color: var(--oh-text-2); white-space: nowrap; }
.dp-chip.ich { outline: 2px solid var(--oh-accent); outline-offset: -2px; background: var(--oh-flaeche); color: var(--oh-text); font-weight: 700; }

.dp-abw { display: inline-flex; gap: 4px; align-items: baseline; border-radius: 8px; padding: 2px 7px; font-size: 11.5px; font-weight: 600; border: 1px solid var(--oh-linie-stark); background: var(--oh-flaeche-2); color: var(--oh-text-2); white-space: nowrap; }
.dp-abw b { font-weight: 700; }
.dp-abw[data-art="urlaub"] { background: var(--dp-urlaub-flaeche); border-color: var(--dp-urlaub-rand); color: var(--oh-ok-text); }
.dp-abw[data-art="krank"] { background: var(--oh-fehler-weich); border-color: var(--dp-krank-rand); color: var(--oh-fehler-text); }
.dp-abw[data-art="frei"] { background: var(--dp-frei-flaeche); border-color: var(--dp-frei-rand); color: var(--oh-warn-text); }
.dp-abwesend th, .dp-abwesend td { background: var(--oh-hover); }

.dp-bar { display: inline-flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.dp-pfeil {
  display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px; border-radius: var(--r-ui);
  border: 1px solid var(--oh-linie); background: var(--oh-flaeche); color: var(--oh-text-2);
  font-size: 11px; text-decoration: none;
}
.dp-pfeil:hover { background: var(--oh-hover); text-decoration: none; }
.kal-menue { position: relative; }
.kal-menue > summary { list-style: none; cursor: pointer; }
.kal-menue > summary::-webkit-details-marker { display: none; }
.kal-menue-liste { position: absolute; right: 0; top: calc(100% + 6px); z-index: 20; min-width: 250px; padding: 6px; border-radius: var(--r-ui); border: 1px solid var(--oh-linie); background: var(--oh-flaeche); box-shadow: var(--schatten-menue); }
.kal-menue-liste a { display: block; padding: 8px 10px; border-radius: var(--r-ui); font-weight: 600; font-size: 13px; color: var(--oh-text); text-decoration: none; }
.kal-menue-liste a:hover { background: var(--oh-hover); }
.kal-menue-liste small { display: block; font-weight: 400; color: var(--oh-text-leise); }
.dp-kw { display: inline-flex; align-items: center; height: 32px; padding: 0 12px; border-radius: var(--r-pille); background: var(--oh-flaeche-2); color: var(--oh-text); font-weight: 700; font-size: 12.5px; white-space: nowrap; font-variant-numeric: tabular-nums; }

.plan-legende { display: flex; flex-wrap: wrap; gap: 6px 14px; align-items: center; font-size: 12px; color: var(--oh-text-leise); margin: 12px 0 0; }
.dp-legende { display: inline-flex; align-items: center; gap: 6px; }
.dp-legende::before { content: ""; width: 14px; height: 10px; border-radius: 3px; background: var(--dp-frueh); }
.dp-legende[data-form="spaet"]::before { background: var(--dp-spaet); }
.dp-legende[data-form="ganztag"]::before { background: var(--dp-ganztag); }
.dp-legende[data-form="sonder"]::before { background: var(--dp-sonder); }

/* Handy: Mein Plan als Tageskarten untereinander (wie „Meine Woche“ im Portal). */
@media (max-width: 760px) {
  .dp-wochen, .dp-wochen tbody, .dp-wochen tr, .dp-wochen td, .dp-wochen th { display: block; width: auto; min-width: 0; border: 0; padding: 0; position: static; }
  .dp-wochen thead, .dp-wochen tfoot { display: none; }
  .dp-wochen tbody tr { margin-bottom: 14px; }
  .dp-wochen tbody th.dp-shop { padding: 4px 0 6px; font-size: 13px; }
  .dp-wochen tbody th.dp-shop small { display: inline; margin-left: 6px; }
  .dp-wochen tbody td { display: flex; flex-wrap: wrap; gap: 6px; align-items: flex-start; padding: 8px 10px; border: 1px solid var(--oh-linie); border-radius: var(--r-ui); margin-bottom: 6px; background: var(--oh-flaeche); }
  .dp-wochen tbody td.heute { background: var(--oh-accent-hauch); border-color: color-mix(in srgb, var(--oh-accent) 32%, transparent); }
  .dp-wochen td > * + * { margin-top: 0; }
  .dp-wochen .dp-tag { position: static; width: auto; height: auto; clip: auto; flex-basis: 100%; font-weight: 700; font-size: 12px; color: var(--oh-text-2); }
  .dp-wochen .dp-slot { flex: 1 1 100%; }
  .dp-wochen td.dp-summe { border: 0; background: none; padding: 0 2px; font-size: 12px; color: var(--oh-text-leise); font-weight: 600; justify-content: flex-start; }
  .dp-wochen td.dp-summe .dp-tag { flex-basis: auto; font-weight: 600; color: inherit; }
  .dp-bar { width: 100%; }
}

/* ================= Zeiterfassung ================= */
.stempel { display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr); gap: 12px; margin-bottom: 12px; }
.stempel > .karte { margin-bottom: 0; }
.uhr { font-size: 46px; font-weight: 650; letter-spacing: -1.2px; line-height: 1; font-variant-numeric: tabular-nums; margin: 14px 0 4px; }
.uhr-unter { color: var(--oh-text-leise); font-size: 13px; margin: 0 0 18px; }
.tageszahl { display: flex; gap: 18px; margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--oh-linie); flex-wrap: wrap; }
.tageszahl div span { display: block; font-size: 11.5px; color: var(--oh-text-leise); font-weight: 600; }
.tageszahl div b { font-size: 17px; font-weight: 650; font-variant-numeric: tabular-nums; }

/* ================= Ohne Anmeldung: Anmeldung, zweiter Faktor, Fehlerseite ================= */
body.ohne-shell {
  position: relative;
  min-height: 100vh;
  background: var(--aurora), var(--page-bg);
  background-attachment: fixed;
  color: var(--auf-rot);
  isolation: isolate;
}
/* Etappe 16f-Nachschliff (05.10.2026), Nutzer-Entscheidung nach Abnahme: das OneHome-Haus
   gross und leise im Hintergrund der Seiten ohne Anmeldung (Anmeldung, zweiter Faktor,
   Fehlerseite). CSS-Maske statt Bild, damit die Farbe ein Token bleibt (Mandantenfarbe);
   fest am Fenster, unten rechts angeschnitten, hinter allen Karten (z-index -1 im
   isolierten body). Nur hier, nicht in der Arbeitsoberflaeche - dort stoert es Tabellen.
   Etappe 21c (08.10.2026): Maske ist jetzt die OnePOS-Bildmarke (offener Ring) statt des
   OneHome-Hauses - das Haus war nach dem Namenswechsel die letzte sichtbare Altmarke. */
.ohne-shell .buehne-anonym::before {
  content: "";
  position: fixed;
  right: -6vmin;
  bottom: -8vmin;
  width: min(82vmin, 780px);
  aspect-ratio: 1;
  z-index: -1;
  pointer-events: none;
  background: var(--auf-rot-wasserzeichen);
  -webkit-mask: url("/img/onepos/onepos-zeichen-weiss.svg?v=1") center / contain no-repeat;
  mask: url("/img/onepos/onepos-zeichen-weiss.svg?v=1") center / contain no-repeat;
}
.ohne-shell .buehne-anonym {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 40px 18px 40px;
}
.ohne-shell .bannerzone { padding-top: 0; align-items: center; margin-bottom: 22px; }
.ohne-shell .meldungen { width: 100%; max-width: 400px; padding-top: 0; }
.ohne-shell .buehne-inhalt { width: 100%; display: flex; flex-direction: column; align-items: center; }
.ohne-shell .seite { width: 100%; max-width: 400px; }
.ohne-shell .seite:not(.seite-frei) { max-width: 640px; }
.anmeldung-marke { display: flex; align-items: center; gap: 12px; color: var(--auf-rot); margin-bottom: 20px; }
.anmeldung-marke .marke-kachel { background: var(--oh-seitenknopf); border-radius: 12px; width: 44px; height: 44px; display: flex; align-items: center; justify-content: center; box-shadow: inset 0 0 0 1px var(--auf-rot-linie); }
.anmeldung-marke .marke-kachel img { width: 26px; height: 26px; display: block; }
.anmeldung-marke .marke-wort { height: 20px; }
.anmeldung-marke span { display: block; font-size: 13px; color: var(--auf-rot); margin-top: 4px; }
.anmeldung-raster { display: flex; flex-direction: column; align-items: center; width: 100%; }
.anmeldung-karte {
  width: 100%;
  max-width: 400px;
  background: var(--oh-flaeche);
  border: 0;
  border-radius: 16px;
  padding: 26px 24px 22px;
  box-shadow: var(--schatten-anmeldung);
  color: var(--oh-text);
  margin: 0;
}
.anmeldung-karte h1 { font-size: 22px; letter-spacing: -.3px; margin: 0 0 2px; color: var(--oh-text); }
.anmeldung-karte .untertitel { margin: 0 0 18px; font-size: 14px; }
.anmeldung-karte label { max-width: none; }
.anmeldung-karte label input { width: 100%; }
.anmeldung-karte form { margin: 0; }
.anmeldung-karte > :last-child { margin-bottom: 0; }
.anmeldung-fuss { font-size: 13px; margin: 14px 0 0; }
/* Etappe 21d (09.10.2026): Kundenlogo ueber der Anmeldekarte (weisse Kachel), Produkt klein am Kartenfuss. */
.anmeldung-logo { display: flex; align-items: center; justify-content: center; min-height: 56px; padding: 10px 18px; border-radius: 12px; background: var(--logo-kachel); box-shadow: var(--schatten-anmeldung); max-width: 100%; }
.anmeldung-logo img { display: block; width: auto; height: auto; max-height: 40px; max-width: min(240px, 100%); object-fit: contain; }
.anmeldung-mit { margin: 16px 0 0; font-size: 11.5px; color: var(--oh-text-leise); text-align: center; letter-spacing: .2px; }
details.anmeldung-fuss > summary { text-align: left; }
.trenner { display: flex; align-items: center; gap: 10px; color: var(--oh-text-leise); font-size: 12px; margin: 14px 0; }
.trenner::before, .trenner::after { content: ""; flex: 1; height: 1px; background: var(--oh-linie); }
.anmeldung-hinweis { margin: 18px 0 0; color: var(--auf-rot); font-size: 12.5px; text-align: center; max-width: 400px; }

/* Demo-Zugänge als Rollenzeilen (Vorschau „Demo ausprobieren“). */
.demo-besuch { width: 100%; max-width: 400px; margin-top: 14px; padding: 16px 18px; }
.demo-besuch h2 { margin: 0; }
.demo-besuch > p { color: var(--oh-text-leise); font-size: 12.5px; margin: 2px 0 6px; }
.demo-besuch dl { margin: 0; }
.besuch-rolle { display: grid; grid-template-columns: minmax(0, 1fr) auto; column-gap: 12px; align-items: center; padding: 10px 0; border-bottom: 1px solid var(--oh-linie); }
.besuch-rolle:last-child { border-bottom: 0; padding-bottom: 0; }
.besuch-rolle dt { grid-column: 1; margin: 0; font-size: 13.5px; display: flex; align-items: center; gap: 10px; }
.besuch-rolle dt .avatar { margin-bottom: -16px; }
.besuch-rolle dd { grid-column: 1 / -1; margin: 0 0 0 42px; font-size: 12px; color: var(--oh-text-leise); overflow-wrap: anywhere; }
.besuch-rolle dd.besuch-aktion { grid-column: 2; grid-row: 1; align-self: start; margin: 0; }
.besuch-aktion button { padding: 6px 11px; min-height: 30px; font-size: 12.5px; }
.wert { font-family: var(--font-mono); color: var(--oh-text); user-select: all; font-size: 12px; }
.demo-codes { margin: 14px 0 0; padding: 10px 12px; border-radius: var(--r-feld); background: var(--oh-hover); }
.demo-codes p { margin: 0 0 4px; }
.demo-codes ul { list-style: none; padding: 0; margin: 0; display: flex; flex-wrap: wrap; gap: 4px 16px; }
.demo-codes li { margin: 0; font-size: 13px; }
.demo-codes li[data-gewaehlt] { font-weight: 650; color: var(--oh-accent-dunkel); }

/* Fehlerseite */
.fehler-code { font-size: 11px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--oh-text-leise); margin: 0 0 6px; }
.seite-fehler .anmeldung-karte { max-width: 480px; }

/* ================= Handy (unter 761 px) ================= */
@media (max-width: 760px) {
  :root { --kopf-hoehe: 56px; --karte-innen: 16px; }
  body.mit-shell { grid-template-columns: minmax(0, 1fr); }
  .kopfleiste { grid-column: 1; padding: 0 12px 0 8px; gap: 8px; }
  .kopf-burger { display: block; }
  .kopf-haus { display: flex; }
  .buehne { grid-column: 1; border-top-left-radius: 0; padding: 0 12px 32px; }
  .seitenleiste {
    position: fixed;
    top: 0; left: 0; bottom: 0;
    width: 272px;
    height: auto;
    transform: translateX(-100%);
    transition: transform .22s ease;
    box-shadow: none;
    visibility: hidden;
  }
  body.menue-offen .seitenleiste { transform: none; box-shadow: var(--schatten-leiste); visibility: visible; }
  body.menue-offen .schleier { display: block; position: fixed; inset: 0; background: var(--schleier); z-index: 25; }
  body.menue-offen { overflow: hidden; }
  .kopfzone, .seite:not(.seite-frei) > h1:first-child { padding: 20px 0 14px; }
  .karte { padding: 16px; }
  .raster-2, .stempel { grid-template-columns: minmax(0, 1fr); }
  .stat-reihe { grid-template-columns: minmax(0, 1fr); gap: 8px; }
  .stat-karte { padding: 12px 16px; }
  .stat-karte.primaer::before { left: 16px; }
  .uhr { font-size: 40px; }
  .knoepfe > button, .knoepfe > form, .knoepfe > form > button { flex: 1; }
  select, textarea, input:not([type="checkbox"]):not([type="radio"]):not([type="file"]) { font-size: 16px; }
  label { max-width: none; }
  .ohne-shell .buehne-anonym { padding: 28px 14px; }
  .ohne-shell .buehne-anonym::before { width: 120vw; right: -38vw; bottom: -14vw; }
  .besuch-rolle dt .avatar { display: none; }
  .besuch-rolle dd { margin-left: 0; }
  .hero .auf-rot { width: 100%; }
}
@media (prefers-reduced-motion: reduce) {
  .seitenleiste, details.nav-gruppe > summary::after { transition: none; }
  /* Optik-Scheibe 1 (17.10.2026): Karten-Hover ohne Übergang. */
  .karte, .stat-karte { transition: none; }
}

/* ================= Etappe 18a (05.10.2026): Seitenkopf, Reiter, Meldungen, Demo =================
   Vorschau „Demo-Ausbau“ (abgenommen). Werte 1:1 aus der Vorschau, Farben als Token oben.
   Seitenkopf: base.html.twig rendert <header class="vfkopf"> aus `seitenkopf()`, sobald eine
   Vorlage `{% block seitentitel %}` setzt – die <h1> steht damit nicht mehr in `.seite`, die
   Karte beginnt in Rasterzeile 1 (Regel `:not(:has(> h1:first-child))` oben). */
.vfkopf {
  position: relative;
  padding: 22px 0 0;
  z-index: 5;
  /* Optik-Scheibe 1 (17.10.2026): feste Titelspalte wie OneHome (header.php,
     `--vfkopf-titelspalte: 256px` = Breite des längsten Seitennamens). Statt `margin-right:auto`
     bekommt der Titel eine feste Spalte, damit die Pillenzone auf jeder Seite an derselben
     Stelle beginnt; ein längerer Seitenname hebt nur diesen Wert. */
  --vfkopf-titelspalte: 256px;
}
.vfkopf-wz {
  position: absolute; right: 0; top: 14px;
  font-size: 60px; font-weight: 800; letter-spacing: -.04em; line-height: 1;
  color: var(--kopf-wasserzeichen); text-transform: uppercase;
  pointer-events: none; user-select: none; z-index: 0; white-space: nowrap;
}
.vfkopf-zeile { position: relative; z-index: 2; display: flex; align-items: center; gap: 12px 24px; min-height: 44px; flex-wrap: wrap; }
.vfkopf-links { flex: 0 0 var(--vfkopf-titelspalte); min-width: 0; }
h1.vfkopf-titel { margin: 0; font-size: 21px; line-height: 1.15; font-weight: 800; letter-spacing: -.015em; color: var(--auf-rot); overflow-wrap: anywhere; }
.vfkopf-bereich { margin: 2px 0 0; font-size: 11.5px; font-weight: 600; color: var(--auf-rot-leise); }
.vfkopf-pillen { flex: 1 1 auto; min-width: 0; display: flex; gap: 6px; flex-wrap: wrap; align-items: center; justify-content: flex-end; }
.vfp {
  display: inline-flex; align-items: center;
  font-size: 12.5px; font-weight: 600; color: var(--auf-rot-pille-text);
  border: 1px solid var(--auf-rot-pille-rand); border-radius: var(--r-pille);
  padding: 5px 12px; white-space: nowrap; text-decoration: none;
  /* Optik-Scheibe 2 (17.10.2026): Die aktive Pille wechselt nicht mehr hart, sondern blendet
     Fläche, Schrift, Rand, Hebung und Schatten über (OneHomes `.vfp.on` wirkt ebenso weich).
     Reine CSS-Transition – kein zusätzliches Skript, kein Gleiter, der bei jedem Umbau
     nachgeführt werden müsste. */
  transition: color .18s ease, border-color .18s ease, background-color .18s ease, box-shadow .18s ease, transform .18s ease;
  list-style: none; cursor: pointer;
}
.vfp:hover { color: var(--auf-rot); border-color: var(--auf-rot-pille-rand-hover); text-decoration: none; }
.vfp.on { background: var(--oh-weiss); color: var(--oh-accent); font-weight: 700; border-color: transparent; box-shadow: var(--oh-knopf-glanz); transform: translateY(-1px); }
.vfp-mehr { border-style: dashed; }
.vfp-mehr::-webkit-details-marker { display: none; }
.vfp .z {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 17px; height: 17px; margin-left: 5px; padding: 0 5px;
  border-radius: var(--r-pille); background: var(--auf-rot-zahl); color: var(--oh-accent-dunkel);
  font-size: 10.5px; font-weight: 800;
}
.vfp.on .z { background: var(--oh-accent); color: var(--oh-weiss); }
.vfp-mehr-wahl { position: relative; }
.vfp-liste {
  position: absolute; right: 0; top: calc(100% + 6px); z-index: 40; min-width: 200px;
  display: flex; flex-direction: column; padding: 6px;
  background: var(--oh-flaeche); border-radius: var(--r-ui); box-shadow: var(--schatten-menue);
}
.vfp-liste a { color: var(--oh-text); padding: 8px 10px; border-radius: var(--r-feld); font-size: 13px; font-weight: 600; }
.vfp-liste a:hover { background: var(--oh-hover); text-decoration: none; }
.vfp-liste a[aria-current="page"] { color: var(--oh-accent-dunkel); background: var(--oh-accent-weich); }
.vfp-liste .z { font-size: 11px; font-weight: 800; color: var(--oh-accent-dunkel); }
.vfp:focus-visible, .vfp-liste a:focus-visible { outline: 2px solid var(--auf-rot); outline-offset: 2px; }
/* Knopfzeile unter dem Kopf (Mein Plan: Kalenderdatei, Abo, Krank melden). */
.kopf-aktionen { display: flex; gap: 8px; flex-wrap: wrap; padding: 14px 0 4px; }

/* Reiter: Laschen; auf Rot hell, in der Karte grau mit weißer aktiver Lasche. */
.reiter { display: flex; gap: 5px; padding: 0 10px; margin-top: 18px; flex-wrap: wrap; }
.seite:not(.seite-frei) > .reiter { padding: 0; border-bottom: 1px solid var(--oh-linie); }
.reiter a {
  font-size: 13px; font-weight: 650; color: var(--auf-rot);
  background: var(--auf-rot-reiter); border: 1px solid var(--auf-rot-reiter-rand); border-bottom: 0;
  border-radius: 10px 10px 0 0; padding: 8px 18px; white-space: nowrap; text-decoration: none;
}
.reiter a .z { font-size: 11.5px; font-weight: 700; opacity: .75; margin-left: 4px; }
.reiter a[aria-current] { background: var(--oh-flaeche); color: var(--oh-text); border-color: var(--oh-flaeche); }
.seite:not(.seite-frei) > .reiter a { color: var(--oh-text-2); background: var(--oh-flaeche-2); border-color: var(--oh-seitenlinie); }
.seite:not(.seite-frei) > .reiter a[aria-current] { background: var(--oh-flaeche); color: var(--oh-text); border-color: var(--oh-linie); }

/* Meldungen: weiße Karte mit farbiger linker Kante (Erfolg grün, Fehler rot). */
.meldungen > p[role] {
  padding: 12px 15px; border-radius: var(--r-ui); font-size: 13.5px; font-weight: 600;
  background: var(--oh-flaeche); border-left: 3px solid var(--oh-text-blass); color: var(--oh-text);
}
.meldungen > p.meldung-erfolg { color: var(--oh-ok-text); border-left-color: var(--oh-ok); }
.meldungen > p.meldung-fehler { color: var(--oh-fehler-text); border-left-color: var(--oh-fehler); }

/* Führungsband (gelb = Demo-Führung, keine Fehlermeldung): Vier-Augen, Meine Daten. */
.fuehrung {
  display: flex; gap: 12px; align-items: flex-start;
  border-radius: 10px; background: var(--fuehrung-flaeche); border: 1px solid var(--fuehrung-rand);
  padding: 12px 14px; margin: 0 0 12px; font-size: 13px; color: var(--fuehrung-text);
}
.fuehrung > .sym { width: 20px; height: 20px; flex: none; color: var(--oh-warn); margin-top: 1px; }
.fuehrung b { color: var(--fuehrung-stark); }
.fuehrung-text { flex: 1; min-width: 0; }
.fuehrung .akt { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; margin-top: 8px; }
.fuehrung code { overflow-wrap: anywhere; font-size: 12.5px; }

/* Demo-Leiste: schwarz über allem, eigene Rasterzeile der Shell. */
.demo-leiste {
  display: flex; align-items: center; gap: 10px 14px; flex-wrap: wrap;
  background: var(--demo-leiste); color: var(--oh-weiss); font-size: 12.5px; padding: 7px 16px;
}
.demo-leiste b { font-weight: 650; }
.demo-leiste .luecke { flex: 1; }
.demo-leiste .wechsel { display: inline-flex; align-items: center; gap: 6px; margin: 0; color: var(--demo-leiste-leise); }
.demo-leiste label { margin: 0; color: inherit; font-weight: 500; max-width: none; }
.demo-leiste select {
  font-family: var(--font); font-size: 12.5px; background: var(--demo-leiste-feld); color: var(--oh-weiss);
  border: 1px solid var(--demo-leiste-rand); border-radius: 7px; padding: 3px 8px; width: auto; min-height: 0;
}
.demo-leiste button { font-size: 12px; padding: 3px 10px; min-height: 0; }
.demo-leiste .postlink { color: var(--oh-weiss); font-weight: 600; border-bottom: 1px solid var(--demo-leiste-linie); }
.demo-leiste .postlink:hover { text-decoration: none; border-bottom-color: var(--oh-weiss); }
.demo-leiste a:focus-visible, .demo-leiste select:focus-visible, .demo-leiste button:focus-visible { outline: 2px solid var(--oh-weiss); outline-offset: 2px; }
body.mit-shell.mit-demo-leiste { grid-template-rows: auto var(--kopf-hoehe) minmax(0, 1fr); }
body.mit-demo-leiste .demo-leiste { grid-column: 1 / 3; grid-row: 1; }
body.mit-shell.mit-demo-leiste .seitenleiste { grid-row: 2 / 4; }
body.mit-shell.mit-demo-leiste .kopfleiste { grid-row: 2; }
body.mit-shell.mit-demo-leiste .buehne { grid-row: 3; }
.nav-zahl {
  margin-left: auto;
  min-width: 18px; height: 18px; padding: 0 5px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: var(--r-pille);
  background: var(--oh-flaeche-2); color: var(--oh-text-2);
  font-size: 11px; font-weight: 700; line-height: 1; font-variant-numeric: tabular-nums;
}
/* Optik-Scheibe 1 (17.10.2026): Zähler als Badge statt bloßer Zahl – auf dem aktiven
   Navigationseintrag füllt er sich mit dem Akzent (Weiß auf Akzent, AA), sonst bleibt er
   leise grau, damit die Seitenleiste nicht bunt wird. */
.leiste-nav a[aria-current="page"] .nav-zahl { background: var(--oh-accent); color: var(--auf-rot); }

/* Anmeldung: Zweckzeile und „neu“-Marke je Besucherrolle. */
.besuch-zweck { color: var(--oh-text-leise); }
.marke-neu {
  display: inline-block; margin-left: 4px; vertical-align: 1px;
  background: var(--oh-accent); color: var(--oh-weiss); border-radius: var(--r-pille);
  font-size: 10.5px; font-weight: 700; letter-spacing: .03em; text-transform: uppercase; padding: 2px 8px;
}
.besuch-rolle[data-gewaehlt] { outline: 2px solid var(--oh-accent); outline-offset: 2px; border-radius: var(--r-ui); }

/* Demo-Postfach: Liste links, Leseansicht rechts. */
.postfach { display: grid; grid-template-columns: minmax(0, 340px) minmax(0, 1fr); gap: 0 22px; min-height: 360px; margin-top: var(--karte-innen); }
.postfach-liste { border-right: 1px solid var(--oh-linie); padding-right: 12px; }
.postfach-liste ul { list-style: none; margin: 0; padding: 0; }
.postfach-liste li a {
  display: block; padding: 10px 12px; border-bottom: 1px solid var(--oh-linie); color: var(--oh-text);
  position: relative; text-decoration: none;
}
.postfach-liste li a:hover { background: var(--oh-hover); }
.postfach-liste li a[aria-current] { background: var(--oh-accent-hauch); }
.postfach-liste li a[aria-current]::before { content: ""; position: absolute; left: 0; top: 8px; bottom: 8px; width: 3px; border-radius: 3px; background: var(--oh-accent); }
.postfach-liste b { display: block; font-size: 13.5px; font-weight: 600; }
.postfach-lesen { min-width: 0; }
.postfach-lesen h2 { font-size: 17px; margin: 0 0 6px; padding: 0; border: 0; }
.mail-text { white-space: pre-wrap; overflow-wrap: anywhere; font-size: 13.5px; color: var(--oh-text-2); border: 1px solid var(--oh-linie); border-radius: 10px; padding: 16px; margin-top: 12px; }
.mail-fuss { margin-top: 8px; color: var(--oh-text-blass); }
.postfach .leer { color: var(--oh-text-leise); }

/* „Jetzt im Shop“ auf „Heute“ (Shopleitung). */
.jetzt-liste { list-style: none; margin: 0; padding: 0; display: grid; gap: 2px; }
.jetzt-liste li { display: flex; align-items: center; gap: 10px; padding: 8px 0; border-bottom: 1px solid var(--oh-linie); color: var(--oh-text); }
.jetzt-liste li:last-child { border-bottom: 0; }
.jetzt-liste .luecke { flex: 1; }
.jetzt-liste .klein { color: var(--oh-text-leise); }

/* Tour je Rolle auf „Heute“. */
.tour-kopf { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.tour-kopf .luecke { flex: 1; min-width: 180px; }
.fortschritt { display: block; width: 100%; height: 6px; margin-top: 6px; accent-color: var(--oh-accent); }
.schritte { list-style: none; margin: 14px 0 0; padding: 0; display: grid; gap: 2px; }
.schritt { display: flex; gap: 12px; align-items: flex-start; padding: 9px 10px; border-radius: 10px; color: var(--oh-text); }
a.schritt:hover { background: var(--oh-hover); text-decoration: none; }
.schritt .haken {
  width: 22px; height: 22px; border-radius: 7px; border: 1.6px solid var(--oh-linie-stark); flex: none;
  display: flex; align-items: center; justify-content: center; margin-top: 1px; background: var(--oh-flaeche); color: var(--oh-weiss);
}
.schritt .haken .sym { width: 14px; height: 14px; opacity: 0; }
.schritt.erledigt .haken { background: var(--oh-ok); border-color: var(--oh-ok); }
.schritt.erledigt .haken .sym { opacity: 1; }
.schritt.erledigt .was b { color: var(--oh-text-leise); text-decoration: line-through; }
.schritt .was { flex: 1; min-width: 0; }
.schritt .was b { display: block; font-weight: 600; font-size: 13.5px; }
.schritt .was span { display: block; font-size: 12.5px; color: var(--oh-text-leise); }
.schritt .ziel { font-size: 12px; font-weight: 600; color: var(--oh-accent-dunkel); white-space: nowrap; margin-top: 2px; }
.schritt .vier {
  display: inline-block; margin-left: 6px; font-size: 10.5px; font-weight: 700; letter-spacing: .03em;
  text-transform: uppercase; color: var(--oh-warn-text); background: var(--oh-warn-weich);
  border-radius: var(--r-pille); padding: 1px 7px; vertical-align: 1px;
}
.tour-aus { margin: 0; }

@media (max-width: 760px) {
  .vfkopf { padding: 16px 0 0; --vfkopf-titelspalte: 100%; }
  .vfkopf-wz { font-size: 40px; }
  .vfkopf-pillen { flex-wrap: nowrap; overflow-x: auto; width: 100%; padding-bottom: 2px; -webkit-overflow-scrolling: touch; justify-content: flex-start; }
  /* Die Mehr-Liste würde im Scrollbereich abgeschnitten – auf dem Handy steht sie fest. */
  .vfp-liste { position: fixed; left: 12px; right: 12px; top: auto; }
  .reiter { padding: 0 4px; }
  .reiter a { padding: 7px 12px; }
  body.mit-shell.mit-demo-leiste { grid-template-columns: minmax(0, 1fr); }
  body.mit-demo-leiste .demo-leiste { grid-column: 1; font-size: 12px; padding: 7px 12px; }
  .demo-leiste .lang { display: none; }
  body.mit-shell.mit-demo-leiste .kopfleiste, body.mit-shell.mit-demo-leiste .buehne { grid-column: 1; }
  .postfach { grid-template-columns: minmax(0, 1fr); }
  .postfach-liste { border-right: 0; padding-right: 0; border-bottom: 1px solid var(--oh-linie); margin-bottom: 12px; }
}

/* ================= Etappe 18e (06.10.2026): Demo-Vertrieb =================
   Nutzer-Entscheidung 06.10.2026, Vorschau „Demo Paket 3“: Einstiegsseite, Datenschutz zum
   Anfassen, Impressum/Datenschutzerklärung, Verarbeitungsverzeichnis-Druck, Hinweis bei
   Freitexten und die mobile Tableiste (P-102). Farben nur über Tokens. */

/* Öffentliche Seiten ohne Anmeldung: breiter als die Anmeldekarte. */
.ohne-shell.seite-oeffentlich .buehne-inhalt { max-width: var(--inhalt-breite); align-items: stretch; }
.ohne-shell.seite-oeffentlich .seite { max-width: none; }
.ohne-shell.seite-oeffentlich .bannerzone { width: 100%; max-width: var(--inhalt-breite); }
.ohne-shell.seite-oeffentlich .vfkopf { padding-bottom: 18px; }

/* Einstieg auf Rot. */
.einstieg { color: var(--auf-rot); padding: 4px 0 18px; }
.einstieg-titel { margin: 0 0 10px; font-size: clamp(22px, 4vw, 30px); line-height: 1.2; font-weight: 800; letter-spacing: -.02em; max-width: 640px; color: var(--auf-rot); }
.einstieg-lead { margin: 0 0 22px; font-size: 14.5px; color: var(--auf-rot-text); max-width: 560px; }
.einstieg-aktionen { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; margin-bottom: 10px; }
.einstieg-fein { font-size: 11.5px; color: var(--auf-rot-fein); display: flex; align-items: center; gap: 6px; margin: 4px 0 0; }
.einstieg-fein i { width: 5px; height: 5px; border-radius: 50%; background: currentColor; display: block; }
.einstieg-module { list-style: none; padding: 0; display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px; margin: 22px 0 4px; }
.einstieg-module li { background: var(--auf-rot-karte); border: 1px solid var(--auf-rot-linie); border-radius: var(--r-karte); padding: 16px; margin: 0; min-width: 0; }
.einstieg-module h2 { margin: 0 0 4px; font-size: 14.5px; font-weight: 700; color: var(--auf-rot); }
.einstieg-module p { margin: 0; font-size: 12.5px; color: var(--auf-rot-text); line-height: 1.4; }
.einstieg-kuerzel { display: inline-flex; align-items: center; justify-content: center; width: 30px; height: 30px; border-radius: 8px; background: var(--oh-weiss); color: var(--oh-accent); font-weight: 750; font-size: 13px; letter-spacing: -.3px; margin-bottom: 10px; }
.einstieg-versprechen h2 { margin: 0; }
.versprechen-liste { list-style: none; padding: 0; margin: 14px 0 0; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; }
.versprechen-liste li { background: var(--oh-flaeche); border: 1px solid var(--oh-linie); border-radius: var(--r-karte); padding: 16px; box-shadow: var(--schatten); margin: 0; min-width: 0; }
.versprechen-liste .nr { display: inline-flex; align-items: center; justify-content: center; width: 24px; height: 24px; border-radius: 7px; background: var(--oh-ok-weich); color: var(--oh-ok-text); font-weight: 700; font-size: 13px; margin-bottom: 8px; }
.versprechen-liste h3 { margin: 0 0 4px; font-size: 13.5px; font-weight: 650; }
.versprechen-liste p { margin: 0; font-size: 12.5px; color: var(--oh-text-leise); }
.zum-anfassen-link { display: inline-flex; align-items: center; gap: 5px; font-size: 12.5px; font-weight: 650; color: var(--oh-accent-dunkel); margin-top: 10px; }
p.zum-anfassen-link { margin: 16px 0 0; }
p.zum-anfassen-link a { font-weight: 650; }

/* Platzhalter (Impressum, Kontakt): sichtbar markiert, nie ein erfundener Wert. */
.pille.platzhalter { background: var(--oh-warn-weich); color: var(--oh-warn-text); font-size: 10.5px; letter-spacing: .03em; text-transform: uppercase; padding: 2px 8px; }
.auf-rot .pille.platzhalter { background: var(--oh-flaeche); }
.platzhalter-feld { background: var(--oh-warn-weich); color: var(--oh-warn-text); border-radius: 5px; padding: 1px 6px; font-weight: 650; font-size: 12.5px; overflow-wrap: anywhere; }

/* Fußzeile der öffentlichen Seiten. */
.oeffentlich-fuss { width: 100%; max-width: var(--inhalt-breite); margin: 24px auto 0; display: flex; flex-wrap: wrap; gap: 10px 14px; align-items: center; color: var(--auf-rot-leise); font-size: 12px; }
.oeffentlich-fuss nav { display: flex; flex-wrap: wrap; gap: 6px 10px; align-items: center; }
.oeffentlich-fuss a { color: var(--auf-rot-pille-text); text-decoration: underline; text-underline-offset: 2px; font-weight: 550; }
.oeffentlich-fuss a:focus-visible { outline-color: var(--auf-rot); }
.oeffentlich-fuss .trenn { opacity: .4; }
.oeffentlich-fuss .fuss-anbieter { margin-left: auto; opacity: .8; }
.seite-anmeldung .oeffentlich-fuss { justify-content: center; max-width: 400px; }
.seite-anmeldung .oeffentlich-fuss .fuss-anbieter { margin-left: 0; }

/* Datenschutz zum Anfassen. */
.zum-anfassen-einleitung { margin: 0 0 16px; font-size: 13px; color: var(--oh-text-leise); max-width: 640px; }
.zum-anfassen-raster { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; margin-bottom: 12px; }
.zum-anfassen-raster > .karte { margin: 0; }
.zum-anfassen-kachel .karte-kopf { margin-bottom: 0; }
.zum-anfassen-kachel h2 { font-size: 15px; }
.zum-anfassen-kachel .mini { font-size: 12px; color: var(--oh-text-leise); margin: 8px 0 10px; }
.kette { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; font-family: var(--font-mono); font-size: 11px; color: var(--oh-text-blass); margin: 0; }
.kette span { background: var(--oh-flaeche-2); border-radius: 6px; padding: 3px 7px; }
.kette i { font-style: normal; }
.k5-raster { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; margin: 10px 0 0; }
.k5-raster .stat-karte { padding: 12px; }
.k5-raster .stat-wert { font-size: 20px; }
.k5-raster .k5-gesperrt { font-size: 16px; color: var(--oh-text-blass); }
.zum-anfassen-vvt { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; margin: 0; }
.zum-anfassen-vvt .vvt-text { flex: 1; min-width: 220px; }
.zum-anfassen-vvt h2 { margin: 0; font-size: 14.5px; }

/* Impressum / Datenschutzerklärung. */
.rechts-text { max-width: 760px; }
.rechts-text h2 { font-size: 15px; font-weight: 700; margin: 22px 0 8px; }
.rechts-text p, .rechts-text ul { margin: 0 0 10px; font-size: 13.5px; color: var(--oh-text-2); }
.rechts-text ul { padding-left: 20px; }
.entwurf-hinweis { padding: 12px 15px; border-radius: var(--r-ui); font-size: 13.5px; font-weight: 600; margin: 0 0 14px; color: var(--oh-warn-text); background: var(--oh-warn-weich); border-left: 3px solid var(--oh-warn); }
.entwurf-hinweis + h2 { margin-top: 0; }

/* Verarbeitungsverzeichnis als Druckansicht. */
.vvt-leiste { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; margin-bottom: 14px; padding-bottom: 12px; border-bottom: 1px solid var(--oh-linie); font-size: 13px; }
.vvt-leiste .luecke { flex: 1; }
.vvt-ohne-js { color: var(--oh-text-leise); font-size: 12.5px; }
.vvt-druck dl { display: grid; grid-template-columns: minmax(140px, 220px) minmax(0, 1fr); gap: 4px 14px; font-size: 13px; }
.vvt-druck dt { font-weight: 650; color: var(--oh-text-leise); }
.vvt-druck dd { margin: 0; overflow-wrap: anywhere; }
.vvt-druck dd ul { margin: 0; padding-left: 18px; }
.vvt-druck h1 { font-size: 20px; }
@media print {
  body.ohne-shell { background: var(--oh-flaeche); color: var(--oh-text); }
  body.ohne-shell::after, .ohne-shell .buehne-anonym::before { display: none; }
  .seite-druck .bannerzone, .seite-druck .anmeldung-marke, .seite-druck .vfkopf, .seite-druck .oeffentlich-fuss, .seite-druck .nicht-drucken, .sprung { display: none; }
  .seite-druck .buehne-anonym { padding: 0; }
  .seite-druck .karte { box-shadow: none; border: 0; background: var(--oh-flaeche); padding: 0; }
  .seite-druck section { break-inside: avoid; }
}

/* ---------- Etiketten: A4-Raster und Druck (Etappe 30b, 20.10.2026) ----------
   Drei Etiketten je Zeile zu 70 x 36 mm; 3 x 70 mm = 210 mm, also genau A4-Breite. Auf dem
   Bildschirm darf die Fläche seitlich scrollen (kleine Fenster), im Druck gilt ein eigener
   Seitenrahmen ohne Rand. Der Name bricht nach zwei Zeilen ab, statt aus dem Etikett zu
   laufen; Preis und Fußzeile stehen fest unten. Keine Hintergründe, damit der Druck keine
   Tinte frisst. */
.etiketten-flaeche { overflow-x: auto; padding: 2px 0 6px; }
.etiketten-blatt { width: 210mm; margin: 0 auto; background: #fff; color: #111; }
.etiketten-raster { display: grid; grid-template-columns: repeat(3, 70mm); align-content: start; }
.etikett {
  box-sizing: border-box;
  width: 70mm;
  height: 36mm;
  padding: 3mm 3.5mm;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: 1mm;
  background: #fff;
  color: #111;
  border-radius: 0;
}
.etikett-name {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  overflow: hidden;
  font-size: 12pt;
  line-height: 1.15;
  font-weight: 700;
  overflow-wrap: anywhere;
}
.etikett-preis { font-size: 16pt; line-height: 1.1; font-weight: 700; font-variant-numeric: tabular-nums; }
.etikett-fuss { font-size: 8pt; line-height: 1.2; color: #333; }
.etiketten-leiste { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }

/* Eigener Seitenrahmen nur für das Etikettenblatt; andere Druckseiten (z. B. das
   Verarbeitungsverzeichnis) behalten ihre Ränder. */
@page etiketten { size: A4; margin: 0; }

@media print {
  body.seite-etiketten { background: #fff; color: #000; }
  body.seite-etiketten .seitenleiste,
  body.seite-etiketten .kopfleiste,
  body.seite-etiketten .vfkopf,
  body.seite-etiketten .bannerzone,
  body.seite-etiketten .demo-leiste,
  body.seite-etiketten .tableiste,
  body.seite-etiketten .meldungen,
  body.seite-etiketten .sprung,
  body.seite-etiketten .etiketten-auswahl,
  body.seite-etiketten .etiketten-vorschau .karte-kopf,
  body.seite-etiketten button,
  body.seite-etiketten .knopf { display: none !important; }
  body.seite-etiketten .buehne { padding: 0; background: #fff; color: #000; }
  body.seite-etiketten .buehne::before,
  body.seite-etiketten .buehne::after,
  body.seite-etiketten .buehne > .buehne-inhalt::before,
  body.seite-etiketten .buehne > .buehne-inhalt::after { display: none !important; }
  body.seite-etiketten .buehne-inhalt { max-width: none; }
  body.seite-etiketten .seite { margin: 0; padding: 0; color: #000; }
  body.seite-etiketten .seite:not(.seite-frei) > * { margin-left: 0; margin-right: 0; }
  body.seite-etiketten .karte { margin: 0; padding: 0; border: 0; box-shadow: none; background: #fff; }
  body.seite-etiketten .etiketten-flaeche { overflow: visible; padding: 0; }
  body.seite-etiketten .etiketten-blatt { page: etiketten; width: 210mm; margin: 0; }
  body.seite-etiketten .etikett { break-inside: avoid; page-break-inside: avoid; border: 0; }
}

/* Hinweis bei Freitexten (nur Demobetrieb, eingefügt von |demo_freitext). */
.freitext-hinweis { display: flex; gap: 9px; align-items: flex-start; background: var(--oh-warn-weich); color: var(--oh-warn-text); border-radius: var(--r-ui); padding: 10px 12px; font-size: 12.5px; font-weight: 600; margin: 0 0 8px; line-height: 1.4; max-width: 640px; }
.freitext-hinweis svg { width: 16px; height: 16px; flex: none; margin-top: 1px; }

/* Mobile Tableiste (P-102): auf dem Desktop unsichtbar. */
.tableiste { display: none; }

@media (max-width: 760px) {
  .einstieg-module { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .versprechen-liste, .zum-anfassen-raster { grid-template-columns: minmax(0, 1fr); }
  .einstieg-aktionen .knopf { flex: 1 1 auto; }
  .oeffentlich-fuss .fuss-anbieter { margin-left: 0; }
  .vvt-druck dl { grid-template-columns: minmax(0, 1fr); }
  .vvt-druck dd { margin-bottom: 6px; }

  body.mit-shell { padding-bottom: calc(var(--tableiste-hoehe) + env(safe-area-inset-bottom, 0px)); }
  .tableiste {
    display: flex;
    position: fixed; left: 0; right: 0; bottom: 0;
    z-index: 22;
    background: var(--oh-flaeche);
    border-top: 1px solid var(--oh-linie);
    padding: 7px 4px calc(7px + env(safe-area-inset-bottom, 0px));
  }
  .tableiste a {
    flex: 1 1 0; min-width: 0;
    display: flex; flex-direction: column; align-items: center; gap: 3px;
    font-size: 10px; font-weight: 650; color: var(--oh-text-blass);
    padding: 4px 2px; text-decoration: none;
  }
  .tableiste a span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%; }
  .tableiste a svg { width: 20px; height: 20px; flex: none; }
  .tableiste a[aria-current="page"] { color: var(--oh-accent-dunkel); }
  .tableiste a:focus-visible { outline: 2px solid var(--oh-accent); outline-offset: -2px; border-radius: var(--r-feld); }
  .tableiste a.stempel-tab { margin-top: -26px; }
  .tableiste .stempel-knopf {
    width: 52px; height: 52px; border-radius: 50%;
    background: var(--oh-knopf); color: var(--oh-weiss);
    display: flex; align-items: center; justify-content: center;
    box-shadow: var(--schatten-stempel), 0 0 0 4px var(--oh-flaeche);
    margin-bottom: 2px; overflow: visible;
  }
  .tableiste .stempel-knopf svg { width: 22px; height: 22px; }
}
@media (max-width: 420px) {
  .einstieg-module, .k5-raster { grid-template-columns: minmax(0, 1fr); }
}

/* ---------------------------------------------------------------------------------------------
   Planungsraster (Etappe 20a, 07.10.2026, ADR-0036): Shop × Tag und Person × Tag, Wochenleiste,
   Kontextmenü. Kartenkopf in der Lage-Farbe, Lage und Chips immer auch als Text. Kopfzeile und
   Shopspalte kleben beim Scrollen; unter 768 px scrollt das Raster waagerecht in seiner Hülle,
   die Seite selbst nie.
   --------------------------------------------------------------------------------------------- */
.dp-lage { display: inline-block; font-size: 11px; font-weight: 700; line-height: 1.4; padding: 1px 7px; border-radius: 6px; color: var(--auf-rot); background: var(--dp-frueh); white-space: nowrap; }
.dp-lage--spaet { background: var(--dp-spaet); }
.dp-lage--ganztag { background: var(--dp-ganztag); }
.dp-lage--sonder { background: var(--dp-sonder); }

.dp-status { display: inline-block; font-size: 12px; font-weight: 700; padding: 2px 9px; border-radius: var(--r-pille); background: var(--oh-flaeche-2); color: var(--oh-text-2); }
.dp-status--eingefroren { background: var(--dp-frei-flaeche); color: var(--oh-warn-text); }
.dp-status--veroeffentlicht { background: var(--dp-urlaub-flaeche); color: var(--oh-ok-text); }
.dp-statuszeile form { display: inline-flex; gap: 8px; align-items: center; flex-wrap: wrap; margin: 6px 12px 0 0; }

.dp-leiste { display: flex; align-items: center; gap: 6px; margin: 0 0 14px; }
.dp-leiste ol { display: flex; gap: 6px; list-style: none; margin: 0; padding: 0; overflow-x: auto; flex: 1 1 auto; min-width: 0; }
.dp-leiste-woche { display: flex; flex-direction: column; align-items: flex-start; gap: 1px; min-width: 92px; padding: 6px 10px; border: 1px solid var(--oh-linie); border-radius: var(--r-ui); background: var(--oh-flaeche); color: var(--oh-text); text-decoration: none; }
.dp-leiste-woche:hover { background: var(--oh-hover); text-decoration: none; }
.dp-leiste-woche.on { border-color: var(--oh-accent); box-shadow: inset 0 0 0 1px var(--oh-accent); }
.dp-leiste-woche small { font-size: 11px; color: var(--oh-text-leise); font-weight: 600; }
.dp-leiste-kw { font-weight: 700; font-size: 12.5px; font-variant-numeric: tabular-nums; }
.dp-leiste-punkt { width: 10px; height: 10px; border-radius: 50%; border: 2px solid var(--oh-linie-stark); background: transparent; }
.dp-leiste-woche[data-zustand="entwurf"] .dp-leiste-punkt { background: var(--oh-text-leise); border-color: var(--oh-text-leise); }
.dp-leiste-woche[data-zustand="eingefroren"] .dp-leiste-punkt { background: var(--oh-warn); border-color: var(--oh-warn); }
.dp-leiste-woche[data-zustand="veroeffentlicht"] .dp-leiste-punkt { background: var(--oh-ok); border-color: var(--oh-ok); }
.dp-leiste-woche[data-leiste-luecke] .dp-leiste-punkt { box-shadow: 0 0 0 2px var(--oh-flaeche), 0 0 0 4px var(--oh-fehler); }

.dp-raster-kopf { display: flex; flex-wrap: wrap; gap: 8px 16px; align-items: center; justify-content: space-between; margin-bottom: 10px; }
.dp-raster-kopf h2 { margin: 0; }
.dp-rasterlegende { display: flex; flex-wrap: wrap; gap: 6px 10px; align-items: center; margin: 0; font-size: 12px; color: var(--oh-text-leise); }
.dp-tipp { flex-basis: 100%; }
.dp-raster-huelle { overflow: auto; max-height: 78vh; border: 1px solid var(--oh-linie); border-radius: var(--r-ui); }
table.dp-raster { border-collapse: separate; border-spacing: 0; width: 100%; min-width: 860px; margin: 0; }
.dp-raster th, .dp-raster td { border-bottom: 1px solid var(--oh-linie); border-right: 1px solid var(--oh-linie); vertical-align: top; padding: 6px; text-align: left; background: var(--oh-flaeche); }
.dp-raster thead th { position: sticky; top: 0; z-index: 3; background: var(--oh-flaeche-2); font-size: 12px; white-space: nowrap; }
.dp-raster thead th small { color: var(--oh-text-leise); font-weight: 600; }
.dp-raster tbody th[scope="row"] { position: sticky; left: 0; z-index: 2; min-width: 120px; font-size: 12.5px; }
.dp-raster tbody th[scope="row"] small { display: block; font-weight: 500; color: var(--oh-text-leise); font-size: 11px; }
.dp-raster .dp-ecke { left: 0; z-index: 4; }
.dp-regionzeile th { background: var(--oh-accent-hauch); color: var(--oh-text); font-size: 11.5px; text-transform: uppercase; letter-spacing: .04em; position: sticky; left: 0; }
.dp-zelle { min-width: 112px; }
.dp-zelle > * + * { margin-top: 4px; }
.dp-zelle[data-dp-zelle] { cursor: context-menu; }
.dp-zelle[data-dp-zelle]:focus-visible, .dp-karte[data-dp-karte]:focus-visible { outline: 2px solid var(--oh-accent); outline-offset: -2px; }
.dp-raster td.dp-zelle--unbesetzt { background: var(--oh-fehler-weich); }
.dp-unbesetzt { margin: 0; font-size: 11.5px; font-weight: 700; color: var(--oh-fehler-text); text-transform: uppercase; letter-spacing: .03em; }

.dp-punkte { display: flex; flex-wrap: wrap; gap: 4px 8px; }
.dp-punkt { display: inline-flex; gap: 2px; align-items: center; }
.dp-punkt i { width: 8px; height: 8px; border-radius: 50%; display: inline-block; }
.dp-punkt i.voll { background: var(--oh-ok); }
.dp-punkt i.leer { border: 2px solid var(--oh-fehler); }
.dp-punkt i.plus { background: var(--oh-warn); }

.dp-karte { border: 1px solid var(--oh-linie); border-radius: 8px; background: var(--oh-flaeche); overflow: hidden; }
.dp-karte p { margin: 0; }
.dp-karte-kopf { background: var(--dp-frueh); color: var(--auf-rot); font-weight: 700; font-size: 10.5px; line-height: 1.3; padding: 3px 6px; font-variant-numeric: tabular-nums; white-space: nowrap; }
.dp-karte-kopf abbr { text-decoration: none; margin-right: 4px; }
.dp-karte--spaet .dp-karte-kopf { background: var(--dp-spaet); }
.dp-karte--ganztag .dp-karte-kopf { background: var(--dp-ganztag); }
.dp-karte--sonder .dp-karte-kopf { background: var(--dp-sonder); }
.dp-karte-rumpf { display: flex; flex-wrap: wrap; gap: 3px; align-items: center; padding: 4px 6px; font-size: 12px; font-weight: 600; }
.dp-karte-fuss { padding: 0 6px 4px; font-size: 11px; color: var(--oh-text-leise); }
.dp-karte abbr.dp-chip { text-decoration: none; }
.dp-chip--planer { background: var(--oh-flaeche); border: 1px dashed var(--oh-linie-stark); }
.dp-abw[data-art="schule"] { background: var(--oh-flaeche-2); border-style: dashed; }
.dp-abw[data-art="abwesend"] { background: var(--oh-flaeche-2); }

.dp-personenraster td { font-size: 11.5px; }
.dp-mini { display: block; border-left: 4px solid var(--dp-frueh); padding: 1px 0 1px 5px; margin-bottom: 2px; font-weight: 600; font-variant-numeric: tabular-nums; white-space: nowrap; }
.dp-mini small { color: var(--oh-text-leise); font-weight: 500; }
.dp-mini--spaet { border-left-color: var(--dp-spaet); }
.dp-mini--ganztag { border-left-color: var(--dp-ganztag); }
.dp-mini--sonder { border-left-color: var(--dp-sonder); }
.dp-soll { white-space: nowrap; font-weight: 700; font-variant-numeric: tabular-nums; }
.dp-soll small { display: block; font-weight: 600; color: var(--oh-text-leise); }
.dp-soll--ueber, .dp-soll--ueber small { color: var(--oh-fehler-text); }
.dp-soll--unter small { color: var(--oh-warn-text); }
.dp-hinweis-klein { font-size: 12px; color: var(--oh-text-leise); }
.dp-anlegen { display: flex; flex-wrap: wrap; gap: 8px 12px; align-items: flex-end; margin-bottom: 12px; }

.dp-menue { position: absolute; z-index: 50; width: 300px; max-width: calc(100vw - 16px); max-height: 70vh; overflow: auto; padding: 8px; background: var(--oh-flaeche); border: 1px solid var(--oh-linie-stark); border-radius: var(--r-ui); box-shadow: var(--dp-menue-schatten); }
.dp-menue-titel { margin: 2px 4px 8px; font-weight: 700; font-size: 13px; }
.dp-menue-warnung { margin: 0 4px 6px; font-size: 12px; color: var(--oh-fehler-text); font-weight: 600; }
.dp-menue-suche { width: 100%; margin-bottom: 6px; }
.dp-menue-eintrag { display: flex; flex-direction: column; align-items: flex-start; width: 100%; text-align: left; padding: 6px 8px; border: 0; border-radius: 6px; background: transparent; color: var(--oh-text); font: inherit; cursor: pointer; box-shadow: none; }
.dp-menue-eintrag:hover, .dp-menue-eintrag:focus-visible { background: var(--oh-hover); outline: none; }
.dp-menue-eintrag.warnt .dp-menue-hinweis { color: var(--oh-fehler-text); }
.dp-menue-text { font-weight: 600; font-size: 13px; }
.dp-menue-hinweis { font-size: 11.5px; color: var(--oh-text-leise); }
.dp-menue-eigen { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; margin: 6px 0; padding-top: 6px; border-top: 1px solid var(--oh-linie); }

@media (max-width: 767px) {
  .dp-raster-huelle { max-height: none; }
  table.dp-raster { min-width: 720px; }
  .dp-raster tbody th[scope="row"] { min-width: 92px; max-width: 110px; }
  .dp-zelle { min-width: 96px; }
  .dp-leiste-woche { min-width: 78px; padding: 5px 8px; }
  .dp-leiste-woche small { display: none; }
  .dp-leiste-woche.on small { display: block; }
  .dp-statuszeile form { width: 100%; }
  .dp-menue { position: fixed; inset: auto 8px 8px 8px; width: auto; }
}

/* Etappe 22b (07.10.2026): Vertragserfassung mobil – eine Spalte, große Bedienflächen. */
.vertrieb-mobil .vertrieb-auswahl select,
.vertrieb-mobil form input[type="text"],
.vertrieb-mobil form input[type="tel"],
.vertrieb-mobil form select { width: 100%; min-height: 44px; font-size: 16px; }
.vertrieb-mobil .vertrieb-option { display: block; padding: 8px 0; }
.vertrieb-mobil .knopf { width: 100%; min-height: 48px; }
/* Etappe 29b (20.10.2026): Warenkorb – Name, Menge/Provision und Aktionen in einer Zeile. */
.warenkorb-liste { list-style: none; margin: 0 0 10px; padding: 0; }
.warenkorb-liste > li { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 12px; padding: 8px 0; border-bottom: 1px solid var(--oh-linie); }
.warenkorb-liste > li:last-child { border-bottom: 0; }
.warenkorb-name { flex: 1 1 240px; min-width: 0; }
.warenkorb-provision { font-variant-numeric: tabular-nums; white-space: nowrap; }
.warenkorb-aktion { display: inline-flex; gap: 6px; margin-left: auto; }
/* ---------- Erscheinungsbild (Etappe 21a, 07.10.2026) ----------
   Seite /verwaltung/erscheinungsbild. Der Vorschaukasten [data-akzent-vorschau] bekommt seine
   Akzent-Tokens aus vorschau-rrggbb.css (ohne JS) bzw. per style.setProperty (mit JS); alle
   Farben hier sind Tokens und werden deshalb im Kasten mit der Vorschaufarbe gerechnet.
   Farbtupfer sind SVG-Rechtecke mit fill (CSP, kein style=""). */
.eb-raster { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 16px; align-items: start; }
.eb-aktuell { display: inline-flex; align-items: center; gap: 6px; margin: 0; font-size: 12.5px; color: var(--oh-text-leise); }
.eb-tupfer { width: 16px; height: 16px; flex: none; vertical-align: -3px; margin-right: 6px; }
.eb-aktuell .eb-tupfer { margin-right: 0; }
.eb-felder { display: flex; flex-wrap: wrap; gap: 10px 12px; align-items: flex-end; }
.eb-felder label { display: flex; flex-direction: column; gap: 4px; font-size: 12.5px; font-weight: 600; color: var(--oh-text-2); }
.eb-felder input[type="color"] { width: 64px; height: 38px; padding: 2px; border: 1px solid var(--oh-linie-stark); border-radius: var(--r-ui); background: var(--oh-flaeche); cursor: pointer; }
.eb-felder input[name="hex"] { width: 120px; font-family: var(--font-mono); }
.eb-vorschlaege { display: flex; flex-wrap: wrap; gap: 6px; margin: 14px 0 0; padding: 0; border: 0; }
.eb-vorschlaege legend { padding: 0; margin-bottom: 6px; font-size: 12.5px; font-weight: 600; color: var(--oh-text-2); }
.eb-vorschlag { display: inline-flex; align-items: center; }
.eb-vorschlag[aria-pressed="true"] { box-shadow: 0 0 0 2px var(--oh-accent-ring), inset 0 0 0 1px var(--oh-accent); }
.eb-befund { margin-top: 14px; }
.eb-befund [data-eb-meldung] { margin: 0 0 8px; padding: 9px 12px; border-radius: var(--r-ui); background: var(--oh-fehler-weich); color: var(--oh-fehler-text); font-weight: 600; }
.eb-ok { display: flex; align-items: center; margin: 0 0 8px; color: var(--oh-ok-text); font-weight: 600; }
.eb-vorschlag-zeile { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; margin: 0 0 8px; }
.eb-vorschlag-zeile button { display: inline-flex; align-items: center; }
.eb-werte { display: grid; gap: 4px; margin: 8px 0 14px; font-size: 13px; }
.eb-werte > div { display: flex; flex-wrap: wrap; gap: 4px 10px; }
.eb-werte dt { min-width: 190px; color: var(--oh-text-leise); }
.eb-werte dd { margin: 0; }
.eb-vorschau { border-radius: var(--r-karte); overflow: hidden; border: 1px solid var(--oh-linie); background: var(--oh-hover); }
.eb-kopf { padding: 16px 18px 14px; background: var(--aurora), var(--page-bg); color: var(--auf-rot); }
.eb-kopf-titel { margin: 0; font-size: 19px; font-weight: 800; letter-spacing: -.015em; }
.eb-kopf-bereich { margin: 2px 0 10px; font-size: 11.5px; font-weight: 600; color: var(--auf-rot-leise); }
.eb-pillen { display: flex; flex-wrap: wrap; gap: 6px; margin: 0; }
.eb-pille { padding: 3px 10px; border-radius: 999px; border: 1px solid var(--auf-rot-pille-rand); color: var(--auf-rot-pille-text); font-size: 12px; font-weight: 600; }
.eb-pille-an { background: var(--oh-flaeche); border-color: var(--oh-flaeche); color: var(--oh-accent-dunkel); }
.eb-flaeche { display: grid; grid-template-columns: 150px minmax(0, 1fr); gap: 12px; padding: 14px; }
/* Sichtpruefung 09.10.2026: Bei zwei Spalten im Raster ist die Vorschau nur ~330 px breit;
   neben der 150-px-Navigation blieb der Karte zu wenig Platz, „Speichern“ lief rechts aus der
   Karte. Darum richtet sich die Vorschau nach ihrer eigenen Breite, nicht nach dem Fenster. */
.eb-vorschau { container-type: inline-size; }
@container (max-width: 460px) {
  .eb-flaeche { grid-template-columns: minmax(0, 1fr); }
}
.eb-nav { list-style: none; margin: 0; padding: 6px; border-radius: var(--r-ui); background: var(--oh-flaeche); }
.eb-nav-punkt { position: relative; padding: 7px 10px; border-radius: 7px; font-size: 13px; color: var(--oh-text-2); }
.eb-nav-aktiv { background: var(--oh-accent-weich); color: var(--oh-accent-dunkel); font-weight: 650; }
.eb-nav-aktiv::before { content: ""; position: absolute; left: 0; top: 7px; bottom: 7px; width: 3px; border-radius: 3px; background: var(--oh-accent); }
.eb-karte { padding: 12px 14px; border: 1px solid transparent; border-radius: var(--r-karte); background: linear-gradient(var(--oh-flaeche), var(--oh-flaeche)) padding-box, var(--edge) border-box; box-shadow: var(--schatten); font-size: 13.5px; }
.eb-karte p { margin: 0 0 8px; }
.eb-karte p:last-child { margin-bottom: 0; }
.eb-link { color: var(--oh-accent-dunkel); font-weight: 550; text-decoration: underline; text-underline-offset: 2px; }
.eb-knoepfe { display: flex; flex-wrap: wrap; gap: 8px; }
/* Etappe 21d (09.10.2026): Karte „Firmenlogo“ ueber die volle Breite unter Akzentfarbe und
   Vorschau; links Auswahl und Regeln, rechts „So wirkt es“ (Kachel auf der gespeicherten
   Akzentflaeche und auf Weiss, wie Seitenleiste und Anmeldeseite). */
.eb-logo { grid-column: 1 / -1; }
.eb-logo-raster { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 16px 24px; align-items: start; }
.eb-logo-wahl { display: grid; gap: 10px; justify-items: start; padding: 14px; border: 2px dashed var(--oh-linie-stark); border-radius: var(--r-karte); }
.eb-logo-wahl input[type="file"] { max-width: 100%; font-size: 13px; }
.eb-logo-knoepfe { display: flex; flex-wrap: wrap; gap: 8px; margin: 10px 0 0; }
.eb-logo-knoepfe form { margin: 0; }
.eb-regeln { margin: 12px 0 0; padding-left: 18px; display: grid; gap: 3px; font-size: 13px; color: var(--oh-text-leise); }
.eb-logo-stand { margin: 0 0 10px; font-size: 13px; font-weight: 600; }
.eb-logo-stand.pruefung { color: var(--oh-warn-text); }
.eb-logo-stand.abgelehnt { color: var(--oh-fehler-text); }
.eb-logo-stand.ok { color: var(--oh-ok-text); }
.eb-logo-probe { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 10px; }
.eb-logo-probe figure { margin: 0; display: grid; gap: 4px; }
.eb-logo-probe figcaption { font-size: 11.5px; color: var(--oh-text-leise); text-align: center; }
.eb-logo-akzent { display: grid; place-items: center; min-height: 64px; padding: 12px; border-radius: var(--r-ui); background: linear-gradient(160deg, var(--oh-accent), var(--oh-accent-tief)); }
.eb-logo-akzent .marke-logo { flex: none; margin: 0; width: 100%; }
.eb-logo-weiss { display: grid; place-items: center; min-height: 64px; padding: 12px; border-radius: var(--r-ui); background: var(--logo-kachel); border: 1px solid var(--oh-linie); }
.eb-logo-weiss img { display: block; width: auto; height: auto; max-height: 40px; max-width: 100%; object-fit: contain; }
.eb-logo-leer { margin: 0; font-size: 13px; color: var(--oh-text-leise); }
@media (max-width: 960px) {
  .eb-raster { grid-template-columns: minmax(0, 1fr); }
  .eb-logo-raster { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 520px) {
  .eb-flaeche { grid-template-columns: minmax(0, 1fr); }
  .eb-werte dt { min-width: 0; flex-basis: 100%; }
}

/* Etappe 22c/22d (08.10.2026): Meine Verträge als Karten, Verlauf und Zahlen – auf dem Telefon
   ohne Querscrollen. */
.vertrieb-karten { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; }
.vertrieb-karten > li { margin: 0; }
.vertrieb-karten p { margin: 4px 0 0; }
.vertrieb-verlauf { list-style: none; margin: 0; padding: 0; }
.vertrieb-verlauf > li { padding: 8px 0; border-bottom: 1px solid var(--oh-linie); }
.vertrieb-verlauf > li:last-child { border-bottom: 0; }
@media (max-width: 640px) {
  .vertrieb-karten .knopf, .vertrieb-aktion .knopf { width: 100%; min-height: 44px; }
}

/* ---------- Persönliches Dashboard (Etappe 23, 09.10.2026, ADR-0045) ----------
   Raster aus Kacheln in drei Größen: klein = 1 Spalte, breit = 2, groß = 2 Spalten × 2 Zeilen.
   Vier Spalten am Desktop, zwei bis 1000 px, eine unter 760 px (375 px ohne Querscrollen).
   Farben je Kachel: weiß (Standard), rot = Akzent des Mandanten mit feiner weißer Innenlinie
   (Pillen neutral weiß, damit Rot nie wie `data-zustand=fehler` wirkt), schwarz = Textton.
   Balken sind SVG mit width-Attribut – kein Inline-Style (CSP). */
.dash { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); grid-auto-flow: row dense; gap: 12px; margin-bottom: 12px; }
.dash-leiste { display: flex; align-items: center; justify-content: space-between; gap: 8px 12px; flex-wrap: wrap; margin: 0 0 10px; }
.dash-leiste > :only-child { margin-left: auto; }
.dash-leiste p { margin: 0; }
.dk {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
  margin: 0;
  padding: 15px 18px;
  border-radius: var(--r-karte);
  border: 1px solid transparent;
  background: linear-gradient(var(--oh-flaeche), var(--oh-flaeche)) padding-box, var(--edge) border-box;
  box-shadow: var(--schatten);
  color: var(--oh-text);
}
.dk-klein { grid-column: span 1; }
.dk-breit { grid-column: span 2; }
.dk-gross { grid-column: span 2; grid-row: span 2; }
.dk-kopf { display: flex; align-items: baseline; gap: 6px; flex-wrap: wrap; }
.dk-kopf h2 { font-size: 11.5px; font-weight: 650; color: var(--oh-text-leise); margin: 0 auto 0 0; letter-spacing: 0; }
.dk-zeichen { font-size: 10.5px; font-weight: 600; color: var(--oh-text-leise); border: 1px solid var(--oh-linie); border-radius: 999px; padding: 0 7px; white-space: nowrap; }
.dk-wert { font-size: clamp(22px, 3.2vw, 26px); font-weight: 650; letter-spacing: -.4px; line-height: 1.15; margin: 2px 0 0; font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
.dk-wert.text { font-size: 16px; letter-spacing: -.2px; line-height: 1.3; }
.dk-leise { font-size: 12px; color: var(--oh-text-leise); margin: 2px 0 0; }
.dk-label { font-size: 11.5px; font-weight: 600; color: var(--oh-text-leise); display: block; }
.dk-link { margin-top: auto; padding-top: 6px; font-size: 12.5px; font-weight: 600; color: var(--oh-accent-dunkel); }
.dk-zahlen { display: grid; grid-template-columns: repeat(auto-fit, minmax(110px, 1fr)); gap: 8px; margin: 6px 0; }
.dk-zahlen .dk-wert { font-size: 20px; display: block; }
.dk-woche { margin-top: 6px; }
.dk-reihen { list-style: none; margin: 6px 0 0; padding: 0; display: grid; gap: 8px; }
.dk-reihen li { margin: 0; }
.dk-reihe-kopf { display: flex; justify-content: space-between; gap: 8px; font-size: 12.5px; }
.dk-reihe-kopf b { font-weight: 650; font-variant-numeric: tabular-nums; white-space: nowrap; }
.dk-balken { display: block; width: 100%; height: 6px; margin-top: 4px; }
.dk-balken .spur { fill: var(--oh-flaeche-2); }
.dk-balken .fuell { fill: var(--oh-text-leise); }
.dk-reihen li.erreicht .fuell { fill: var(--oh-ok); }

.dk-rot { background: var(--oh-accent); border-color: var(--oh-accent); box-shadow: var(--schatten), inset 0 0 0 1px var(--auf-rot-rand); color: var(--auf-rot); }
.dk-schwarz { background: var(--oh-text); border-color: var(--oh-text); color: var(--oh-weiss); }
.dk-rot .dk-kopf h2, .dk-rot .dk-leise, .dk-rot .dk-label, .dk-rot .klein,
.dk-schwarz .dk-kopf h2, .dk-schwarz .dk-leise, .dk-schwarz .dk-label, .dk-schwarz .klein { color: var(--auf-rot-leise); }
.dk-rot .dk-zeichen, .dk-schwarz .dk-zeichen { color: var(--auf-rot-pille-text); border-color: var(--auf-rot-pille-rand); }
.dk-rot .dk-link, .dk-schwarz .dk-link { color: var(--auf-rot); }
.dk-rot .pille, .dk-schwarz .pille { background: var(--auf-rot-flaeche); color: var(--auf-rot); }
.dk-rot .dk-balken .spur, .dk-schwarz .dk-balken .spur { fill: var(--auf-rot-flaeche); }
.dk-rot .dk-balken .fuell, .dk-schwarz .dk-balken .fuell { fill: var(--auf-rot); }
.dk-rot .liste li, .dk-schwarz .liste li, .dk-rot .jetzt-liste li, .dk-schwarz .jetzt-liste li { border-color: var(--auf-rot-linie); color: inherit; }
.dk-rot .liste .tag small, .dk-rot .liste .was span, .dk-rot .liste .wann,
.dk-schwarz .liste .tag small, .dk-schwarz .liste .was span, .dk-schwarz .liste .wann { color: var(--auf-rot-leise); }

/* Anordnen */
[data-dashboard] .dk[data-beweglich] { cursor: grab; }
[data-dashboard] .dk:focus-visible { outline: 2px solid var(--oh-accent-ring); outline-offset: 2px; }
.dk.dk-zieht { opacity: .55; }
.dk-werkzeug { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; padding-top: 10px; border-top: 1px dashed var(--oh-linie-stark); }
.dk-werkzeug form { display: flex; flex-wrap: wrap; gap: 4px; margin: 0; }
.dk-werkzeug .gewaehlt { box-shadow: inset 0 0 0 2px var(--oh-accent-ring); }
.dk-farbwahl { width: 30px; min-height: 30px; padding: 0; border-radius: 50%; border: 1px solid var(--oh-linie-stark); box-shadow: none; }
.dk-farbwahl-weiss, .dk-farbwahl-weiss:hover { background: var(--oh-weiss); }
.dk-farbwahl-rot, .dk-farbwahl-rot:hover { background: var(--oh-accent); }
.dk-farbwahl-schwarz, .dk-farbwahl-schwarz:hover { background: var(--oh-text); }
.dk-farbwahl.gewaehlt { box-shadow: 0 0 0 2px var(--oh-flaeche), 0 0 0 4px var(--oh-accent-ring); }
.dk-rot .dk-werkzeug, .dk-schwarz .dk-werkzeug { border-color: var(--auf-rot-rand); }
.dash-katalog-liste { list-style: none; margin: 0; padding: 0; }
.dash-katalog-liste li { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 8px 0; border-bottom: 1px solid var(--oh-linie); flex-wrap: wrap; margin: 0; }
.dash-katalog-liste li:last-child { border-bottom: 0; }
.dash-katalog-liste form { margin: 0; }
.dash-katalog h3 { font-size: 13px; margin: 14px 0 4px; }
.dash-katalog-liste.gesperrt b { color: var(--oh-text-leise); }

@media (max-width: 1000px) {
  .dash { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 760px) {
  .dash { grid-template-columns: minmax(0, 1fr); gap: 8px; }
  .dk-klein, .dk-breit, .dk-gross { grid-column: auto; grid-row: auto; }
  .dk-werkzeug button { min-height: 40px; }
  .dk-farbwahl { width: 40px; }
}

/* ===== OnePulse-Cockpit, Etappe 25b (10.10.2026, ADR-0062/0063; Nutzer-Entscheidung 09.10.26).
   Ampelfarben als Alias auf die Zustandstokens (--oh-ok/-warn/-fehler), damit Licht- und
   ein künftiges Dunkel-Thema sie an einer Stelle umfärben; eigene Hexwerte gibt es hier
   bewusst nicht. Leise Werte: nur ein kleiner Punkt vor der Zahl, keine gefärbten Flächen. */
:root {
  --op-ampel-gruen: var(--oh-ok);
  --op-ampel-gruen-text: var(--oh-ok-text);
  --op-ampel-gelb: var(--oh-warn);
  --op-ampel-gelb-text: var(--oh-warn-text);
  --op-ampel-rot: var(--oh-fehler);
  --op-ampel-rot-text: var(--oh-fehler-text);
}
.op-reiter { display: flex; flex-wrap: wrap; gap: 12px; align-items: baseline; margin: 10px 0 12px; }
.op-reiter strong { border-bottom: 2px solid var(--oh-accent); padding-bottom: 2px; }
.op-reiter .op-gruppieren { margin-left: auto; font-size: 13px; }
.op-cockpit th a { color: inherit; text-decoration: none; }
.op-cockpit th a:hover { text-decoration: underline; }
.op-cockpit th[aria-sort] a::after { content: " ↕"; color: var(--oh-text-leise); }
.op-cockpit th[aria-sort="descending"] a::after { content: " ↓"; color: inherit; }
.op-cockpit th[aria-sort="ascending"] a::after { content: " ↑"; color: inherit; }
.op-punkt { display: inline-block; width: 8px; height: 8px; border-radius: 50%; vertical-align: baseline; }
td[data-ampel="gruen"] .op-punkt { background: var(--op-ampel-gruen); }
td[data-ampel="gelb"] .op-punkt { background: var(--op-ampel-gelb); }
td[data-ampel="rot"] .op-punkt { background: var(--op-ampel-rot); }
td[data-ampel="rot"] { color: var(--op-ampel-rot-text); font-weight: 650; }
/* Trendpfeil: Farbe folgt der Lage (Richtung der Kennzahl), nicht dem Vorzeichen. */
.op-trend { font-size: 11.5px; white-space: nowrap; color: var(--oh-text-leise); }
.op-trend-besser { color: var(--op-ampel-gruen-text); }
.op-trend-schlechter { color: var(--op-ampel-rot-text); }
.op-auf { background: none; border: 0; padding: 0; margin: 0; font: inherit; color: inherit; cursor: pointer; text-align: left; box-shadow: none; min-height: 0; }
.op-auf:hover { text-decoration: underline; }
.op-auf[aria-expanded="true"]::after { content: " ▾"; color: var(--oh-text-leise); }
.op-auf[aria-expanded="false"]::after { content: " ▸"; color: var(--oh-text-leise); }
.op-chip { display: inline-block; margin-left: 6px; padding: 1px 7px; border-radius: 999px; font-size: 10.5px; letter-spacing: .03em; text-transform: uppercase; background: var(--oh-flaeche-leise, var(--oh-linie)); color: var(--oh-text-leise); }
tr.op-ausgeschieden > td { color: var(--oh-text-leise); }
tr.op-gruppe th { background: none; font-size: 12px; letter-spacing: .04em; text-transform: uppercase; color: var(--oh-text-leise); padding-top: 14px; }
tr.op-zwischensumme th, tr.op-zwischensumme td { font-weight: 650; border-bottom: 1px solid var(--oh-linie-stark); }
tr.op-durchschnitt th, tr.op-durchschnitt td { color: var(--oh-text-leise); }
.op-detail > td { background: var(--oh-flaeche); }
.op-kacheln { display: grid; grid-template-columns: repeat(auto-fill, minmax(170px, 1fr)); gap: 8px; padding: 6px 0; }
.op-kachel { display: grid; gap: 2px; border: 1px solid var(--oh-linie); border-radius: var(--r-ui); padding: 8px 10px; font-size: 12.5px; }
.op-kachel strong { font-size: 12px; }
.op-kachel span { color: var(--oh-text-leise); }

/* Unter 700px: Karten statt Tabelle (Nutzer-Entscheidung 09.10.26) – kein waagerechter
   Rollbalken, 16px Seitenrand; jede Zelle beschriftet sich über data-k. */
@media (max-width: 700px) {
  .op-cockpit { display: block; border: 0; }
  .op-cockpit thead { display: none; }
  .op-cockpit tbody, .op-cockpit tfoot { display: block; }
  .op-cockpit tr { display: block; border: 1px solid var(--oh-linie); border-radius: var(--r-ui); margin: 0 0 10px; padding: 8px 16px; }
  .op-cockpit tr.op-gruppe { border: 0; padding: 4px 0 0; margin: 0; }
  .op-cockpit tr.op-detail { margin-top: -10px; border-top: 0; border-top-left-radius: 0; border-top-right-radius: 0; }
  .op-cockpit th, .op-cockpit td { display: flex; justify-content: space-between; gap: 10px; border: 0; padding: 3px 0; text-align: left; }
  .op-cockpit td[data-k]:not([data-k=""])::before { content: attr(data-k); color: var(--oh-text-leise); font-size: 12px; }
  .op-cockpit td svg { display: none; }
  .op-cockpit .op-detail > td { display: block; }
}

/* ================= Optik-Scheibe 1 (17.10.2026): Schnellgewinne =================
   Visuelle Gap-Analyse: OnePOS ist farb-, schrift- und rastermäßig nah an OneHome, wirkt
   aber „dünner“. Diese Scheibe hebt vorhandene Bausteine an – nur CSS, keine Vorlagen –,
   damit es sofort auf allen Seiten wirkt. Alle Farben sind Tokens bzw. Ableitungen; kein
   neuer Farbwert, kein Inline-Style, keine Einbindung fremder Dateien, keine externe URL,
   kein Dunkelmodus. */

/* Kategorie-Pillen (Vertragsart): OneHomes `.chip-*` als Token-Fassung der `.pille`.
   Farben ausschließlich aus der Kernpalette – die weiche Fläche plus die AA-Stufe derselben
   Farbe (`--oh-*-text`), wie bei `.pille.ok/.warn/.gut/.fehler`. Vorlagen werden später von
   den bisherigen ad-hoc-Klassen hierauf umgestellt; jetzt stehen die Klassen nur bereit. */
.pille.kredit    { background: var(--oh-accent-weich); color: var(--oh-accent-dunkel); }
.pille.vvl       { background: var(--oh-gut-weich); color: var(--oh-gut-text); }
.pille.breitband { background: var(--oh-fehler-weich); color: var(--oh-fehler-text); }
.pille.tv        { background: var(--oh-warn-weich); color: var(--oh-warn-text); }
.pille.winback   { background: var(--oh-ok-weich); color: var(--oh-ok-text); }
.pille.neutral   { background: var(--oh-flaeche-2); color: var(--oh-text-2); }

/* Info-Chip: kleines „i“ neben einer Beschriftung, Tooltip über das `title`-Attribut.
   Leer lassen (<span class="kachel-info" title="…"></span>), das Zeichen kommt aus ::before;
   Farbe/Hover nur aus Tokens, `cursor: help` macht die Bedeutung sichtbar. */
.kachel-info {
  display: inline-flex; align-items: center; justify-content: center;
  width: 16px; height: 16px; flex: none;
  border-radius: 50%; border: 1px solid var(--oh-linie);
  background: var(--oh-flaeche-2); color: var(--oh-text-2);
  font-size: 11px; font-weight: 700; line-height: 1;
  vertical-align: 1px; cursor: help;
}
.kachel-info::before { content: "i"; }
.kachel-info:hover { background: var(--oh-accent-weich); border-color: var(--oh-accent-ring); color: var(--oh-accent-dunkel); }

/* Inline-Bearbeiten: OneHomes `.edit-details` als Token-Fassung. Ein `<details>` klappt die
   Bearbeitung im Satz auf; `.edit-box` ist die Fläche darin. Nichts umbenannt – nur ergänzt. */
.edit-details { margin-top: 10px; }
.edit-details > summary { cursor: pointer; color: var(--oh-accent-dunkel); font-weight: 600; font-size: 13px; list-style: none; }
.edit-details > summary::-webkit-details-marker { display: none; }
.edit-details > summary:hover { color: var(--oh-text); }
.edit-box { margin-top: 10px; padding: 12px; border: 1px solid var(--oh-linie); border-radius: var(--r-ui); background: var(--oh-flaeche-2); }

/* ================= Optik-Scheibe 2 (17.10.2026): die großen Hebel =================
   Zweite Runde nach der visuellen Gap-Analyse (Scheibe 1 = Schnellgewinne, oben). Rein
   additiv: kein bestehender Selektor wird umbenannt oder entfernt, jede Farbe ist ein
   `--oh-*`-Token oder eine color-mix()-Ableitung daraus, kein Inline-Style, keine externe
   Datei, kein Dunkelmodus. Die Aurora-Bewegung steht oben bei der Bühne, weil sie dort
   hingehört; hier folgen Formularbausteine, einklappbare Seitenleiste, Toast und die
   weiche Aktiv-Pille. */

/* ---------- 1. Formularbausteine ----------
   OnePOS benutzte bisher nackte Felder; die Feldoptik kam allein aus den Elementselektoren
   oben (`label`, `input`, `select`, `textarea`). Diese Klassen setzen genau darauf auf – sie
   gruppieren und beschriften, sie gestalten das Feld nicht neu. Nichts muss umgestellt
   werden; neue Vorlagen können sie einzeln verwenden. */
.feld { display: block; margin: 0 0 12px; max-width: 360px; min-width: 0; }
/* `.feld-label` ist eine eigenständige Beschriftung (mit `for=`) über dem Feld,
   `.feld-hinweis` die leise Hilfe darunter, `.feld-fehler` die Fehlermeldung in der festen
   Fehlerfarbe (auf Weiß 5,9:1). */
.feld-label { display: block; margin: 0 0 5px; max-width: none; font-size: 12.5px; font-weight: 600; color: var(--oh-text-2); }
.feld-hinweis { display: block; margin: 4px 0 0; font-size: 12px; color: var(--oh-text-leise); }
.feld-fehler { display: block; margin: 4px 0 0; font-size: 12px; font-weight: 600; color: var(--oh-fehler-text); }
.feld > input:not([type="checkbox"]):not([type="radio"]):not([type="hidden"]),
.feld > select,
.feld > textarea { width: 100%; }
/* Mehrspaltig: so viele Spalten wie ab 220 px hineinpassen – unter 760 px also genau eine. */
.feld-raster { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 4px 16px; align-items: start; margin-bottom: 4px; }
.feld-raster > .feld { max-width: none; }
/* Fehlerzustand am Feld selbst (deutsch `.eingabe.fehler`, englisch `.input.is-error`) und
   barrierefrei über `aria-invalid` – dieselbe feste Fehlerfarbe wie `.pille.fehler`. */
.eingabe, .input { max-width: 100%; }
.eingabe.fehler, .input.is-error, [aria-invalid="true"] { border-color: var(--oh-fehler); box-shadow: 0 0 0 3px var(--oh-fehler-weich); }
/* Klickbare Optionszeilen (Radiogruppe, Mehrfachauswahl): die ganze Zeile ist die Fläche,
   der Auswahlzustand kommt aus dem Feld selbst (`:has`), nicht aus einer zweiten Klasse. */
.optionen { display: grid; gap: 6px; margin: 0 0 12px; padding: 0; border: 0; }
.optionen > label.option {
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 10px;
  max-width: none;
  margin: 0;
  padding: 9px 12px;
  border: 1px solid var(--oh-linie-stark);
  border-radius: var(--r-ui);
  background: var(--oh-flaeche);
  font-size: 13.5px;
  font-weight: 500;
  cursor: pointer;
  transition: background-color .14s ease, border-color .14s ease;
}
.optionen > label.option:hover { background: var(--oh-hover); }
.optionen > label.option:has(input:checked) { border-color: var(--oh-accent); background: var(--oh-accent-weich); box-shadow: inset 0 0 0 1px var(--oh-accent); }
.optionen > label.option:has(input:focus-visible) { outline: 2px solid var(--oh-accent); outline-offset: 2px; }

/* ---------- 2. Seitenleiste einklappen ----------
   OneHome kann die Seitenleiste auf eine 68-px-Symbolspalte verkleinern (`html.vfa-schmal`,
   header.php). Dieselbe Mechanik hier: die Klasse steht am `<html>` und tauscht nur
   `--leiste-breite`; die Breite selbst kommt unverändert aus dem Raster `body.mit-shell`.
   Gültig nur ab 1000 px – darunter ist die Leiste ohnehin eine Schublade hinter dem Burger,
   in der es nichts zu spalten gibt. Den Zustand merkt `public/js/leiste.js` in
   `localStorage`; ohne JavaScript bleibt die Leiste offen (der Umschalter ist dann `hidden`),
   es gibt also immer einen Rückfall. */
.leiste-umschalter {
  display: none;                 /* JS entfernt [hidden]; unter 1000 px bleibt er unsichtbar */
  align-items: center;
  gap: 8px;
  width: 100%;
  min-height: 34px;
  margin: 0 0 8px;
  padding: 7px 10px;
  font-size: 12.5px;
  font-weight: 600;
  border: 1px solid var(--oh-seitenlinie);
  border-radius: var(--r-ui);
  background: var(--oh-flaeche);
  color: var(--oh-text-2);
  box-shadow: none;
}
.leiste-umschalter:hover { background: var(--oh-hover); }
.leiste-umschalter svg.sym { flex: none; }
@media (min-width: 1000px) {
  .leiste-umschalter { display: flex; }
  body.mit-shell { transition: grid-template-columns .18s ease; }
  /* Ab hier die eingeklappte Fassung. */
  html.leiste-schmal { --leiste-breite: 68px; }
  html.leiste-schmal .seitenleiste { padding-left: 8px; padding-right: 8px; overflow-x: hidden; }
  /* Beschriftungen verschwinden über `font-size: 0` statt `display: none`: der Text bleibt
     im Baum und damit der Name des Links für Vorleser erhalten, den Hover-Titel setzt
     leiste.js. Die Symbole behalten ihre feste Größe und werden zentriert; die Zähler
     (`--nav-zahl` mit eigener Schriftgröße) werden ausdrücklich ausgeblendet. */
  html.leiste-schmal .leiste-nav a { font-size: 0; justify-content: center; gap: 0; padding: 8px 0; }
  html.leiste-schmal .leiste-nav a svg.sym { flex: 0 0 20px; width: 20px; height: 20px; }
  html.leiste-schmal .leiste-nav .nav-zahl { display: none; }
  /* Gruppentitel werden zur Trennlinie – die Ordnung bleibt sichtbar, der Text kann es nicht
     (wie OneHomes `.vfa-grp`). Die Titel selbst verschwinden ganz, sonst bliebe eine 1-px-
     Klickfläche, die eine Gruppe zuklappen und damit Links verschwinden ließe; leiste.js
     klappt die Gruppen im schmalen Zustand auf. */
  html.leiste-schmal .leiste-nav .nav-titel { visibility: hidden; height: 0; margin: 0; padding: 0; overflow: hidden; }
  html.leiste-schmal .leiste-nav details.nav-gruppe { border-top: 1px solid var(--oh-seitenlinie); margin-top: 8px; padding-top: 6px; }
  /* Marke: nur Zeichen und (falls vorhanden) das Firmenlogo auf kleiner Kachel. */
  html.leiste-schmal .leiste-marke { justify-content: center; padding: 10px 6px; }
  html.leiste-schmal .leiste-marke .marke-wort,
  html.leiste-schmal .leiste-marke .marke-trenner,
  html.leiste-schmal .leiste-marke .marke-mandant,
  html.leiste-schmal .leiste-marke .marke-demo-pille { display: none; }
  html.leiste-schmal .leiste-marke .marke-logo { padding: 4px; min-height: 30px; }
  html.leiste-schmal .leiste-marke .marke-logo img { max-height: 22px; }
  /* Fuß: nur das Kürzel. „Sicherheit“ und „Meine Daten“ stehen weiter im Konto-Menü der
     Kopfleiste, sie sind also nicht verloren. */
  html.leiste-schmal .leiste-fuss { padding: 10px 0 0; }
  html.leiste-schmal .leiste-fuss .wer { justify-content: center; }
  html.leiste-schmal .leiste-fuss .wer > div { display: none; }
  html.leiste-schmal .leiste-fuss nav { display: none; }
  /* Umschalter im schmalen Zustand: nur das Symbol, der Text bleibt als Name erhalten. */
  html.leiste-schmal .leiste-umschalter { justify-content: center; gap: 0; padding: 7px 0; }
  html.leiste-schmal .leiste-umschalter .leiste-umschalter-text { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; }
}

/* ---------- 3. Toast (kurze Einblendung) ----------
   OneHomes `.vffeier-toast` als Token-Fassung: dunkle Fläche unten in der Mitte, die von
   selbst wieder verschwindet. Keine Vorlage muss etwas tun; wer eine Einblendung will, setzt
   `data-toast` an ein Element (public/js/toast.js holt es in den Bereich und blendet es ein
   und aus) oder rendert `.toast` direkt in einem `.toast-bereich`. Fläche `--oh-text` mit
   weißer Schrift (17:1), die linke Kante trägt den Zustand; `aria-live="polite"` setzt das
   Skript am Bereich. */
.toast-bereich {
  position: fixed;
  left: 50%;
  bottom: calc(20px + env(safe-area-inset-bottom, 0px));
  transform: translateX(-50%);
  z-index: 60;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  width: max-content;
  max-width: min(92vw, 440px);
  pointer-events: none;
}
.toast {
  pointer-events: auto;
  margin: 0;
  padding: 10px 15px;
  border: 1px solid transparent;
  border-left-width: 3px;
  border-left-color: var(--auf-rot-pille-rand);
  border-radius: var(--r-ui);
  background: var(--oh-text);
  color: var(--oh-weiss);
  box-shadow: var(--schatten-menue);
  font-size: 13.5px;
  font-weight: 550;
  line-height: 1.35;
  text-align: left;
  opacity: 0;
  transform: translateY(10px);
  transition: opacity .22s ease, transform .22s ease;
}
.toast.sichtbar { opacity: 1; transform: none; }
.toast-erfolg { border-left-color: var(--oh-ok); }
.toast-warn { border-left-color: var(--oh-warn); }
.toast-fehler { border-left-color: var(--oh-fehler); }
.toast a { color: var(--oh-weiss); text-decoration: underline; text-underline-offset: 2px; }
@media (max-width: 760px) {
  /* Über der festen Tableiste, sonst läge der Toast darunter. */
  .toast-bereich { bottom: calc(var(--tableiste-hoehe) + 16px + env(safe-area-inset-bottom, 0px)); max-width: 94vw; }
}

/* Bewegung aus, wenn das Betriebssystem es verlangt: keine Aurora (steht oben bei der Bühne),
   keine weichen Übergänge, kein Ein-/Ausblenden. Die Endzustände bleiben sichtbar. */
@media (prefers-reduced-motion: reduce) {
  body.mit-shell { transition: none; }
  .leiste-umschalter, .optionen > label.option { transition: none; }
  .vfp { transition: none; }
  .toast { transition: none; }
  /* Optik-Scheibe 4: die Diagramme bewegen sich nicht von selbst; der Wächter bleibt
     trotzdem stehen, damit ein späterer Übergang (Hover) hier zentral abschaltbar ist. */
  .oh-diagramm, .oh-diagramm *, .kpi-zelle { transition: none; animation: none; }
}

/* ================= Optik-Scheibe 4 (18.10.2026): Datenvisualisierung =================
   Wiederverwendbare SVG-Bausteine (templates/_bausteine/diagramme.html.twig) und ein
   KPI-Raster für Kennzahl-Kacheln. Wie Scheibe 1–3 rein additiv: jede Farbe ist ein
   `--oh-*`-Token oder `currentColor`, kein Inline-Style, keine externe Datei, kein
   Dunkelmodus. Die Geometrie kommt aus den Makro-Parametern, die Farbe nur von hier –
   damit ein künftiges Dunkel-Thema sie an einer Stelle umfärben kann.

   `.oh-balken-soll` ist der leise Sollwert (dieselbe Blassstufe wie kleine Schrift, als
   Grafik zulässig), `.oh-balken-ist` und die Reihe folgen der Textfarbe (`currentColor`),
   damit sie in farbigen Kacheln (`.dk-rot`/`.dk-schwarz`) mitkippen. Der Ringwert steht
   ebenfalls in `currentColor`, die Spur ist die Flächenstufe wie beim `.dk-balken`. */
.oh-diagramm { display: block; max-width: 100%; }
.oh-balken-soll { fill: var(--oh-text-blass); }
.oh-balken-ist { fill: currentColor; }
.oh-ring-spur { stroke: var(--oh-flaeche-2); }
.oh-ring-wert { stroke: currentColor; }
.oh-ring-text { fill: var(--oh-text); font-size: 20px; font-weight: 650; font-variant-numeric: tabular-nums; }
.oh-balken-reihe { fill: currentColor; }
.oh-verlauf-linie { stroke: currentColor; stroke-width: 2px; vector-effect: non-scaling-stroke; }

/* Kennzahl-Kacheln (KPI-Raster): OneHomes `.stat-*` als Token-Fassung. `.kpi-zelle` ist
   die weiße Kachel, `.kpi-wert` die große Zahl, `.kpi-label`/`.kpi-notiz` die leisen
   Beschriftungen; ein Diagramm darin sitzt über `margin-top: auto` am unteren Rand. */
.kpi-raster { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 10px; margin: 0 0 14px; }
.kpi-zelle { display: flex; flex-direction: column; gap: 4px; min-width: 0; padding: 10px 12px; border: 1px solid var(--oh-linie); border-radius: var(--r-ui); background: var(--oh-flaeche); }
.kpi-label { font-size: 12px; font-weight: 600; color: var(--oh-text-leise); }
.kpi-wert { font-size: 22px; font-weight: 650; letter-spacing: -.4px; line-height: 1.15; font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
.kpi-notiz { font-size: 12px; color: var(--oh-text-leise); }
.kpi-zelle .oh-diagramm { margin-top: auto; }

/* Im aufgeklappten OnePulse-Detail bleibt das Diagramm auch unter 700 px sichtbar: die
   Regel `.op-cockpit td svg { display: none }` gilt der Zellminiatur, nicht dem Baustein. */
.op-cockpit .op-detail svg.oh-diagramm { display: block; }
.op-kachel .oh-diagramm { margin-top: 4px; }

@media (max-width: 760px) {
  .kpi-raster { grid-template-columns: repeat(auto-fit, minmax(130px, 1fr)); gap: 8px; }
}

/* ================= Optik-Scheibe 5b (18.10.2026): globale Suche (Strg-K) =================
   OneHomes Strg-K-Palette als Token-Fassung. Rein additiv wie Scheibe 1–4: kein bestehender
   Selektor wird umbenannt oder entfernt, jede Farbe ist ein `--oh-*`-Token oder eine
   Ableitung daraus, kein Inline-Style, keine externe Datei, kein Dunkelmodus. Markup:
   templates/_bausteine/suche.html.twig, Verhalten: public/js/suche.js.

   Ohne JavaScript bleibt alles unsichtbar: der Knopf in der Kopfleiste steht `hidden` im
   Markup, das Overlay ebenso. Deshalb die ausdrücklichen `[hidden]`-Regeln – `.kopf-suche`
   und `.suche-eintrag` setzen `display: flex`, das die Vorgabe des Browsers für `hidden`
   sonst überschriebe. */

/* ---------- Knopf in der Kopfleiste (neben Glocke und Konto) ---------- */
.kopf-suche {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: none;
  min-height: 32px;
  padding: 5px 9px;
  border: 1px solid var(--oh-linie-stark);
  border-radius: var(--r-ui);
  background: var(--oh-flaeche);
  color: var(--oh-text-leise);
  box-shadow: none;
  font-size: 13px;
  font-weight: 500;
}
.kopf-suche:hover { background: var(--oh-hover); color: var(--oh-text-2); }
.kopf-suche svg.sym { width: 17px; height: 17px; flex-basis: 17px; }
/* Tastenhinweis: wie eine Taste gesetzt (OneHomes `kbd`-Fassung), aber aus Tokens. */
.kopf-suche-taste {
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 600;
  line-height: 1;
  padding: 3px 5px;
  border: 1px solid var(--oh-linie-stark);
  border-radius: 5px;
  background: var(--oh-flaeche-2);
  color: var(--oh-text-2);
}

/* ---------- Overlay ---------- */
.suche-schleier {
  position: fixed;
  inset: 0;
  z-index: 70;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: max(48px, 10vh) 16px 24px;
  background: var(--schleier);
}
.suche-bereich {
  display: flex;
  flex-direction: column;
  width: min(94vw, 560px);
  max-height: min(72vh, 560px);
  overflow: hidden;
  border: 1px solid var(--oh-linie-stark);
  border-radius: var(--r-karte);
  background: var(--oh-flaeche);
  box-shadow: var(--schatten-anmeldung);
}

/* Suchfeld: Lupe, Eingabe, Schließen. Das Feld selbst hat keine eigene Feldoptik – es ist
   die Kopfzeile der Palette, nicht ein Formularfeld. */
.suche-feld {
  display: flex;
  align-items: center;
  gap: 10px;
  flex: none;
  padding: 12px 14px;
  border-bottom: 1px solid var(--oh-seitenlinie);
}
.suche-feld svg.sym { width: 19px; height: 19px; flex-basis: 19px; color: var(--oh-text-blass); }
.suche-eingabe {
  flex: 1;
  min-width: 0;
  min-height: 0;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
  font-size: 15.5px;
  font-weight: 500;
  color: var(--oh-text);
}
.suche-eingabe:focus { border: 0; box-shadow: none; }
.suche-zu {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 30px;
  height: 30px;
  min-height: 0;
  padding: 0;
  border: 0;
  border-radius: var(--r-feld);
  background: transparent;
  box-shadow: none;
  color: var(--oh-text-leise);
}
.suche-zu:hover { background: var(--oh-hover); color: var(--oh-text); }
.suche-zu svg.sym { width: 15px; height: 15px; flex-basis: 15px; }

/* Trefferliste. Die aktive Zeile ist keine Fokus-, sondern eine Auswahlfläche
   (`aria-selected` am role="option"): der Fokus bleibt im Feld, die Zeile leuchtet. */
.suche-liste {
  margin: 0;
  padding: 6px;
  list-style: none;
  overflow-y: auto;
  overscroll-behavior: contain;
}
.suche-eintrag {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 11px;
  border-radius: var(--r-feld);
  color: var(--oh-text-2);
  font-size: 13.5px;
  font-weight: 500;
  cursor: pointer;
}
.suche-eintrag[aria-selected="true"] { background: var(--oh-accent-weich); color: var(--oh-accent-dunkel); }
.suche-titel { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Die Gruppe („Mein Arbeitsplatz“, „Verwaltung“, …) steht rechts und ist leiser als der
   Titel – kleine Schrift nimmt `--oh-text-leise`, nicht die blasse Stufe. */
.suche-gruppe {
  margin-left: auto;
  flex: none;
  font-size: 11.5px;
  font-weight: 600;
  color: var(--oh-text-leise);
}

/* Leerzustand und Fußzeile mit den Tastenhinweisen. */
.suche-leer {
  margin: 0;
  padding: 22px 16px;
  text-align: center;
  color: var(--oh-text-leise);
  font-size: 13.5px;
}
.suche-fuss {
  display: flex;
  align-items: center;
  gap: 6px;
  flex: none;
  margin: 0;
  padding: 9px 14px;
  border-top: 1px solid var(--oh-seitenlinie);
  background: var(--oh-flaeche-2);
  color: var(--oh-text-leise);
  font-size: 11.5px;
}
.suche-fuss kbd {
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 600;
  line-height: 1;
  padding: 2px 5px;
  border: 1px solid var(--oh-linie-stark);
  border-radius: 4px;
  background: var(--oh-flaeche);
  color: var(--oh-text-2);
}

/* Die Seite hinter dem Overlay scrollt nicht mit. */
body.suche-offen { overflow: hidden; }

/* Nur die Elemente, deren `display` diese Scheibe setzt, brauchen die Ausnahme. */
.kopf-suche[hidden],
.suche-schleier[hidden],
.suche-eintrag[hidden],
.suche-liste[hidden],
.suche-leer[hidden] { display: none; }

@media (max-width: 760px) {
  /* Auf dem Handy ist kein Platz für Text und Tastenhinweis: nur die Lupe bleibt. */
  .kopf-suche { padding: 6px; }
  .kopf-suche-text, .kopf-suche-taste { display: none; }
  .suche-schleier { padding: 16px 10px; }
  .suche-bereich { max-height: 82vh; }
}

/* ---------- Bestand und Bestellvorschlag (Etappe 31, 20.10.2026) ----------
   Die Bestandsseite setzt je Zeile ein kleines Formular; der Bestellvorschlag ist eine
   druckbare Unterseite. Der Druckblock steht bewusst nur unter `body.seite-bestellvorschlag`
   und �berschreibt keine der vorhandenen Druckregeln (Etiketten, Verzeichnis). */
.bestand-shopwahl { display: flex; align-items: end; gap: 12px; flex-wrap: wrap; margin-top: 8px; }
.bestand-setzen { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.eingabe.kurz { width: 92px; min-width: 0; }
tr.gedaempft td { color: var(--oh-text-leise); }
tr.gedaempft td .pille { opacity: .85; }

@media print {
  body.seite-bestellvorschlag { background: var(--oh-weiss); color: var(--oh-schwarz); }
  body.seite-bestellvorschlag .seitenleiste,
  body.seite-bestellvorschlag .kopfleiste,
  body.seite-bestellvorschlag .vfkopf,
  body.seite-bestellvorschlag .bannerzone,
  body.seite-bestellvorschlag .demo-leiste,
  body.seite-bestellvorschlag .tableiste,
  body.seite-bestellvorschlag .meldungen,
  body.seite-bestellvorschlag .sprung,
  body.seite-bestellvorschlag .bestellvorschlag-auswahl,
  body.seite-bestellvorschlag button,
  body.seite-bestellvorschlag .knopf { display: none !important; }
  body.seite-bestellvorschlag .buehne { padding: 0; background: var(--oh-weiss); color: var(--oh-schwarz); }
  body.seite-bestellvorschlag .buehne::before,
  body.seite-bestellvorschlag .buehne::after,
  body.seite-bestellvorschlag .buehne > .buehne-inhalt::before,
  body.seite-bestellvorschlag .buehne > .buehne-inhalt::after { display: none !important; }
  body.seite-bestellvorschlag .buehne-inhalt { max-width: none; }
  body.seite-bestellvorschlag .seite { margin: 0; padding: 0; color: var(--oh-schwarz); }
  body.seite-bestellvorschlag .karte { margin: 0; padding: 0; border: 0; box-shadow: none; background: var(--oh-weiss); }
  body.seite-bestellvorschlag .tabelle-scroll { overflow: visible; }
  body.seite-bestellvorschlag table { width: 100%; }
  body.seite-bestellvorschlag tr { break-inside: avoid; page-break-inside: avoid; }
}

/* ---------- Monatsabrechnung (Etappe 28c, 21.10.2026) ----------
   Druckbare Fassung ohne Seitengerüst: Der Block steht bewusst nur unter
   `body.seite-abrechnung` und überschreibt keine vorhandenen Druckregeln. */
@media print {
  body.seite-abrechnung { background: var(--oh-weiss); color: var(--oh-schwarz); }
  body.seite-abrechnung .seitenleiste,
  body.seite-abrechnung .kopfleiste,
  body.seite-abrechnung .vfkopf,
  body.seite-abrechnung .bannerzone,
  body.seite-abrechnung .demo-leiste,
  body.seite-abrechnung .tableiste,
  body.seite-abrechnung .meldungen,
  body.seite-abrechnung .sprung,
  body.seite-abrechnung .nicht-drucken,
  body.seite-abrechnung .knopfreihe,
  body.seite-abrechnung .leer-aktion,
  body.seite-abrechnung button,
  body.seite-abrechnung .knopf { display: none !important; }
  body.seite-abrechnung .buehne { padding: 0; background: var(--oh-weiss); color: var(--oh-schwarz); }
  body.seite-abrechnung .buehne::before,
  body.seite-abrechnung .buehne::after,
  body.seite-abrechnung .buehne > .buehne-inhalt::before,
  body.seite-abrechnung .buehne > .buehne-inhalt::after { display: none !important; }
  body.seite-abrechnung .buehne-inhalt { max-width: none; }
  body.seite-abrechnung .seite { margin: 0; padding: 0; color: var(--oh-schwarz); }
  body.seite-abrechnung .karte { margin: 0 0 10mm; padding: 0; border: 0; box-shadow: none; background: var(--oh-weiss); }
  body.seite-abrechnung .tabelle-scroll { overflow: visible; }
  body.seite-abrechnung table { width: 100%; }
  body.seite-abrechnung tr { break-inside: avoid; page-break-inside: avoid; }
}

/* ---------- Rangliste (Etappe 28f, 22.10.2026) ----------
   Druckbare Fassung wie Abrechnung und Etiketten: derselbe Zuschnitt, eigener Body-Klasse-
   Schalter. Steht bewusst nur unter `body.seite-rangliste` und überschreibt keine
   vorhandenen Druckregeln. */
@media print {
  body.seite-rangliste { background: var(--oh-weiss); color: var(--oh-schwarz); }
  body.seite-rangliste .seitenleiste,
  body.seite-rangliste .kopfleiste,
  body.seite-rangliste .vfkopf,
  body.seite-rangliste .bannerzone,
  body.seite-rangliste .demo-leiste,
  body.seite-rangliste .tableiste,
  body.seite-rangliste .meldungen,
  body.seite-rangliste .sprung,
  body.seite-rangliste .nicht-drucken,
  body.seite-rangliste .knopfreihe,
  body.seite-rangliste .leer-aktion,
  body.seite-rangliste button,
  body.seite-rangliste .knopf { display: none !important; }
  body.seite-rangliste .buehne { padding: 0; background: var(--oh-weiss); color: var(--oh-schwarz); }
  body.seite-rangliste .buehne::before,
  body.seite-rangliste .buehne::after,
  body.seite-rangliste .buehne > .buehne-inhalt::before,
  body.seite-rangliste .buehne > .buehne-inhalt::after { display: none !important; }
  body.seite-rangliste .buehne-inhalt { max-width: none; }
  body.seite-rangliste .seite { margin: 0; padding: 0; color: var(--oh-schwarz); }
  body.seite-rangliste .karte { margin: 0 0 10mm; padding: 0; border: 0; box-shadow: none; background: var(--oh-weiss); }
  body.seite-rangliste .tabelle-scroll { overflow: visible; }
  body.seite-rangliste table { width: 100%; }
  body.seite-rangliste tr { break-inside: avoid; page-break-inside: avoid; }
}

/* ===== OneContracts (Etappe 36a, 26.10.2026) =====================================
   Betreiberverträge: Umschalter, ausklappbare Gruppen, Feldgruppen des Formulars und
   die Dokumentliste. Nur Ergänzungen mit Präfix `oc-`; die Grundformen (Karte, Pille,
   Knopf, Tabelle, Raster) kommen aus den vorhandenen Regeln. Mobil einspaltig, Tabellen
   bleiben in `.tabelle-scroll` scrollbar. */
.oc-umschalter { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.oc-umschalter .pille { text-decoration: none; border: 1px solid var(--oh-linie); }
.oc-umschalter .pille.ok { border-color: transparent; }
.oc-umschalter .pille[aria-current="true"] { box-shadow: inset 0 0 0 1px var(--oh-accent-ring); }

.oc-gruppe { padding: 0; overflow: hidden; }
.oc-gruppe > summary { list-style: none; cursor: pointer; display: flex; align-items: center; gap: 10px; padding: 14px 18px; }
.oc-gruppe > summary::-webkit-details-marker { display: none; }
.oc-gruppe > summary::before { content: "▸"; color: var(--oh-text-leise); font-size: 12px; transition: transform .15s ease; }
.oc-gruppe[open] > summary::before { transform: rotate(90deg); }
.oc-gruppe-kopf { font-weight: 600; }
.oc-gruppe-titel { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.oc-gruppe-kopf .pille { margin-left: auto; }
.oc-gruppe > .tabelle-scroll { padding: 0 18px 16px; }

.oc-seiten { display: flex; align-items: center; flex-wrap: wrap; gap: 12px; margin-top: 12px; }

.oc-feldgruppe { border: 0; margin: 0; padding: 0; min-width: 0; }
.oc-feld { min-width: 0; }
.oc-pflicht { color: var(--oh-fehler-text); }
.oc-schalter { display: flex; align-items: center; gap: 8px; }
.oc-felder { min-width: 640px; }
.oc-felder input[type="text"], .oc-felder select { width: 100%; }
.oc-gefahr { border-color: var(--oh-fehler-weich); }
.oc-gefahr > summary { cursor: pointer; color: var(--oh-fehler-text); font-weight: 600; }

/* Etappe 36b (26.10.2026): markierte Felder eines Auslese-Vorschlags. */
.oc-vorschlag input, .oc-vorschlag select, .oc-vorschlag textarea,
input.oc-vorschlag, select.oc-vorschlag, textarea.oc-vorschlag {
  border-color: var(--oh-accent);
  box-shadow: inset 0 0 0 1px var(--oh-accent-ring);
}
.oc-vorschlag-hinweis { border-color: var(--oh-accent); background: var(--oh-accent-weich); }
.oc-vorschlag-hinweis ul { margin: 8px 0 0; padding-left: 20px; }

.pille.oc-farbe-0 { background: var(--oh-accent-weich); color: var(--oh-accent-dunkel); }
.pille.oc-farbe-1 { background: var(--oh-ok-weich); color: var(--oh-ok-text); }
.pille.oc-farbe-2 { background: var(--oh-warn-weich); color: var(--oh-warn-text); }
.pille.oc-farbe-3 { background: var(--oh-gut-weich); color: var(--oh-gut-text); }
.pille.oc-farbe-4 { background: var(--oh-fehler-weich); color: var(--oh-fehler-text); }
.pille.oc-farbe-5 { background: color-mix(in srgb, var(--oh-accent) 18%, var(--oh-flaeche)); color: var(--oh-accent-dunkel); }
.pille.oc-farbe-6 { background: color-mix(in srgb, var(--oh-ok) 18%, var(--oh-flaeche)); color: var(--oh-ok-text); }
.pille.oc-farbe-7 { background: var(--oh-flaeche-2); color: var(--oh-text-2); }

@media (max-width: 760px) {
  .oc-gruppe > summary { padding: 12px 14px; }
  .oc-gruppe > .tabelle-scroll { padding: 0 14px 12px; }
  .oc-umschalter { width: 100%; }
}

/* Etappe 36i (27.10.2026): Prüffristen/Inventar, Erfassung vor Ort. Nur auf schmalen Geräten:
   `.raster-2` steht oben bereits einspaltig, hier werden Felder und Knöpfe größer. Desktop und
   das Markup bleiben unverändert; kein Inline-JavaScript im Template, kein Foto-Upload. */
@media (max-width: 760px) {
  .oc-erfassung form input[type="text"],
  .oc-erfassung form input[type="number"],
  .oc-erfassung form input[type="date"],
  .oc-erfassung form select,
  .oc-erfassung form textarea { min-height: 48px; font-size: 17px; }
  .oc-erfassung form .knopf { width: 100%; min-height: 50px; font-size: 17px; }
  .oc-erfassung .knopfreihe label { width: 100%; }
}

/* =============================================================================================
   Etappe 37d (26.10.2026), Mobil: Zeiterfassungs-Woche und Kollegenplan als Tageskarten,
   Stempelknopf ohne Überdeckung.

   Angehängt, nicht umgebaut: „Mein Plan“ (`.dp-wochen`, Zeile 1142-1156) bleibt unverändert;
   die Regeln hier sind dieselbe Umformung für den Kollegenplan (`.dp-team`, aus demselben
   Raster Shop × Tag) und für die Zeiterfassungs-Woche (`.zf-woche`, Tage × Zahlen). Beide
   Tabellen tragen ihre Zellbeschriftung in `data-spalte`; `::before` zeigt sie nur in der
   Karte (Muster von `.op-cockpit td[data-k]`, Zeile 2079). Auf dem Desktop und für
   Screenreader bleibt alles die Tabelle mit ihren Spaltenköpfen – das Markup ist dasselbe,
   nur ergänzt.

   Stempelknopf: `.tableiste a.stempel-tab` zieht den runden Knopf über die Leiste (gemessen
   ragen 14 px Knopf plus 4 px Ring darüber, die Leiste selbst ist 66 px hoch), die Reserve in
   `body.mit-shell` (Zeile 1689) war mit `--tableiste-hoehe` (62 px) nur die Leiste. 30 px
   zusätzlich decken Überstand und Ring und lassen 12 px Luft – unabhängig vom 48-px-Rand der
   Bühne, der bisher allein den Abstand trug. Die Tableiste selbst bleibt unverändert.
   ============================================================================================= */
@media (max-width: 760px) {
  /* ---------- Stempelknopf: Platz für den Überstand ---------- */
  body.mit-shell { padding-bottom: calc(var(--tableiste-hoehe) + 30px + env(safe-area-inset-bottom, 0px)); }

  /* ---------- Grundform: Zeile = Karte, Kopfzeile entfällt ---------- */
  table:is(.dp-team, .zf-woche),
  :is(.dp-team, .zf-woche) tbody,
  :is(.dp-team, .zf-woche) tbody tr,
  :is(.dp-team, .zf-woche) tbody th,
  :is(.dp-team, .zf-woche) tbody td,
  :is(.dp-team, .zf-woche) tfoot,
  :is(.dp-team, .zf-woche) tfoot tr,
  :is(.dp-team, .zf-woche) tfoot th,
  :is(.dp-team, .zf-woche) tfoot td {
    display: block; width: auto; min-width: 0; border: 0; padding: 0; position: static;
  }
  :is(.dp-team, .zf-woche) thead { display: none; }

  /* ---------- Kollegenplan: Shop-Karte mit Tag für Tag (wie `.dp-wochen`) ---------- */
  .dp-team tbody tr { margin-bottom: 14px; }
  .dp-team tbody th.dp-shop { padding: 4px 0 6px; font-size: 13px; white-space: normal; }
  .dp-team tbody td {
    display: flex; flex-wrap: wrap; gap: 6px; align-items: flex-start;
    padding: 8px 10px; margin-bottom: 6px;
    border: 1px solid var(--oh-linie); border-radius: var(--r-ui);
    background: var(--oh-flaeche);
  }
  .dp-team tbody td.heute { background: var(--oh-accent-hauch); border-color: color-mix(in srgb, var(--oh-accent) 32%, transparent); }
  .dp-team tbody td > * + * { margin-top: 0; }
  .dp-team tbody td[data-spalte]::before { content: attr(data-spalte); flex-basis: 100%; font-weight: 700; font-size: 12px; color: var(--oh-text-2); }
  .dp-team .dp-slot { flex: 1 1 100%; }
  .dp-team td .leer { padding: 0; }

  /* ---------- Zeiterfassungs-Woche: Tag-Karte, je Zeile eine beschriftete Zahl ---------- */
  .zf-woche tbody tr {
    padding: 10px 12px; margin-bottom: 10px;
    border: 1px solid var(--oh-linie); border-radius: var(--r-ui);
    background: var(--oh-flaeche);
  }
  .zf-woche tbody tr.heute { background: var(--oh-accent-hauch); border-color: color-mix(in srgb, var(--oh-accent) 32%, transparent); }
  .zf-woche tbody td {
    display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 10px;
    padding: 2px 0; background: none;
    font-size: 12.5px; text-align: left; white-space: normal; overflow-wrap: anywhere;
  }
  .zf-woche tbody td:first-child {
    padding: 0 0 5px; margin-bottom: 4px; border-bottom: 1px solid var(--oh-linie);
    font-weight: 700; font-size: 13px; color: var(--oh-text);
  }
  .zf-woche tbody td[data-spalte]::before {
    content: attr(data-spalte); flex: 1 1 auto;
    color: var(--oh-text-leise); font-weight: 600; font-size: 12px;
  }
  /* Eine Zahl, die es an diesem Tag nicht gibt, bekommt keine leere Zeile. */
  .zf-woche tbody td:empty { display: none; }
  /* Bleibt nur die Tagesüberschrift übrig (keine Buchung), fällt die Trennlinie darunter weg. */
  .zf-woche tbody tr:not(:has(td:not(:first-child):not(:empty))) td:first-child { padding-bottom: 0; margin-bottom: 0; border-bottom: 0; }

  /* ---------- Summenzeile: eine flache Karte mit beschrifteten Werten ---------- */
  :is(.dp-team, .zf-woche) tfoot tr {
    display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 14px;
    padding: 8px 10px; margin: 0 0 6px;
    border: 1px solid var(--oh-linie); border-radius: var(--r-ui);
    background: var(--oh-flaeche-2);
  }
  :is(.dp-team, .zf-woche) tfoot > tr > :first-child { flex-basis: 100%; margin-bottom: 2px; font-weight: 700; color: var(--oh-text-2); }
  :is(.dp-team, .zf-woche) tfoot th,
  :is(.dp-team, .zf-woche) tfoot td { font-size: 12px; font-weight: 600; }
  :is(.dp-team, .zf-woche) tfoot [data-spalte]::before { content: attr(data-spalte) "\00a0"; color: var(--oh-text-leise); font-weight: 600; }
  :is(.dp-team, .zf-woche) tfoot :empty { display: none; }
}
