/* InnererRaum – Verwaltungsoberfläche im Glas-Look.
   Gestaltung seit dem 06.10.2026: der Arbeitsstand der Verwaltung (Auftrag des Eigentümers,
   „alle seiten und die komplette app umstellen“) – Glasfenster mit Seitenleiste und
   Goldmarke, warme und kühle Lichtflecken, Gold als Akzent, weißer Fokusring. Vorher
   violetter Grund nach dem Admin-Entwurf vom 21.09.2026 (bis Commit 29a042b).
   Mechanik unverändert: die Leiste trägt Namen und lässt sich auf die Symbolsäule
   einklappen (Auftrag vom 25.09.2026); welcher Zustand ohne Keks gilt, entscheidet
   RAIL_VOREINSTELLUNG in server.js.
   Schrift: die lokale Plus Jakarta Sans - die Inhaltssicherheitsregel lässt nur eigene
   Schriften zu (font-src 'self'), das Haus lädt nichts von fremden Servern (CLAUDE.md). */
@font-face { font-family: "Plus Jakarta Sans"; font-weight: 400; font-style: normal; font-display: swap; src: url(/static/fonts/PlusJakartaSans-Regular.woff2) format("woff2"); }
@font-face { font-family: "Plus Jakarta Sans"; font-weight: 500; font-style: normal; font-display: swap; src: url(/static/fonts/PlusJakartaSans-Medium.woff2) format("woff2"); }
@font-face { font-family: "Plus Jakarta Sans"; font-weight: 600; font-style: normal; font-display: swap; src: url(/static/fonts/PlusJakartaSans-SemiBold.woff2) format("woff2"); }
@font-face { font-family: "Plus Jakarta Sans"; font-weight: 700; font-style: normal; font-display: swap; src: url(/static/fonts/PlusJakartaSans-Bold.woff2) format("woff2"); }
@font-face { font-family: "Plus Jakarta Sans"; font-weight: 800; font-style: normal; font-display: swap; src: url(/static/fonts/PlusJakartaSans-ExtraBold.woff2) format("woff2"); }

:root {
  --bg: #0A0E16;
  --fenster: rgba(17, 21, 30, .62);     /* das Glasfenster um Leiste und Inhalt */
  --leiste-g: rgba(255, 255, 255, .035); /* die gemalte Spalte der Leiste */
  --karte: rgba(255, 255, 255, .065);   /* Glas: Karten, Tabellen, Felder */
  --karte-2: rgba(255, 255, 255, .10);  /* Glas, angehoben: Hover, aktiver Eintrag */
  --rand: rgba(255, 255, 255, .13);
  --kante: rgba(255, 255, 255, .40);    /* Kante der Bedienelemente: >= 3:1 gegen Glas (WCAG 1.4.11) */
  --kante-2: rgba(255, 255, 255, .55);
  --ink: #F1F3F7;
  --ink-2: #D5DAE3;
  --muted: #ABB3C1;      /* >= 5:1 auch auf Glas vor einem hellen Lichtfleck */
  --leise: #A3ABBA;
  --gold: #F2C46B;
  --gold-2: #F8D58E;
  --auf-gold: #2A1A05;   /* Schrift auf Gold: deutlich ueber 10:1 */
  --orange: #FF9F2E;
  --gruen: #34D399;
  --gelb: #FFD54A;
  --rose: #FB7185;
  --blau: #63A8F7;
  --blau-hell: #A9CEFF;
  --fokus: 0 0 0 3px rgba(255, 255, 255, .92);
  --sans: 'Plus Jakarta Sans', -apple-system, "Segoe UI", Arial, sans-serif;
  --radius: 16px;
  /* Abstand zwischen zwei BLOECKEN einer Seite – zwischen den Kacheln, zwischen einem
     Kachelblock und dem naechsten, zwischen Karte und Tabelle. Gemessen am 27.09.2026
     auf „Auswertungen": dort standen an drei Stellen 0 px. Grund: die Raster (.kacheln,
     .zwei) tragen nur ihren INNEREN Abstand (gap), und die Karte bekommt ihr eigenes
     margin-bottom im Raster abgeschaltet – zwischen zwei Rastern blieb damit nichts
     uebrig. Ein Wert an einer Stelle, damit das nicht je Seite auseinanderlaeuft. */
  --luft: 40px;
  /* Breite der gemalten Leistenspalte - folgt dem Einklappen (unten). */
  --leistenbreite: 212px;
}
/* Auf dem Telefon steht ohnehin alles untereinander – dort trennt schon die Reihenfolge,
   und 40 px je Karte waeren vor allem Scrollweg. */
@media (max-width: 720px) { :root { --luft: 24px; } }
* { box-sizing: border-box; }
html { color-scheme: dark; scrollbar-gutter: stable; background: var(--bg); }
/* Der Grund liegt NUR auf html: ein eigener Hintergrund auf body wuerde ueber die
   Lichtflecken (body::before, z-index -1) gemalt und sie verdecken. */
/* flow-root: der untere Rand des Fensters (.shell, Platz fuer das Dock) bleibt IM body. Ohne
   eigenen Formatierungskontext fiel er durch den body hindurch, und min-height schluckte ihn -
   auf einer Seite, die fast genau fensterhoch ist, lag der Inhalt dann unter dem Dock
   (Kalt-Review 07.10.2026, test/kontrast.test.js). */
body {
  margin: 0; color: var(--ink); font-family: var(--sans); display: flow-root;
  font-size: 14.5px; line-height: 1.45; min-height: 100vh; overflow-x: hidden;
}
/* Warme und kuehle Lichtflecken hinter dem Glas - sie machen den Charakter aus. Als
   Pseudoelement, damit der Rahmen kein Zierelement tragen muss; die Kontrast-Tests lesen
   deshalb den GEMALTEN Bildpunkt und nicht die Elternkette (test/kontrast.test.js). */
body::before {
  content: ""; position: fixed; inset: 0; z-index: -1; pointer-events: none;
  background:
    radial-gradient(30vw 26vh at 18% 10%, rgba(224, 136, 31, .55), transparent 70%),
    radial-gradient(34vw 30vh at 86% 8%, rgba(47, 111, 224, .55), transparent 70%),
    radial-gradient(22vw 20vh at 50% 2%, rgba(201, 164, 106, .28), transparent 70%),
    radial-gradient(26vw 34vh at 6% 88%, rgba(30, 79, 180, .45), transparent 70%),
    radial-gradient(28vw 28vh at 90% 94%, rgba(240, 165, 58, .38), transparent 70%),
    linear-gradient(180deg, rgba(10, 14, 22, .2), rgba(10, 14, 22, .6));
}
a { color: var(--gold); }
h1 { margin: 0; font-size: 1.9rem; font-weight: 800; line-height: 1.15; }
h2 { margin: 0 0 .7rem; font-size: 1.02rem; font-weight: 700; letter-spacing: -.01em; }
h1 small, h2 small { color: var(--muted); font-weight: 500; font-size: .62em; }
code, .mono { font-family: ui-monospace, "Cascadia Mono", Consolas, monospace; font-size: .92em; }

/* --- Ein Fokus fuer alle Bedienelemente im Inhalt: weisser Ring mit dunklem Saum - sichtbar
       auf Glas UND auf farbigen Flaechen (Zettel, Goldknopf). :where() haelt die Regel
       schwach: Bausteine mit eigenem Fokus (Termin, Leiste, Reiter, Felder) behalten ihn. */
:where(.inhalt, .anmelde-karte) :is(a, button, summary):focus-visible {
  outline: 2px solid #FFFFFF; outline-offset: 2px; box-shadow: 0 0 0 5px rgba(8, 11, 18, .92);
}

/* --- Rahmen: ein Glasfenster mit der Bereichsleiste links und dem Inhalt rechts.
       Die Leiste steht beschriftet (212px) oder als Symbolsaeule (64px); der Zustand kommt
       vom Server. Die Spalte der Leiste malt das FENSTER (heller Streifen + Trennlinie),
       nicht die Leiste selbst: die bleibt klebend (sticky) und so hoch wie ihr Inhalt. Eine
       Leiste auf voller Fensterhoehe schob auf langen Seiten „Benutzer", „Handbuch" und
       „Mein Konto" unter den Bildschirmrand - gemessen von test/kontrast.test.js am
       06.10.2026. */
.shell {
  display: flex; width: min(1500px, 100% - 48px); margin: 24px auto 112px;
  background:
    linear-gradient(90deg, var(--leiste-g) 0 var(--leistenbreite),
      rgba(255, 255, 255, .08) var(--leistenbreite) calc(var(--leistenbreite) + 1px), transparent 0),
    var(--fenster);
  border: 1px solid var(--rand); border-radius: 22px;
  backdrop-filter: blur(30px) saturate(140%);
  box-shadow: 0 40px 120px rgba(0, 0, 0, .55), inset 0 1px 0 rgba(255, 255, 255, .08);
}
.rail {
  position: sticky; top: 26px; align-self: flex-start;
  border-radius: 22px 0 0 0;
  padding: 14px 10px; display: flex; flex-direction: column; gap: 6px; align-items: stretch;
  min-height: 70vh; flex: none;
  width: 212px; transition: width .16s ease; z-index: 3;
}
.rail-kopf { display: flex; align-items: center; justify-content: space-between; margin-bottom: 14px; }
.rail .klapp {
  width: 44px; height: 44px; flex: none; border: none; background: none; cursor: pointer;
  border-radius: 13px; display: grid; place-items: center; color: var(--muted);
  font: inherit; padding: 0; transition: background .15s, color .15s;
}
.rail .klapp svg { transition: transform .16s ease; }
/* Die Bildmarke der Praxis (docs/logo/logo.py) – Zierde, darum alt="" */
.rail .rail-marke { display: block; width: 34px; height: 34px; margin-left: 5px; }
/* Der Praxisname neben der Bildmarke. Er bricht um statt abgeschnitten zu werden: er ist
   einstellbar (Einstellungen), und „Massagepraxis InnererRaum" passt nicht in eine Zeile. */
.rail-name { flex: 1; min-width: 0; margin-left: 8px; line-height: 1.2; }
.rail-name b { display: block; font-size: .86rem; font-weight: 700; color: var(--ink); overflow-wrap: anywhere; }
.rail-name span { display: block; font-size: .72rem; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rail a, .rail .aus {
  /* Zwei Spalten: feste Bildspur, dann das Wort. Eingeklappt geht die Wortspur auf 0.
     NICHT place-items verwenden - das setzt auch justify-items:center und ruecke jedes
     Wort verschieden weit ein, was in einer Navigationsliste sofort auffaellt.
     KEIN sichtbarer Rand: eingeklappt ist die Innenbreite genau 44 px, ein Rand je Seite
     schoebe das Sinnbild aus der Spalte - Kanten entstehen als Innenschatten (inset). */
  display: grid; grid-template-columns: 44px 1fr; align-items: center; justify-items: start;
  min-height: 44px; border-radius: 13px;
  color: var(--ink-2); text-decoration: none; transition: background .15s, color .15s;
}
.rail .bild { width: 44px; height: 44px; display: grid; place-items: center; }
.rail .wort {
  /* Nur das Wort wird beschnitten, nicht die Leiste: ein overflow:hidden auf .rail
     kappte die Goldmarke des aktiven Eintrags. */
  overflow: hidden; white-space: nowrap; padding-right: 12px;
  font-size: .88rem; font-weight: 600; line-height: 1.2;
}
.rail .wort .wann {
  display: block; font-style: normal; font-size: .71rem; font-weight: 500;
  color: var(--leise); margin-top: 1px;
}
.rail .klapp:hover, .rail a:hover {
  background: rgba(255, 255, 255, .06); color: var(--ink); box-shadow: inset 0 0 0 1px var(--kante);
}
.rail a.aktiv {
  position: relative; background: var(--karte-2); color: var(--ink); box-shadow: inset 0 0 0 1px var(--kante);
}
/* Die Goldmarke des aktiven Bereichs. Sie sitzt in der Bildspur, nicht am Rand der Leiste:
   eingeklappt ist dort kein Platz daneben. */
.rail a.aktiv::before {
  content: ""; position: absolute; left: 0; top: 10px; bottom: 10px; width: 3px;
  border-radius: 3px; background: var(--gold);
}
/* Die noch nicht gebauten Bereiche: Schrift in --leise (gemessen in test/kontrast.test.js),
   ruhiger wirken sie ueber das Sinnbild, nicht ueber die Schriftfarbe. */
.rail .aus { cursor: default; color: var(--leise); }
/* NACH .rail a.aktiv, nicht davor: bei gleicher Spezifitaet gewinnt die spaetere Regel,
   und die Kante des aktiven Eintrags schluckte den Fokusring sonst. Der aktive Eintrag
   behaelt seine Kante UND bekommt den Ring - deshalb beide Schatten. */
.rail .klapp:focus-visible, .rail a:focus-visible { outline: none; box-shadow: var(--fokus); }
.rail a.aktiv:focus-visible { box-shadow: var(--fokus), inset 0 0 0 1px var(--kante); }
.rail .aus .bild { opacity: .38; }
.rail svg {
  width: 21px; height: 21px; fill: none; stroke: currentColor;
  stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round;
}
.rail .fuellung { flex: 1; }

/* Eingeklappt. Nur oberhalb des Umbruchs: quer hat die Leiste keine Breite zu sparen,
   dort wuerde sie nicht flacher, nur namenlos. Die Grenze ist buendig an die
   Mediaabfrage unten gesetzt: "not all and (max-width: 860px)" ist deren exaktes
   Gegenstueck. Ein min-width-Wert waere es NICHT - bei 861px faellt alles zwischen
   860,01 und 860,99 in keinen der beiden Zweige, und gebrochene Breiten entstehen
   beim Seitenzoom und bei nicht ganzzahligem Geraeteverhaeltnis. */
@media not all and (max-width: 860px) {
  html[data-rail="zu"] { --leistenbreite: 64px; }
  html[data-rail="zu"] .rail { width: 64px; }
  html[data-rail="zu"] .rail a, html[data-rail="zu"] .rail .aus { grid-template-columns: 44px 0; }
  html[data-rail="zu"] .rail .wort { width: 0; min-width: 0; padding-right: 0; }
  html[data-rail="zu"] .rail .klapp svg { transform: rotate(180deg); }
  /* Bildmarke und Praxisname weichen: zu dritt passen sie mit dem Knopf nicht in die 44px
     Innenbreite - der Knopf wuerde herausgedrueckt und die Leiste liesse sich nicht
     wieder aufklappen. */
  html[data-rail="zu"] .rail .rail-marke, html[data-rail="zu"] .rail-name { display: none; }
  html[data-rail="zu"] .rail-kopf { justify-content: center; }
  /* Eingeklappt ist das Wort auf 0 geschnitten. Damit der Name trotzdem erreichbar
     bleibt, legt er sich bei Zeiger UND bei Tastaturfokus als Fahne neben die Leiste.
     Das ersetzt den title: der wiederholte aufgeklappt den sichtbaren Text, und
     Vorleseprogramme kuendigen ihn als Beschreibung an - der Name kaeme zweimal. */
  html[data-rail="zu"] .rail a:focus-visible .wort,
  html[data-rail="zu"] .rail a:hover .wort,
  html[data-rail="zu"] .rail .aus:hover .wort {
    position: absolute; left: 62px; width: auto; padding: 5px 11px;
    background: #141925; color: var(--ink); border: 1px solid var(--kante); border-radius: 10px;
    box-shadow: 0 10px 26px rgba(0,0,0,.5); z-index: 4;
  }
  html[data-rail="zu"] .rail a, html[data-rail="zu"] .rail .aus { position: relative; }
}
.inhalt { flex: 1; min-width: 0; padding: 28px 28px 32px; }
.inhalt:focus { outline: none; }

/* Nur fuer Vorleseprogramme: sichtbar erst bei Tastaturfokus. Gold mit dunkler Schrift. */
.sprung {
  position: absolute; left: 14px; top: -60px; z-index: 20;
  background: var(--gold); color: var(--auf-gold); padding: .6rem 1.1rem; border-radius: 0 0 12px 12px;
  font-weight: 700; font-size: .88rem; text-decoration: none; transition: top .15s;
}
.sprung:focus { top: 0; }
.nurlesen {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
}

.kopf { display: flex; justify-content: space-between; align-items: flex-start; gap: 20px; margin-bottom: 20px; flex-wrap: wrap; }
.kopf .unter { color: var(--muted); margin: .25rem 0 0; font-size: .92rem; }
.kopf .uhr { text-align: right; }
.kopf .uhr b { display: block; font-size: 2.1rem; font-weight: 800; line-height: 1; letter-spacing: -.02em; }
.kopf .uhr span { color: var(--muted); font-size: .86rem; }

@media (max-width: 860px) {
  /* Die Leiste wird zum Querstreifen oben im Fenster; die gemalte Spalte entfaellt. */
  :root { --leistenbreite: 0px; }
  .shell { flex-direction: column; width: calc(100% - 24px); margin: 12px auto 100px; background: var(--fenster); }
  .rail {
    position: static; flex-direction: row; min-height: 0; width: 100%; overflow-x: auto;
    background: var(--leiste-g); border-bottom: 1px solid rgba(255, 255, 255, .08); border-radius: 22px 22px 0 0;
  }
  /* Die ganze Kopfzeile weicht, nicht nur die Bildmarke - sonst bliebe der Klappknopf im
     Querstreifen stehen und schoebe den ersten Bereich zur Seite. */
  .rail .rail-kopf, .rail .fuellung { display: none; }
  /* flex: none, sonst stauchen die Eintraege und schneiden die Woerter ab, statt die
     vorhandene Querrolle zu benutzen. Das Behandlungs-iPad hochkant ist genau das
     Geraet, das die Namen am dringendsten braucht. */
  .rail a, .rail .aus { flex: none; }
  .inhalt { padding: 20px 16px 24px; }
  .kopf .uhr { text-align: left; }
  h1 { font-size: 1.5rem; }
}

/* --- Karten */
/* .g-karte ist die Karte der Uebersicht - dasselbe Glas, nur ohne Abstand nach unten,
   weil dort das Raster die Luft setzt. */
.karte, .g-karte {
  background: var(--karte); border: 1px solid var(--rand); border-radius: var(--radius);
  padding: 16px; min-width: 0; box-shadow: inset 0 1px 0 rgba(255, 255, 255, .06);
}
.karte { margin-bottom: 16px; }
.karte h2 .link { font-size: .72rem; font-weight: 600; color: var(--gold); text-decoration: none; float: right; }
/* --- Die Kennzahlen-Kacheln
 *
 * Vorher: repeat(auto-fit, minmax(270px, 1fr)). Gemessen am 27.09.2026 auf der Seite
 * „Auswertungen" mit ihren vier Kacheln:
 *     1440 px  ->  4 nebeneinander à 273 px, zwei Beschriftungen zweizeilig
 *     1280 px  ->  nur noch 3 passen, die VIERTE steht allein in der zweiten Reihe
 * Beides ist das, was „zu eng" meint: einmal zu schmal, einmal ein einzelner Rest.
 *
 * auto-fit kann das nicht lösen. Es füllt so viele Spalten, wie hineinpassen, und weiß
 * nichts davon, dass vier Kacheln sich schlecht auf drei Spalten verteilen – egal, wo
 * man die Mindestbreite ansetzt, es gibt immer eine Fensterbreite, bei der eine allein
 * bleibt. Deshalb wird die SPALTENZAHL gesetzt und nicht geraten.
 *
 * VIER SPALTEN GIBT ES NICHT MEHR, und das ist der Kern: das Fenster ist auf 1500 px
 * gedeckelt, abzüglich Leiste und Rand bleiben rund 1230 px Inhalt. Vier Spalten wären
 * darin IMMER zu schmal; die Vierer-Anordnung wurde nicht verschoben, sondern abgeschafft.
 * Zwei Kacheln nebeneinander sind hier rund 480 bis 560 px breit, und die Beschriftungen
 * stehen einzeilig.
 *
 * :has() liest die Anzahl aus dem Markup, damit keine Vorlage eine Klasse mitführen muss
 * (dieselbe Technik wie beim Dock, das dem Fokus ausweicht). DREI Kacheln behalten drei
 * Spalten, solange Platz ist – der Rest wäre ein Loch.
 */
.kacheln {
  display: grid; gap: var(--luft); align-items: start; margin-bottom: var(--luft);
  grid-template-columns: repeat(2, minmax(0, 1fr));
}
@media (min-width: 1101px) {
  .kacheln:has(> :nth-child(3):last-child) { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
/* Wer als Einzelner in der letzten Reihe landet, nimmt die ganze Breite – eine halb
   leere Reihe sieht aus wie ein Fehler im Aufbau. */
.kacheln > :last-child:nth-child(odd) { grid-column: 1 / -1; }
.kacheln:has(> :nth-child(3):last-child) > :last-child { grid-column: auto; }
@media (max-width: 1100px) {
  .kacheln:has(> :nth-child(3):last-child) > :last-child { grid-column: 1 / -1; }
}
@media (max-width: 720px) {
  .kacheln, .kacheln:has(> :nth-child(3):last-child) { grid-template-columns: 1fr; }
}
.kacheln .karte { margin-bottom: 0; }
.zwei { display: grid; grid-template-columns: 1fr 1fr; gap: var(--luft); align-items: start; margin-bottom: var(--luft); }
.zwei .karte { margin-bottom: 0; }
/* Die Bloecke einer Seite untereinander: dieselbe Luft wie im Raster, damit eine Reihe
   Kacheln und die Karte darunter denselben Abstand halten. Nur DIREKTE Kinder von
   .inhalt – eine Karte innerhalb einer Karte behaelt ihre eigenen 16 px. */
.inhalt > .karte, .inhalt > .tablewrap { margin-bottom: var(--luft); }
/* Der letzte Block braucht unten nichts – darunter steht nur noch der Seitenrand. */
.inhalt > :last-child { margin-bottom: 0; }
/* 1200 statt 1050: die Schwelle war gegen die schmale Symbolleiste (66px) geeicht.
   Beschriftet nimmt die Leiste 212px, und zwei Karten nebeneinander wuerden sonst
   bis etwa 1200px in einer Breite stehen, fuer die sie zu schmal sind. */
@media (max-width: 1200px) { .zwei { grid-template-columns: 1fr; } }

.kpi { background: var(--karte); border: 1px solid var(--rand); border-radius: var(--radius); padding: 16px; }
.kpi .wert { font-size: 1.9rem; font-weight: 800; line-height: 1.05; letter-spacing: -.02em; font-variant-numeric: tabular-nums; }
.kpi .label { color: var(--muted); font-size: .84rem; margin-top: .2rem; }
/* Innerhalb einer Karte traegt die Kennzahl keinen eigenen Rahmen - sonst Karte in Karte. */
.kpi.nackt { background: none; border: none; padding: 0; }

/* --- Meldungen */
.flash { padding: .75rem 1rem; border-radius: 14px; margin: 0 0 16px; border: 1px solid var(--rand); background: var(--karte-2); border-left: 3px solid var(--gruen); }
.flash.fehler { border-left-color: var(--rose); }
.fehlerliste { background: var(--karte-2); border: 1px solid var(--rand); border-left: 3px solid var(--rose); padding: .75rem 1rem .75rem 1.7rem; border-radius: 14px; margin: 0 0 16px; }
.fehlerliste li { margin: .2rem 0; }
.hinweis { background: rgba(255, 213, 74, .10); border: 1px solid rgba(255, 213, 74, .32); padding: .75rem 1rem; border-radius: 14px; margin: 0 0 14px; font-size: .92rem; }

/* --- Tabellen */
.tablewrap { overflow-x: auto; border: 1px solid var(--rand); border-radius: var(--radius); background: var(--karte); }
table.daten { width: 100%; border-collapse: collapse; font-size: .93rem; }
.daten th, .daten td { text-align: left; padding: .7rem .9rem; border-bottom: 1px solid var(--rand); vertical-align: top; }
/* Kleinste Schrift der Anwendung: 11,2px Grossbuchstaben - --leise, gemessen in
   test/kontrast.test.js („Spaltenköpfe"). */
.daten th { color: var(--leise); font-size: .7rem; letter-spacing: .09em; text-transform: uppercase; font-weight: 700; white-space: nowrap; }
.daten tr:last-child td { border-bottom: none; }
.daten tbody tr:hover td { background: var(--karte-2); }
.daten td.num, .daten th.num { text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums; }
.daten td.aktion { white-space: nowrap; text-align: right; }
.daten .leer td { color: var(--muted); text-align: center; padding: 1.6rem; }
/* Ohne Knoepfe - ein Knopf in der Tabelle behaelt seine eigene Schrift; sonst stand „Verkaufen“
   hell auf Gold (1,47:1, test/kontrast.test.js). :where() haelt die Spezifitaet wie vorher,
   damit sich fuer alle anderen Tabellenlinks an der Kaskade nichts verschiebt. */
.daten a:where(:not(.btn)) { color: var(--ink); text-decoration: none; }
.daten a:where(:not(.btn)):hover { color: var(--gold); }

/* --- Eine Tabelle, die auf dem Telefon STAPELT statt seitwaerts zu rollen
 *
 * Gemessen am 26.09.2026 auf 375 px: die Posteingangsliste war 726 px breit in einer
 * 330 px breiten Huelle. Der BETREFF - das Einzige, weswegen man die Liste ueberhaupt
 * ansieht - stand bei x = 342 und damit ausserhalb des Fensters. `.tablewrap` rollt
 * seitwaerts, man kommt also hin; aber eine Liste, deren wichtigste Spalte man erst
 * suchen muss, ist auf einem Telefon keine Liste.
 *
 * Deshalb `stapelbar` als eigene Klasse und nicht als Regel fuer alle Tabellen: die
 * uebrigen Listen dieser Software rollen seitwaerts. Wer eine weitere Liste umstellen
 * will, setzt die Klasse und gibt den Zellen ein `data-titel` - die Ueberschrift
 * verschwindet ja mit dem Tabellenkopf.
 *
 * `data-titel` und nicht die Spaltennummer: eine Nummer verschiebt sich, sobald jemand
 * eine Spalte einfuegt, und dann steht der falsche Name an der Zelle. */
@media (max-width: 560px) {
  .tablewrap:has(.daten.stapelbar) { overflow-x: visible; }
  .daten.stapelbar thead { display: none; }
  .daten.stapelbar, .daten.stapelbar tbody, .daten.stapelbar tr, .daten.stapelbar td { display: block; }
  .daten.stapelbar tr { padding: .55rem 0; border-bottom: 1px solid var(--rand); }
  .daten.stapelbar tr:last-child { border-bottom: none; }
  .daten.stapelbar td { border-bottom: none; padding: .12rem .9rem; }
  .daten.stapelbar td[data-titel]::before {
    content: attr(data-titel) ": "; color: var(--leise); font-size: .72rem;
    letter-spacing: .06em; text-transform: uppercase; font-weight: 700;
  }
  /* Eine leere Zelle wuerde als blosse Beschriftung dastehen - etwa "TERMIN:" ohne
     Termin. :empty allein genuegt dafuer nicht, Leerraum im Markup zaehlt als Inhalt;
     deshalb tragen die Vorlagen das Attribut nur, wo auch etwas steht. */
  .daten.stapelbar td:empty { display: none; }
  /* Die Knoepfe duerfen umbrechen statt die Zeile zu weiten. */
  .daten.stapelbar td.aktion { white-space: normal; text-align: left; padding-top: .45rem; }
  .daten.stapelbar .leer td { text-align: left; padding: 1.2rem .9rem; }
  /* Lange Mailadressen brechen, statt die Zeile aufzuspannen. */
  .daten.stapelbar td { overflow-wrap: anywhere; }
}

/* Marken: offen blau, grau, rot, Warnung gelb - je ueber 4,5:1 auf Glas, auch im
   Zeilen-Hover (test/kontrast.test.js). */
.badge { display: inline-block; font-size: .68rem; font-weight: 700; letter-spacing: .05em; text-transform: uppercase; padding: .2rem .55rem; border-radius: 999px; background: rgba(99, 168, 247, .16); color: var(--blau-hell); white-space: nowrap; }
.badge.grau { background: rgba(255, 255, 255, .08); color: var(--ink-2); }
.badge.rot { background: rgba(251, 113, 133, .16); color: #FDA4AF; }   /* heller als --rose: im Zeilen-Hover sonst 4,37:1 */
.badge.warn { background: rgba(255, 213, 74, .14); color: var(--gelb); }

/* --- Formulare */
form.stack { display: grid; gap: 16px; }
.felder { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: .9rem 1rem; }
/* align-content: start - sonst STRECKT das Raster die Eingabe auf die Hoehe der
   hoechsten Zelle derselben Zeile. Gemessen auf der Gutscheinseite: ein Feld neben
   einem mit zwei Zeilen Beitext war 88 px hoch statt 43 - eine Eingabe, die aussieht
   wie ein Textfeld, in die aber nur eine Zeile passt. */
.feld { display: grid; gap: .3rem; align-content: start; }
.feld.breit { grid-column: 1 / -1; }
/* Ein Feld, das das Skript ausblendet (hidden), bleibt aus - .feld setzt display: grid und hebelte das Attribut sonst aus. */
.feld[hidden] { display: none; }
/* .felder.zeilen: die Eingaben einer Reihe stehen auf EINER Linie, auch wenn ein Label daneben
   umbricht (Georg 12.10.2026: „die Eingabefelder flattern“). Jedes Feld belegt drei Zeilen des
   Rasters - Label, Eingabe, Hinweis - und teilt sie per subgrid mit seinen Nachbarn; das Label
   sitzt unten buendig ueber seiner Eingabe. align-content: start oben bleibt: die Eingabe wird
   nicht gestreckt. Bisher nur im Behandlungsformular gesetzt. */
.felder.zeilen > .feld { grid-row: span 3; grid-template-rows: subgrid; row-gap: .3rem; }
.felder.zeilen > .feld > label { align-self: end; }
.felder.zeilen > .feld > p { margin: 0; }
/* Behandlungsformular: Abschnitte mit hervorgehobener Ueberschrift, Labels in Schriftfarbe. */
.behandlung-form .karte > h2 { color: var(--gold); font-size: 1.08rem; padding-bottom: .55rem; border-bottom: 1px solid var(--rand); margin-bottom: .8rem; }
.behandlung-form .karte > h2 + p.klein { margin: -.25rem 0 .8rem; }
.behandlung-form > .zwei { margin-bottom: 0; }
.behandlung-form .feld > label { color: var(--ink-2); font-size: .88rem; }
/* Behandlungsliste nach Art: je Gruppe eine Ueberschrift; feste Spaltenbreiten, damit die Spalten
   beider Tabellen untereinander stehen. Auf dem Telefon rollt die Tabelle wie bisher seitwaerts. */
.behandlung-gruppe { margin-bottom: var(--luft); }
.behandlung-gruppe > h2 { color: var(--gold); font-size: 1.08rem; margin: 0 0 .6rem; }
.behandlung-gruppe > h2 small { color: var(--muted); font-weight: 600; font-size: .85rem; margin-left: .3rem; }
/* Breiten in Prozent: feste rem-Breiten quetschten die Namensspalte auf 1280 px auf wenige Zeichen. */
.behandlung-gruppe .daten { table-layout: fixed; min-width: 860px; }
.behandlung-gruppe .daten th:nth-child(1) { width: 31%; }
.behandlung-gruppe .daten th:nth-child(2) { width: 12%; }   /* „1 Std. 30 Min.“ in einer Zeile */
.behandlung-gruppe .daten th:nth-child(3), .behandlung-gruppe .daten th:nth-child(4) { width: 9%; }
.behandlung-gruppe .daten th:nth-child(5) { width: 8%; }
.behandlung-gruppe .daten th:nth-child(6) { width: 11%; }
.behandlung-gruppe .daten th:nth-child(7) { width: 20%; }
.behandlung-name { font-size: 1rem; }
label { font-size: .8rem; font-weight: 600; color: var(--muted); }
/* Die Kante der Felder traegt --kante (>= 3:1 gegen das Glas, WCAG 1.4.11) - vorher lag
   sie bei einer Deckkraft von .09 und war praktisch unsichtbar. */
input[type=text], input[type=email], input[type=tel], input[type=date], input[type=number],
input[type=password], input[type=file], input[type=search], input[type=time], select, textarea {
  width: 100%; padding: .6rem .75rem; border: 1px solid var(--kante); border-radius: 12px;
  background: var(--karte); color: var(--ink); font: inherit; font-size: .95rem;
}
input::placeholder, textarea::placeholder { color: var(--muted); }
input:hover, select:hover, textarea:hover { border-color: var(--kante-2); }
/* Fokus: weisse Kante mit hellem Saum - ein Ring um das Feld, der nichts verschiebt. */
input:focus, select:focus, textarea:focus { outline: none; border-color: #FFFFFF; box-shadow: 0 0 0 3px rgba(255, 255, 255, .28); }
textarea { min-height: 5.5rem; resize: vertical; }
/* Eine Gruppe von Optionsfeldern (Arbeitszeiten im Benutzerformular): die Legende nennt die
   Frage, damit ein Vorleseprogramm die Wahl nicht ohne Zusammenhang ansagt. */
fieldset { border: 1px solid var(--rand); border-radius: 12px; padding: 8px 14px 12px; margin: 0 0 14px; }
legend { padding: 0 6px; font-weight: 600; color: var(--ink-2); }
input.num { text-align: right; font-variant-numeric: tabular-nums; }
select option { background: #141925; color: var(--ink); }
/* min-height: die Beschriftung IST das Ziel des Kästchens – gemessen 22 px hoch, WCAG 2.5.8
   verlangt 24 (test/kontrast.test.js, 30.09.2026). */
.check { display: flex; align-items: center; gap: .55rem; font-weight: 500; color: var(--ink); font-size: .93rem; min-height: 24px; }
.check input { width: auto; accent-color: var(--gold); }
/* Betreffe aus Formular und Postfach sind fremder Text: ein Name ohne Leerzeichen schob die
   Akte bei 320 px auf 1010 px Breite (WCAG 1.4.10, Kalt-Review 30.09.2026, Runde 8); ebenso ein
   langer Name oder Sperrgrund (Runde 9). Nur wo solcher Text steht, ausdrücklich per Klasse –
   breiter gefasst änderte „anywhere“ die Mindestbreite anderer Beschriftungen, auch in
   Tabellenzellen (rechnungen/neu.ejs). */
.umbruch, .check a.link { overflow-wrap: anywhere; }
/* Listen aus Links: untereinander standen die Ziele 18 px hoch im Abstand von 21 px (WCAG 2.5.8,
   Runde 9). */
.linkliste a, .check a.link { display: inline-block; min-height: 24px; line-height: 24px; }
/* Eine Tabelle IN einer Karte (Terminliste der Akte): zwei Tönungen übereinander und der Hover der
   Zeile drückten die Marken unter 4,5:1 – „abgesagt" auf 2,75:1 (Kalt-Review 30.09.2026, Runde 10).
   Nur hier per Klasse, nicht .karte .tablewrap: das träfe 15 Tabellen in 13 Ansichten. */
.tablewrap.in-karte { background: transparent; }
.tablewrap.in-karte .badge.grau { color: var(--ink); }
.tablewrap.in-karte td a { display: inline-block; min-height: 24px; line-height: 24px; }

.leiste { display: flex; flex-wrap: wrap; gap: .6rem; align-items: center; margin: 16px 0; }
.leiste .rechts { margin-left: auto; }
/* Der Hauptknopf: Gold mit dunkler Schrift (--auf-gold, deutlich ueber 10:1). Der violette
   Vorgaenger trug weisse Schrift auf Violett - 4,23:1, unter der Schwelle. */
.btn {
  display: inline-block; padding: .6rem 1.1rem; border-radius: 999px; border: 1px solid transparent;
  background: var(--gold); color: var(--auf-gold); font: inherit; font-weight: 700; font-size: .88rem;
  cursor: pointer; text-decoration: none; line-height: 1.3; transition: transform .12s, background .15s;
}
.btn:hover { background: var(--gold-2); transform: translateY(-1px); }
.btn.zweit { background: var(--karte); color: var(--ink); border-color: var(--kante); }
.btn.zweit:hover { background: var(--karte-2); border-color: var(--kante-2); }
.btn.gefahr { background: transparent; color: var(--rose); border-color: rgba(251, 113, 133, .55); }
.btn.gefahr:hover { background: rgba(251, 113, 133, .12); }
/* "schmal", nicht "klein": .klein ist weiter unten die Textgroesse fuer grauen
   Beitext. Beide Bedeutungen unter einem Namen faerbten den Knopftext grau. */
.btn.schmal { padding: .3rem .75rem; font-size: .78rem; }
.btn:disabled { opacity: .45; cursor: not-allowed; }
form.inline { display: inline; }
.suche { display: flex; gap: .5rem; }
.suche input { max-width: 340px; }

/* --- Detailansichten */
.dl { display: grid; grid-template-columns: max-content 1fr; gap: .4rem 1.3rem; margin: 0; font-size: .93rem; }
.dl dt { color: var(--muted); }
.dl dd { margin: 0; font-weight: 500; }
/* Auf schmalen Fenstern UNTEREINANDER statt nebeneinander.
   `max-content` nimmt sich die Breite des laengsten Begriffs, egal wie schmal das Fenster
   ist - bei 320 px ragte die Liste 45 bis 75 px hinaus, und die SEITE rollte waagerecht.
   Dass `body` overflow-x: hidden traegt, hat das NICHT verhindert: die Rolle entsteht auf
   `html`, und dort steht overflow-x: visible. Beides gemessen am 26.09.2026 mit einem
   echten Browser auf 320 px (WCAG 1.4.10 verlangt dort eine Richtung, nicht zwei).
   560 px ist die Grenze, an der auch das Dock schon umschaltet - EINE Schwelle statt
   zweier, die auseinanderlaufen. */
@media (max-width: 560px) {
  .dl { grid-template-columns: 1fr; gap: .15rem; }
  /* Ein Abstand VOR dem Begriff, nicht nach der Beschreibung: so bleibt der erste
     Eintrag oben ohne Vorsprung, und zwischen den Paaren entsteht trotzdem Luft. */
  .dl dt + dd { margin-bottom: .55rem; }
}
.klein { font-size: .84rem; color: var(--muted); }
.zeilenumbruch { white-space: pre-line; }
.ok { color: var(--gruen); font-weight: 600; }
.nein { color: var(--rose); font-weight: 600; }

/* --- Schrittlisten (ul.schritte) */
ul.schritte { list-style: none; padding: 0; margin: .5rem 0 0; }
ul.schritte li { display: flex; gap: .7rem; align-items: flex-start; padding: .55rem 0; border-bottom: 1px solid var(--rand); font-size: .92rem; }
ul.schritte li:last-child { border-bottom: none; }
ul.schritte .marke-offen { flex: none; width: 17px; height: 17px; border: 1.5px solid var(--kante); border-radius: 5px; margin-top: .1rem; }
ul.schritte .marke-fertig { flex: none; width: 17px; height: 17px; border-radius: 5px; background: var(--gold); color: var(--auf-gold); display: grid; place-items: center; margin-top: .1rem; }
ul.schritte .marke-fertig svg { width: 11px; height: 11px; fill: none; stroke: currentColor; stroke-width: 2.6; stroke-linecap: round; stroke-linejoin: round; }
ul.schritte li.fertig span:not(.marke-fertig) { color: var(--muted); text-decoration: line-through; }

/* --- Anmeldung: eine Glaskarte vor den Lichtflecken */
.anmelde-seite { min-height: 100vh; display: grid; place-items: center; padding: 1rem; }
.anmelde-karte {
  background: var(--fenster); border: 1px solid var(--rand); border-radius: 24px; padding: 2rem;
  width: min(410px, 100%); backdrop-filter: blur(30px) saturate(140%); box-shadow: 0 30px 70px rgba(0,0,0,.45);
}
.anmelde-karte .marke { text-align: center; }
.anmelde-karte .marke-bild { display: inline-block; vertical-align: top; width: 200px; height: auto; margin-bottom: 1rem; }  /* inline: zentriert ueber text-align, ohne margin:auto, das als krummer Abstand zaehlt */
.anmelde-karte .marke span { display: block; font-size: .62rem; letter-spacing: .24em; text-transform: uppercase; color: var(--muted); border-top: 1px solid var(--rand); margin-top: .5rem; padding-top: .45rem; margin-bottom: 1.5rem; }
.anmelde-karte input { font-size: 1.02rem; }
.anmelde-karte .btn { width: 100%; padding: .8rem; margin-top: .4rem; font-size: 1rem; }
.qr { display: block; margin: .7rem 0; border: 1px solid var(--rand); border-radius: 14px; background: #fff; padding: 6px; }

/* --- Dock unten: Schnellzugriff */
/* Die Leiste schwebt UEBER dem Inhalt. Beim Springen mit der Tastatur landete das
   fokussierte Feld darunter und war vollstaendig verdeckt - gemessen mit der
   Zustandsprobe auf drei Seiten, bei 375 px und bei 1280 px (WCAG 2.4.11, seit 2.2
   verbindlich). Der Scroll-Rand sagt dem Browser, dass die unteren 110 px nicht als
   "sichtbar" zaehlen; er scrollt beim Fokussieren dann daran vorbei.
   110 px = 18 unten + 64 Leiste + 28 Luft. Schmal (bis 560 px) MEHR: dort bricht das
   Dock in zwei Zeilen um - 120 px = 18 unten + 90 Dock + 12 Luft. */
html { scroll-padding-bottom: 110px; }
@media (max-width: 560px) { html { scroll-padding-bottom: 120px; } }

/* Mittig ueber left/right + margin auto statt left:50% + translateX(-50%): so darf das Dock
   die ganze Fensterbreite nutzen und bei Bedarf UMBRECHEN. Mit der alten Zentrierung stand
   ihm nur die halbe Breite zur Verfuegung - es ragte auf dem Telefon hinaus (T-044), und ein
   Umbruch haette drei bis vier Zeilen ergeben (Plan-Review 07.10.2026). */
.dock {
  position: fixed; left: 8px; right: 8px; bottom: 18px; z-index: 5;
  width: fit-content; margin-inline: auto;
  background: rgba(17, 21, 30, .80); border: 1px solid var(--rand); border-radius: 20px;
  padding: 10px 16px; display: flex; flex-wrap: wrap; justify-content: center; gap: 14px;
  backdrop-filter: blur(16px); box-shadow: 0 18px 50px rgba(0,0,0,.5);
}
/* Nur die direkten Kinder: im Link sitzt ein eigenes <span> um das Sinnbild, damit
   Vorleseprogramme den Namen aus aria-label nehmen und nicht "Haus" sagen. Ein
   Nachfahren-Selektor faerbte dieses innere <span> mit aus. */
.dock > a, .dock > span, .dock button {
  width: 42px; height: 42px; border-radius: 12px; display: grid; place-items: center;
  font-size: 1.15rem; text-decoration: none; color: var(--muted); transition: .2s;
}
.dock a:hover, .dock button:hover { color: #fff; background: var(--karte-2); transform: translateY(-3px); }
.dock a.aktiv { background: var(--karte-2); color: var(--ink); box-shadow: inset 0 0 0 1px var(--kante); }
.dock a:focus-visible, .dock button:focus-visible { outline: none; box-shadow: var(--fokus); }
.dock > span { opacity: .3; cursor: default; filter: grayscale(1); }
.dock form { display: flex; }
.dock button { background: none; border: none; cursor: pointer; padding: 0; font-family: inherit; }
.dock button svg { width: 19px; height: 19px; fill: none; stroke: currentColor; stroke-width: 1.9; stroke-linecap: round; stroke-linejoin: round; }
/* Kompakt ab derselben Grenze, an der die Leiste zum Querstreifen wird: so passt das Dock
   ab 472 px nutzbarer Breite in eine Zeile (11 Ziele; mit einer festen Bildlaufleiste ab
   etwa 490 px Fenster), darunter in genau zwei. Gross (42 px) waere es schon zwischen 561
   und 651 px breiter als das Fenster gewesen. */
@media (max-width: 860px) { .dock { gap: 6px; padding: 7px 10px; } .dock > a, .dock > span, .dock button { width: 34px; height: 34px; } }
/* Zwei Zeilen sind 90 px hoch, dazu 18 px Abstand unten: der Inhalt endet darueber, und ein
   angesprungenes Element rollt nicht darunter (test/kontrast.test.js, Ruhezustand). */
@media (max-width: 560px) { .shell { margin-bottom: 124px; } }

/* Solange jemand IM INHALT tippt, tritt die Leiste beiseite.
   Der Scroll-Rand oben reicht nicht fuer ein Feld, das hoeher ist als der Rest des
   Fensters: das Impressum-Feld ist 197 px hoch, und auf einem schmalen Fenster lag es
   auch nach dem Scrollen noch unter der Leiste (gemessen, WCAG 2.4.11).
   Reines CSS ueber :has() - ein Skript waere hier die teurere Loesung, und die
   Inhaltssicherheitsregel dieses Hauses laesst ohnehin kein Inline-Skript zu.
   Der Uebergang laeuft weich, damit das Wegtreten nicht wie ein Fehler aussieht;
   wer Bewegung abbestellt hat, bekommt ihn ohne. */
/* :focus NEBEN :focus-visible, und das ist kein Gürtel-und-Hosenträger.
   :focus-visible entsteht nur bei Tastaturbedienung. Ein Fokus, den das PROGRAMM setzt -
   etwa wenn nach einer fehlgeschlagenen Eingabe in das beanstandete Feld gesprungen wird -
   traegt ihn NICHT. Genau dann liegt das Feld aber womoeglich unter der Leiste, und genau
   dann braucht es der Mensch. Gemessen am 26.09.2026: mit echtem TAB tritt die Leiste
   beiseite (Deckkraft 0), mit element.focus() nicht.
   Der Preis: wer auf dem Telefon einen Knopf im Inhalt antippt, sieht die Leiste kurz
   weggehen. Das ist der billigere der beiden Fehler. */
body:has(.inhalt :is(:focus, :focus-visible)) .dock { opacity: 0; pointer-events: none; }
.dock { transition: opacity .18s ease; }
@media (prefers-reduced-motion: reduce) { .dock { transition: none; } }

/* Wer im System weniger Bewegung eingestellt hat, bekommt keine. Das Fenster nimmt
   gleich die Bewegungen mit, die vorher schon im Blatt standen. */
@media (prefers-reduced-motion: reduce) {
  .rail, .rail .klapp svg, .btn, .dock > a, .dock button, .sprung, .g-zettel, .g-ring-bogen { transition: none; }
  .btn:hover, .dock a:hover, .dock button:hover, .g-zettel:hover { transform: none; }
}

/* --- Kalender: Wochenansicht. Tage als Zeilen, Raeume als Spalten - der Engpass der
       Praxis ist der Raum, und bei vier Raeumen und zwei Behandlern passen die
       Behandler als Farbstreifen in die Kachel. */
.woche { table-layout: fixed; }
/* 120 px: „08:00–20:00“ braucht in der echten Schrift auch normal gesetzt 82 px, bei 110 px blieben
   nur 81,2 px (T-070). */
.woche .tagspalte { width: 120px; vertical-align: top; }
.woche tr.heute > th, .woche tr.heute > td { background: rgba(242, 196, 107, .06); }
.woche .zelle { vertical-align: top; padding: .5rem; min-height: 64px; }

/* Der Farbstreifen links ist die Kennfarbe des Behandlers (in der Vorlage gesetzt);
   Gold nur, wo jemand keine eigene hat. */
.termin {
  display: block; text-decoration: none; color: var(--ink);
  background: var(--karte-2); border: 1px solid var(--rand); border-left: 3px solid var(--gold);
  border-radius: 10px; padding: .45rem .6rem; margin-bottom: .4rem; transition: background .15s;
}
.termin:hover { background: rgba(255, 255, 255, .14); }
.termin:focus-visible { outline: none; box-shadow: var(--fokus); }
.termin b { display: block; font-size: .8rem; font-variant-numeric: tabular-nums; }
.termin span { display: block; font-size: .88rem; font-weight: 600; }
.termin em { display: block; font-style: normal; font-size: .74rem; color: var(--muted); margin-top: 1px; }   /* --leise kam auf der Kachel auf 4,44:1 */
/* Abgesagt bleibt lesbar, tritt aber zurueck: der Termin ist Geschichte, keine Aufgabe. */
.termin.abgesagt { opacity: .55; }
.termin.abgesagt b, .termin.abgesagt span { text-decoration: line-through; }

/* Der Platz zum Eintragen. Unaufdringlich, aber mit 32px hoch genug fuer einen Finger. */
.zelle .frei {
  display: block; text-align: center; color: var(--leise); text-decoration: none;
  border: 1px dashed var(--rand); border-radius: 10px; padding: .3rem; min-height: 32px;
  font-size: 1rem; line-height: 1.6;
}
.zelle .frei:hover { color: var(--ink); border-color: var(--gold); background: var(--karte-2); }
.zelle .frei:focus-visible { outline: none; box-shadow: var(--fokus); }

.punkt { display: inline-block; width: 10px; height: 10px; border-radius: 50%; vertical-align: baseline; }

@media (max-width: 860px) {
  /* Quer wird die Wochentabelle zu schmal. Sie rollt in ihrem Rahmen, statt die
     Spalten auf Unlesbarkeit zu stauchen. */
  .woche { table-layout: auto; min-width: 640px; }
}

/* Kennfarbe im Kalender. 44px, damit es am Empfang mit dem Finger trifft (WCAG 2.5.8
   verlangt 24). Die Auswahl zeigt sich als Ring, nicht als Haken - ein Haken auf
   farbigem Grund braucht wieder eigenen Kontrast. */
.farbwahl {
  width: 44px; height: 44px; border-radius: 13px; border: 2px solid transparent;
  cursor: pointer; padding: 0; transition: transform .12s, box-shadow .15s;
}
.farbwahl:hover { transform: translateY(-2px); }
.farbwahl.gewaehlt { box-shadow: 0 0 0 3px var(--bg), 0 0 0 5px var(--ink); }
.farbwahl:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--bg), 0 0 0 6px #FFFFFF; }

/* Abwesenheit in der Tagesspalte der Wochenansicht. Sie haengt am Behandler und
   passt deshalb in keine Raumspalte. */
.abwesend {
  display: block; text-decoration: none; margin-top: .35rem; padding: .25rem .45rem;
  border-radius: 8px; background: rgba(255, 213, 74, .10); border: 1px solid rgba(255, 213, 74, .30);
  color: var(--ink); font-size: .74rem; line-height: 1.3;
}
.abwesend:hover { background: rgba(255, 213, 74, .18); }
.abwesend:focus-visible { outline: none; box-shadow: var(--fokus); }
.abwesend em { display: block; font-style: normal; color: #E8D08F; }
/* Ein Feld, das gerade keine Rolle spielt. Nicht versteckt, damit die Zeile nicht
   springt - nur zurueckgenommen. */
.feld.stumm { opacity: .45; }
/* Ein Termin, dessen Behandler inzwischen abwesend ist. Er wird NICHT automatisch
   abgesagt - die Kundin erfuehre nichts davon -, darf aber auch nicht still
   dastehen, als waere alles in Ordnung. */
.termin.kollidiert { border-color: rgba(255, 213, 74, .55); background: rgba(255, 213, 74, .08); }
.termin.kollidiert:hover { background: rgba(255, 213, 74, .14); }

/* --- Kalender: Umschalter Tag | Woche, Feiertag, Online-Angebot (T-023, T-024, T-026). */
.umschalter { display: inline-flex; border: 1px solid var(--kante); border-radius: 10px; overflow: hidden; }
.umschalter a {
  display: inline-flex; align-items: center; min-height: 36px; padding: 0 .85rem;
  color: var(--ink); text-decoration: none; font-size: .88rem; font-weight: 600;
}
.umschalter a + a { border-left: 1px solid var(--kante); }
.umschalter a[aria-current="page"] { background: var(--gold); color: var(--auf-gold); }
.umschalter a:not([aria-current]):hover { background: var(--karte-2); }
/* Innen gezeichnet: overflow:hidden schnitte einen Ring aussen ab. */
.umschalter a:focus-visible { outline: none; box-shadow: inset 0 0 0 3px rgba(255, 255, 255, .92); }

.feiertag { display: block; margin-top: .3rem; color: var(--gold); font-size: .76rem; font-weight: 700; }
.feiertag-band {
  margin: 0 0 1rem; padding: .65rem .9rem; border-radius: 12px;
  background: rgba(242, 196, 107, .10); border: 1px solid rgba(242, 196, 107, .35);
}
.feiertag-band .feiertag { display: inline; margin: 0; font-size: inherit; }

/* Woche: der Tagesname fuehrt zur Tagesansicht; die Zeile ist grau, wenn die Website an
   diesem Tag niemanden anbietet - die Woche hat keine Zeitachse (ANNAHME D14). */
.woche .tag-link { color: inherit; text-decoration: none; display: inline-block; border-radius: 6px; }
.woche .tag-link:hover b { text-decoration: underline; }
.woche .tag-link:focus-visible { outline: none; box-shadow: var(--fokus); }
/* Normal statt fett (aus th geerbt) als Reserve: in 120 px Spalte (91,2 px Inhalt) braucht „08:00–20:00“
   fett 87 px, normal 82 px - 4 statt 9 px Luft (T-070, gemessen mit geladener Plus Jakarta Sans). */
.woche .angebot { display: block; margin-top: .3rem; font-size: .72rem; font-weight: 400; color: var(--muted); }
/* Die Tageskopfzelle setzt Grossbuchstaben - Feiertag, Angebot und Abwesenheit (Name und Grund)
   sind Saetze, keine Etiketten. Und .daten th verbietet den Umbruch: ohne white-space ragte
   „online 08:00–20:00“ 20 px, eine Fortbildung mit langem Namen bis 71 px in die erste
   Raumspalte, bei jeder Fensterbreite (T-070). */
.woche .angebot, .woche .feiertag, .woche .abwesend { text-transform: none; letter-spacing: normal; white-space: normal;
  hyphens: auto; overflow-wrap: break-word; }
/* Lange Woerter („Weihnachtstag“, ein Nachname ohne Bindestrich) werden nach deutscher Regel getrennt
   (<html lang="de">); break-word nur als letzte Rettung, falls die Trennung nichts findet (Kalt-Review 2l). */
.woche tr.niemand > td, .woche tr.niemand > th { background: rgba(4, 6, 10, .45); }

/* --- Kalender: Tagesansicht. Eine Spalte je Person, die Kopfzeilen aller Spalten gleich hoch
       (subgrid), darunter das Raster: 56px je Stunde. Auf dem Telefon rollt es in seinem
       Rahmen, statt die Spalten zu stauchen. */
.tagwrap { overflow-x: auto; border: 1px solid var(--rand); border-radius: var(--radius); background: var(--karte); }
.tagesraster {
  display: grid; grid-template-rows: auto auto;
  grid-template-columns: 52px repeat(var(--spalten), minmax(150px, 1fr));
  min-width: calc(52px + var(--spalten) * 150px);
}
.tagesraster > .stundenleiste, .tagesraster > .person { grid-row: 1 / span 2; display: grid; grid-template-rows: subgrid; }
.tagesraster > .person { border-left: 1px solid var(--rand); }
.tagesraster .flaeche { position: relative; height: calc(var(--stunden) * 56px); }
.stundenleiste span {
  position: absolute; right: .45rem; padding-top: 2px;
  font-size: .72rem; color: var(--muted); font-variant-numeric: tabular-nums;
}
.person-kopf { padding: .6rem .65rem; border-bottom: 1px solid var(--rand); display: flex; flex-direction: column; gap: .15rem; }
.person-kopf .abwesend { margin-top: .2rem; }
.stundenlinie { position: absolute; left: 0; right: 0; border-top: 1px solid rgba(255, 255, 255, .06); }
/* Grau: hier bietet die Website die Person nicht an. Abgedunkelt, nicht verdeckt - eine
   Kachel darin bleibt voll lesbar (sie liegt darueber). */
.ausserhalb { position: absolute; left: 0; right: 0; background: rgba(4, 6, 10, .55); }
.abwesend-block {
  position: absolute; left: 0; right: 0;
  background: repeating-linear-gradient(135deg, rgba(255, 213, 74, .16) 0 6px, transparent 6px 12px);
  border-top: 1px solid rgba(255, 213, 74, .35); border-bottom: 1px solid rgba(255, 213, 74, .35);
}
.flaeche .termin { position: absolute; margin: 0; overflow: hidden; padding: .3rem .45rem; z-index: 1; }
/* Unter 45 Minuten reicht die Hoehe fuer eine Zeile: Uhrzeit und Name nebeneinander. */
.flaeche .termin.knapp { white-space: nowrap; text-overflow: ellipsis; padding-top: .2rem; padding-bottom: .2rem; }
.flaeche .termin.knapp b, .flaeche .termin.knapp span { display: inline; }
.flaeche .termin.knapp > span { margin-left: .35rem; }
.flaeche .termin.knapp em, .flaeche .termin.knapp .badge { display: none; }

/* Teilnehmer eines Termins. Ein abgesagter bleibt lesbar, tritt aber zurueck -
   bei einem Workshop faellt der Termin nicht, weil einer nicht kann. */
.teilnehmer { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; margin-bottom: .35rem; }
.teilnehmer.abgesagt { opacity: .55; }
.teilnehmer.abgesagt .link { text-decoration: line-through; }
/* Mehrfachauswahl: hoch genug, dass mehrere Namen ohne Rollen sichtbar sind. */
select[multiple] { min-height: 180px; padding: .4rem; }

/* Der Mailtext steht so da, wie er hinausginge - nicht umformatiert. */
.mailtext {
  white-space: pre-wrap; font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
  font-size: .84rem; line-height: 1.55; background: var(--karte-2);
  border: 1px solid var(--rand); border-radius: 12px; padding: 1rem; margin: 1rem 0 0;
  overflow-x: auto;
}

/* --- Reiter innerhalb eines Bereichs
   Fuer Bereiche, die fachlich zusammengehoeren, aber nicht auf eine Seite passen -
   Gutscheine, Mehrfachkarten, Kartenarten. Nicht in die Seitenleiste: die traegt die
   BEREICHE, und sie waere sonst bei jedem neuen Baustein um eine Zeile laenger.
   Die Zielgroesse liegt bei 44 px Hoehe, also ueber den 24 px aus WCAG 2.5.8 - hier
   stehen mehrere Ziele dicht nebeneinander, und dann zaehlt der Abstand mit. */
.reiter { display: flex; flex-wrap: wrap; gap: .4rem; margin: 0 0 18px; border-bottom: 1px solid var(--rand); }
.reiter a {
  padding: .7rem 1.05rem; border-radius: 12px 12px 0 0; text-decoration: none;
  color: var(--muted); font-weight: 600; font-size: .92rem; line-height: 1.4;
  border: 1px solid transparent; border-bottom: none; margin-bottom: -1px;
}
.reiter a:hover { color: var(--ink); background: var(--karte-2); }
.reiter a[aria-current="page"] {
  color: var(--ink); background: var(--karte); border-color: var(--kante);
}
.reiter a:focus-visible { outline: 2px solid #FFFFFF; outline-offset: -2px; box-shadow: none; }

/* --- Geldzeilen
   Eine Summe steht rechts und in gleich breiten Ziffern, damit zwei Zahlen
   untereinander vergleichbar sind. Negative Betraege (Storno) tragen die Farbe nicht
   ALLEIN: das Minus steht davor, sonst haengt die Aussage an der Farbwahrnehmung. */
.geld { font-variant-numeric: tabular-nums; white-space: nowrap; }
.geld.minus { color: var(--rose); }
.summenzeile { display: flex; justify-content: space-between; gap: 1.5rem; padding: .35rem 0; }
.summenzeile.gesamt { border-top: 1px solid var(--rand); margin-top: .4rem; padding-top: .6rem; font-weight: 800; font-size: 1.05rem; }
.summenzeile .name { color: var(--muted); }
.summenzeile.gesamt .name { color: var(--ink); }

/* --- Die Uebersicht (Startseite): Tagesplan, Ring, Zettel, Kalender, Bestand -------------------------------------------------------- */
.g-kopf { display: flex; justify-content: space-between; align-items: flex-start; gap: 16px; flex-wrap: wrap; margin-bottom: 16px; }
.g-kopf h1 { font-size: 1.6rem; font-weight: 700; letter-spacing: -.01em; }
.g-name { color: var(--gold); }
.g-unter { margin: 4px 0 0; color: var(--muted); font-size: .9rem; }
.g-uhr { font-size: 2rem; font-weight: 700; line-height: 1; font-variant-numeric: tabular-nums; letter-spacing: -.01em; }

.g-werkzeug { display: flex; flex-wrap: wrap; gap: 12px; margin-bottom: 24px; }
.g-suche { position: relative; display: flex; flex: 1 1 260px; }
.g-suche svg {
  position: absolute; left: 12px; top: 12px; width: 17px; height: 17px;
  fill: none; stroke: var(--muted); stroke-width: 1.8; stroke-linecap: round; pointer-events: none;
}
/* Nur Hoehe und Platz fuer die Lupe - Kante, Hover und Fokus kommen aus der allgemeinen
   Feldregel. Eine eigene border-Angabe hier stand spaeter bei gleicher Spezifitaet und hat
   den weissen Fokusrand still abgeschaltet (test/kontrast.test.js, Fokus an der Kante). */
.g-suche input { height: 42px; padding: 0 12px 0 40px; }

.g-knopf {
  display: inline-flex; align-items: center; min-height: 42px; padding: 0 16px; border-radius: 12px;
  font-weight: 700; font-size: .9rem; white-space: nowrap; text-decoration: none;
  color: var(--gold); background: rgba(242, 196, 107, .08); border: 1px solid rgba(242, 196, 107, .55);
}
.g-knopf:hover { background: rgba(242, 196, 107, .18); color: #FFE2A6; }
.g-knopf:active { background: rgba(242, 196, 107, .26); }
.g-knopf.schmal { min-height: 32px; padding: 0 12px; font-size: .82rem; }
.g-link {
  display: inline-flex; align-items: center; min-height: 32px; color: var(--ink-2); font-weight: 600; font-size: .84rem;
  text-decoration: underline; text-underline-offset: 3px; text-decoration-color: rgba(255, 255, 255, .4);
}
.g-link:hover { color: #FFFFFF; text-decoration-color: currentColor; }


.g-block { margin-bottom: 28px; }
.g-abschnitt { font-size: .95rem; font-weight: 700; margin: 0 0 12px; }
.g-abschnitt small { color: var(--muted); font-weight: 600; font-size: .8em; }
.g-karte h3 {
  display: flex; justify-content: space-between; align-items: baseline; gap: 8px;
  margin: 0 0 12px; font-size: .9rem; font-weight: 700;
}
.g-hinweis { color: var(--muted); font-weight: 500; font-size: .8rem; }
.g-label { margin: 4px 0 0; color: var(--muted); font-size: .84rem; }
.g-leer { margin: 0; color: var(--muted); font-size: .9rem; }

/* Heute: Tagesplan | Naechster Termin | Zahlen */
.g-heute { display: grid; grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr) minmax(0, 1fr); gap: 16px; }
.g-slots { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
/* Ein Termin als Raster: Farbstreifen | Zeit | Wer und Was | Marke. Auf dem Telefon rueckt
   die Marke neben die Zeit, und Wer/Was bekommen die ganze Breite (unten) - nebeneinander
   blieben dort fuer "Rueckenmassage" kaum 150 px, und das Wort brach mitten durch. */
.g-slot {
  display: grid; grid-template-columns: 4px minmax(52px, auto) minmax(0, 1fr) auto;
  grid-template-areas: "balken zeit was status"; column-gap: 12px;
  padding: 12px; border-radius: 12px; background: var(--karte); box-shadow: inset 0 0 0 1px transparent;
}
.g-balken { grid-area: balken; border-radius: 4px; background: var(--muted); }
.g-zeit { grid-area: zeit; color: var(--muted); font-size: .8rem; font-variant-numeric: tabular-nums; }
.g-zeit b { display: block; color: var(--ink); font-size: .95rem; }
.g-was { grid-area: was; min-width: 0; }
.g-wer {
  display: inline-block; min-height: 24px; line-height: 24px; font-weight: 700; font-size: .95rem;
  color: var(--ink); text-decoration: none; overflow-wrap: anywhere;
}
a.g-wer:hover { text-decoration: underline; text-underline-offset: 3px; }
.g-info { display: block; color: var(--muted); font-size: .8rem; overflow-wrap: anywhere; }
.g-status { grid-area: status; display: flex; flex-direction: column; align-items: flex-end; justify-content: center; gap: 4px; }
.g-laeuft { display: none; color: var(--gold); font-size: .78rem; font-weight: 700; }
.g-slot.laeuft { background: rgba(242, 196, 107, .10); box-shadow: inset 0 0 0 1px rgba(242, 196, 107, .62); }
.g-slot.laeuft .g-laeuft { display: block; }
/* Vorbei: die Flaeche tritt zurueck und der Farbstreifen verblasst - die SCHRIFT bleibt
   lesbar hell (Kontrast in test/kontrast.test.js gemessen). */
.g-slot.vorbei { background: rgba(255, 255, 255, .025); }
.g-slot.vorbei .g-balken { opacity: .35; }
.g-slot.vorbei .g-zeit b, .g-slot.vorbei .g-wer { color: var(--ink-2); }
.g-fuss { margin: 12px 0 0; }
.g-veraltet {
  margin: 12px 0 0; padding: 8px 16px; border-radius: 12px; font-size: .9rem;
  background: rgba(255, 213, 74, .12); border: 1px solid rgba(255, 213, 74, .45);
}
.g-veraltet a { color: var(--gelb); font-weight: 700; }

.g-ringwrap { display: grid; place-items: center; padding: 4px 0; }
.g-ring { position: relative; width: 132px; height: 132px; }
.g-ring svg { display: block; transform: rotate(-90deg); }
.g-ring-spur { stroke: rgba(255, 255, 255, .10); }
.g-ring-bogen { stroke: var(--gold); transition: stroke-dashoffset .4s ease; }
.g-ring-mitte { position: absolute; inset: 0; display: grid; place-items: center; text-align: center; }
.g-ring-zahl { display: block; font-size: 1.35rem; font-weight: 700; font-variant-numeric: tabular-nums; }
.g-ring-text { display: block; color: var(--muted); font-size: .76rem; }
.g-naechster { margin: 12px 0 0; text-align: center; color: var(--muted); font-size: .86rem; overflow-wrap: anywhere; }
.g-naechster b { color: var(--ink); }

.g-gross { font-size: 2rem; font-weight: 700; line-height: 1.1; font-variant-numeric: tabular-nums; }
.g-zahlen dl { margin: 12px 0 0; }
.g-zahlen dl div { display: flex; justify-content: space-between; gap: 8px; padding: 4px 0; font-size: .86rem; }
.g-zahlen dt { color: var(--muted); }
.g-zahlen dd { margin: 0; font-weight: 700; font-variant-numeric: tabular-nums; }

/* Was haengt: angeheftete Zettel. Dringendes orange, das Uebrige gelb - beide mit dunkler
   Schrift (orange #2B1700 und gelb #2B2200, je deutlich ueber 7:1). */
.g-zettel-raster { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 16px; }
.g-zettel {
  position: relative; display: flex; flex-direction: column; min-height: 132px; padding: 16px 16px 12px;
  border-radius: 12px; text-decoration: none; overflow: hidden;
  box-shadow: 0 14px 30px rgba(0, 0, 0, .35); transition: transform .15s ease;
}
.g-zettel::before {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(160deg, rgba(255, 255, 255, .22), rgba(255, 255, 255, 0) 55%);
}
.g-zettel::after {
  content: ""; position: absolute; right: 0; bottom: 0; width: 24px; height: 24px; pointer-events: none;
  background: linear-gradient(315deg, rgba(12, 16, 24, .78) 50%, rgba(255, 255, 255, .38) 50%);
  border-top-left-radius: 8px;
}
.g-zettel:hover { transform: translateY(-2px); }
.g-zettel p { position: relative; margin: 0; font-size: .9rem; font-weight: 600; line-height: 1.4; overflow-wrap: anywhere; }
.g-tags { position: relative; display: flex; flex-wrap: wrap; gap: 4px; margin-top: 8px; }
.g-tags span { padding: 4px 8px; border-radius: 999px; font-size: .74rem; font-weight: 700; }
.g-ansehen { position: relative; flex: 1; display: flex; align-items: flex-end; padding-top: 12px; font-size: .8rem; font-weight: 700; }
.g-zettel.orange { background: var(--orange); color: #2B1700; }
.g-zettel.orange .g-tags span { background: rgba(70, 35, 0, .16); color: #3A1E00; }
.g-zettel.gelb { background: var(--gelb); color: #2B2200; }
.g-ruhe { margin: 0; color: var(--muted); font-size: .9rem; }

/* Kalender und Bestand */
.g-unten { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 16px; align-items: start; }
.g-kal-kopf { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; }
.g-kal-kopf b { font-size: .9rem; }
.g-rund {
  display: grid; place-items: center; width: 32px; height: 32px; padding: 0; border-radius: 50%;
  color: var(--ink-2); background: transparent; border: 0; cursor: pointer;
}
.g-rund:hover { background: rgba(255, 255, 255, .07); box-shadow: inset 0 0 0 1px var(--kante); }
.g-rund svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.g-kal { width: 100%; border-collapse: collapse; font-size: .8rem; text-align: center; font-variant-numeric: tabular-nums; }
.g-kal th { padding: 4px 0; color: var(--leise); font-weight: 600; }
.g-kal td { padding: 4px 0; }
.g-kal td a, .g-kal td span {
  display: inline-grid; place-items: center; width: 28px; height: 28px; border-radius: 8px;
  color: var(--ink); text-decoration: none;
}
.g-kal td.blass a, .g-kal td.blass span { color: var(--leise); }
.g-kal td a:hover { background: rgba(255, 255, 255, .08); box-shadow: inset 0 0 0 1px var(--kante); }
.g-kal td [aria-current="date"] { background: var(--gold); color: var(--auf-gold); font-weight: 700; }

/* Bestand als Ordner: Karte mit Reiter oben links */
.g-ordner { position: relative; margin-top: 12px; border-top-left-radius: 6px; }
.g-ordner::before {
  content: ""; position: absolute; left: -1px; top: -13px; width: 44%; height: 13px;
  border: 1px solid var(--rand); border-bottom: 0; border-radius: 10px 10px 0 0; background: var(--karte);
}
.g-wert { font-size: 2rem; font-weight: 700; line-height: 1.1; font-variant-numeric: tabular-nums; }
.g-links { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; margin-top: 12px; }

.g-auftrag summary { min-height: 24px; cursor: pointer; }
.g-auftrag p { margin: 12px 0 0; color: var(--muted); font-size: .86rem; }

/* --- Schmalere Fenster ------------------------------------------------------------------
   Drei Spalten brauchen gut 900 px Inhalt; mit der beschrifteten Leiste ist das ab etwa
   1280 px Fensterbreite der Fall. */
@media (max-width: 1279px) {
  .g-heute { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .g-plan { grid-column: 1 / -1; }
  .g-unten { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .g-kalender { grid-column: 1 / -1; }
}
@media (max-width: 1100px) {
  .g-zettel-raster { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 640px) {
  .g-heute, .g-unten, .g-zettel-raster { grid-template-columns: 1fr; }
  .g-slot {
    grid-template-columns: 4px minmax(0, 1fr) auto; grid-template-areas: "balken zeit status" "balken was was"; row-gap: 4px;
  }
  .g-zeit b { display: inline; margin-right: 8px; }
  .g-status { flex-direction: row; align-items: center; }
  .g-kopf h1 { font-size: 1.35rem; }
  .g-uhr { font-size: 1.6rem; }
}
