/* Tageslicht, in eurem Firmenrot.

   Das Werkzeug wird tagsüber im Büro bedient: helle Fläche, dunkle Schrift.
   Aufbau und Benennung wie im CMS der App, damit sich beide Werkzeuge wie
   Geschwister anfühlen. Nur der Akzent ist eurer, nicht der Lavendel der App.

   Zwei Töne statt einem: Das Firmenrot steht auf Flächen mit weißer Schrift
   darauf (4,75 zu 1). Als Schrift auf hellem Grund liegt es mit 4,44 knapp
   unter der Lesbarkeitsschwelle, dafür gibt es --akzent-schrift, einen Hauch
   dunkler. Sichtbar ist der Unterschied nicht, messbar schon.

   Das Warnrot ist bewusst weit weg vom Firmenrot. Sonst wäre nicht mehr zu
   unterscheiden, ob eine rote Zahl zur Marke gehört oder ein Minus bedeutet.

   Alles hängt an diesen Werten, die Bauteile kennen nur die Namen. */
:root {
  --grund: #fbf6f8;
  --erhoben: #ffffff;
  --rand: #f0e2e7;
  --schrift: #241a1e;
  --leise: #7c6a70;
  --akzent: #e50146;
  --akzent-schrift: #d40140;
  --akzent-hell: #ffd9e2;
  /* Die überfahrene Tabellenzeile: ein ganz zartes Grau (Florian,
     04.10.2026). Neutral und nicht rosa, damit die Zeile sich absetzt,
     ohne nach Auswahl oder Warnung auszusehen. */
  --zeile-hover: var(--flaeche-2);
  --gold: #8a6210;
  --vorschlag-grund: #e4edf8;
  --vorschlag-schrift: #1d4f91;
  --gold-hell: #f0c88f;
  --warn: #9f1239;
  --gut: #1f7a5a;
  /* Flaechen fuer Marken, Meldungen und das Abwesenheitsraster. Als
     Namen, damit Dunkel sie tauschen kann (Florian, 30.10.2026). */
  --gut-flaeche: #e3f4ec;
  --warn-flaeche: #fbe6ea;
  --gold-flaeche: #fdf0da;
  --frei: #ece6e9;
  --feiertag: #bdd4ee;
  --krank: #e3a21f;
  --kind-krank: #f6dc9c;
  --neutral-hover: #f3f1f2;
  /* Erhoben ueber einer Karte (Fenster, Listen, Kalender), die tiefe
     Hausfarbe fuer den Fokus voller Knoepfe, der Schleier hinter einem
     Fenster, die zweite Diagrammfarbe und das Ende der Farbstufen in
     Ringen und Rastern (Prüfung, 31.10.2026). */
  --erhoben-hoch: #ffffff;
  --akzent-tief: #b0013a;
  --schleier: rgb(36 26 30 / .35);
  --diagramm-zweit: #ffd9e2;
  --stufen-ende: #ffffff;
  /* Die Stufe eines Ring- oder Rasterstuecks setzt die Grafik je Stueck
     im style; voll, wo keine steht. */
  --stufe: 1;
  /* Die Farbe des Punkts vor einer Statusmarke; die Marke setzt sie. */
  --ton: var(--leise);
  color-scheme: light;

  --breite-leiste: 208px;
  /* Rundungen wie im CMS der App: Karten 16, Felder und kleine Flaechen
     12 (Florian, 07.10.2026). */
  --rundung: 14px;
  --rundung-klein: 10px;
  /* Auf hellem Grund trennt eine leise Kante die Karten besser als eine
     Linie allein. Derselbe Schatten wie dort, im Hausrot gemischt. */
  --kartenschatten: var(--schatten);
  /* Ein Abstand für alle Blöcke untereinander (Florian, 03.10.2026).
     Seit dem 07.10.2026 etwas knapper: Auf einem 13-Zoll-Bildschirm war
     sonst nur bei 90 Prozent alles zu sehen. Die Schrift bleibt, wie sie
     war; kleiner wurde der Leerraum. */
  --luft: 14px;

  /* Abgeleitete Toene wie im CMS der Einschlaf-App (Florian,
     30.10.2026). Keine neuen Farben, alles aus den Werten oben gemischt:
     zwei leise Flaechentoene, eine sehr leise Schrift, eine Akzentflaeche
     und zwei Schattenstufen. Getrennt wird mit Flaechen und Schatten,
     nicht mit Linien. */
  --flaeche-2: color-mix(in srgb, var(--grund) 45%, var(--rand));
  --flaeche-3: var(--rand);
  --sehr-leise: color-mix(in srgb, var(--leise) 68%, var(--erhoben));
  --akzent-flaeche: color-mix(in srgb, var(--akzent) 11%, var(--erhoben));
  --schatten:
    0 1px 2px color-mix(in srgb, var(--schrift) 5%, transparent),
    0 4px 16px color-mix(in srgb, var(--schrift) 6%, transparent);
  --schatten-hoch:
    0 2px 4px color-mix(in srgb, var(--schrift) 6%, transparent),
    0 12px 32px color-mix(in srgb, var(--schrift) 10%, transparent);
  /* Die Kurve fuer alles, was auf einen Druck antwortet. */
  --ease-out: cubic-bezier(0.23, 1, 0.32, 1);
  /* Die Kurve fuer die Leiste, die wie eine Schublade aus- und einfaehrt. */
  --ease-schublade: cubic-bezier(0.32, 0.72, 0, 1);
}

* { box-sizing: border-box; }

/* Knoepfe und Felder erben die Schrift. Ohne das standen DM Sans und die
   Systemschrift nebeneinander, je nachdem ob ein Knopf ein <a> oder ein
   <button> war (Prüfung nach Emil Kowalski, 30.10.2026). */
button, input, select, textarea { font: inherit; color: inherit; }

/* Ein Fokusring fuer alles, als Schatten und nicht als Rahmen: Felder
   bekommen einen Hof in der hellen Hausfarbe, Knoepfe einen Ring mit
   Abstand. Vorher verschwand der Fokus an der Zeitraumwahl ganz, und
   jedes Feld zeigte ihn anders. */
/* Felder: gefuellt statt umrandet. Beim Fokus wird die Flaeche hell und
   hebt sich mit einem weichen Schatten ab, wie im CMS der Einschlaf-App
   (Florian, 30.10.2026). */
:where(input:not([type="checkbox"], [type="radio"], [type="color"], [type="file"],
             [type="hidden"], [type="submit"], [type="button"]), select, textarea) {
  /* Mit !important, weil ein Dutzend aelterer Feldregeln je eigenen
     Rand und Grund setzt; so gilt die Fuellung ueberall gleich. */
  border: 0 !important; border-radius: var(--rundung-klein);
  background-color: var(--flaeche-2) !important;
}
:where(input, textarea)::placeholder { color: var(--sehr-leise); }
:where(input, select, textarea):focus {
  outline: none; background-color: var(--flaeche-3) !important;
}
/* Auswahlfelder mit eigenem Pfeil und Luft zum Rand. */
/* Mit !important, weil aeltere Feldregeln den Grund mit der Kurzform
   "background" setzen und den Pfeil damit still loeschten; an der
   Zeitraumwahl sah man nicht mehr, dass sie sich aufklappen laesst
   (Florian, 31.10.2026). */
select {
  appearance: none; -webkit-appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12' fill='none' stroke='%237c6a70' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 4.5 6 7.5 9 4.5'/%3E%3C/svg%3E") !important;
  background-repeat: no-repeat !important; background-position: right 12px center !important;
  background-size: 12px 12px !important; padding-right: 34px !important;
}
/* Im Dunkeln ein heller Pfeil. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) select {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12' fill='none' stroke='%23ab9ca3' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 4.5 6 7.5 9 4.5'/%3E%3C/svg%3E") !important;
  }
}
:root[data-theme="dark"] select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12' fill='none' stroke='%23ab9ca3' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 4.5 6 7.5 9 4.5'/%3E%3C/svg%3E") !important;
}
/* Tastaturfokus: eine Flaeche statt eines Rahmens, wie im
   Podcast-Studio. Knoepfe mit eigener Farbe werden dunkler. */
/* Der Fokus selbst steht am Ende der Datei, damit ihn keine spaetere
   Regel mit eigenem Hintergrund verschluckt. */

/* Was sich druecken laesst, gibt beim Druecken ein wenig nach. Dezent
   genug fuer dutzende Klicks am Tag. */
.knopf, .knopf-haupt, .knopf-warn, .knopf-leise, .reiter, .pille,
.seitenzahl, .klappknopf {
  transition: transform 160ms var(--ease-out), background-color 160ms var(--ease-out),
              color 160ms var(--ease-out);
}
.knopf:active, .knopf-haupt:active, .knopf-warn:active, .knopf-leise:active,
.reiter:active, .pille:active, .seitenzahl:active, .klappknopf:active {
  transform: scale(0.97);
}
@media (prefers-reduced-motion: reduce) {
  .knopf:active, .knopf-haupt:active, .knopf-warn:active, .knopf-leise:active,
  .reiter:active, .pille:active, .seitenzahl:active, .klappknopf:active {
    transform: none;
  }
}

/* Zahlen nebeneinander stehen Ziffer unter Ziffer, auch in Kacheln und
   Diagrammen, nicht nur in Tabellenzellen. */
.kachel .wert, .grafik text, .kalendergitter button, .monatsgitter button {
  font-variant-numeric: tabular-nums;
}

body {
  margin: 0;
  background: var(--grund);
  color: var(--schrift);
  /* Die Systemschrift und 14 Pixel wie im CMS der Einschlaf-App
     (Florian, 30.10.2026). Bis dahin DM Sans in 13 Pixeln. */
  font-family: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Inter",
               "Segoe UI", system-ui, sans-serif;
  font-size: 14px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

a { color: var(--akzent-schrift); text-decoration: none; }
a:hover { text-decoration: underline; }

/* ── Gerüst ──────────────────────────────────────────────────────── */
.rahmen { display: flex; min-height: 100vh; }

/* ── Seitenleiste, ein- und ausklappbar ──────────────────────────────
   Zwei Zustaende ueber Variablen statt ueber zwei Regelsaetze: So
   nehmen der Knopf und das schmale Fenster denselben Weg. Die Klasse am
   <html> schlaegt die Vorgabe, auch innerhalb der Medienabfrage; wer
   also bei schmalem Fenster aufklappt, bekommt die Leiste aufgeklappt
   (Florian, 08.10.2026). */
:root {
  --leiste-breite: var(--breite-leiste);
  --wegname: inline;
  --wegname-reihe: flex;
}
/* ── Dunkel ──────────────────────────────────────────────────────────
   Wie im Podcast-Studio: nach dem System, ausser jemand hat Hell
   gewaehlt, oder ausdruecklich Dunkel (Florian, 30.10.2026). Getauscht
   werden nur die Namen; die Bauteile bleiben, wie sie sind. Das
   Firmenrot bleibt als Flaeche, als Schrift wird es heller, sonst waere
   es auf dunklem Grund kaum zu lesen. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --grund: #141012;
    --erhoben: #1d181b;
    --rand: #2f272b;
    --schrift: #f1eaed;
    --leise: #ab9ca3;
    --akzent: #e50146;
    --akzent-schrift: #ff6b92;
    --akzent-hell: #4d1f2d;
    --gold: #e8b766;
    --gold-hell: #6a4c22;
    --vorschlag-grund: #1f2b42;
    --vorschlag-schrift: #93b5f0;
    --warn: #ff8fa3;
    --gut: #6fd3a8;
    --gut-flaeche: #16302a;
    --warn-flaeche: #3d1a22;
    --gold-flaeche: #3a2d17;
    --frei: #2a2327;
    --feiertag: #24364f;
    --krank: #c98a1a;
    --kind-krank: #6b5524;
    --neutral-hover: #2a2427;
    --erhoben-hoch: #262024;
    --akzent-tief: #b0013a;
    --schleier: rgb(0 0 0 / .6);
    --diagramm-zweit: #a8486a;
    --stufen-ende: #6e5a63;
    --schatten: 0 1px 2px rgba(0, 0, 0, .3), 0 4px 16px rgba(0, 0, 0, .25);
    --schatten-hoch: 0 2px 4px rgba(0, 0, 0, .35), 0 12px 32px rgba(0, 0, 0, .4);
    color-scheme: dark;
  }
}
:root[data-theme="dark"] {
  --grund: #141012;
  --erhoben: #1d181b;
  --rand: #2f272b;
  --schrift: #f1eaed;
  --leise: #ab9ca3;
  --akzent: #e50146;
  --akzent-schrift: #ff6b92;
  --akzent-hell: #4d1f2d;
  --gold: #e8b766;
  --gold-hell: #6a4c22;
  --vorschlag-grund: #1f2b42;
  --vorschlag-schrift: #93b5f0;
  --warn: #ff8fa3;
  --gut: #6fd3a8;
  --gut-flaeche: #16302a;
  --warn-flaeche: #3d1a22;
  --gold-flaeche: #3a2d17;
  --frei: #2a2327;
  --feiertag: #24364f;
  --krank: #c98a1a;
  --kind-krank: #6b5524;
  --neutral-hover: #2a2427;
  --erhoben-hoch: #262024;
  --akzent-tief: #b0013a;
  --schleier: rgb(0 0 0 / .6);
  --diagramm-zweit: #a8486a;
  --stufen-ende: #6e5a63;
  --schatten: 0 1px 2px rgba(0, 0, 0, .3), 0 4px 16px rgba(0, 0, 0, .25);
  --schatten-hoch: 0 2px 4px rgba(0, 0, 0, .35), 0 12px 32px rgba(0, 0, 0, .4);
  color-scheme: dark;
}
/* Umschalten wirkt sofort, ohne dass jede Flaeche einzeln nachblendet. */
.ohne-uebergang, .ohne-uebergang * { transition: none !important; }

html.leiste-schmal {
  --leiste-breite: 60px;
  --wegname: none;
  --wegname-reihe: none;
}
@media (max-width: 1000px) {
  :root {
    --leiste-breite: 60px;
    --wegname: none;
    --wegname-reihe: none;
  }
  html.leiste-breit {
    --leiste-breite: var(--breite-leiste);
    --wegname: inline;
    --wegname-reihe: flex;
  }
}
/* Waehrend des Einfahrens: Alles sieht aus wie ausgefahren, nur die
   Breite geht schon auf 60 Pixel. So deckt die schmaler werdende Leiste
   die Namen ab, statt sie vorher verschwinden zu lassen; das ist das
   Ausfahren rueckwaerts (Florian, 09.10.2026). Steht hinter der
   Medienabfrage und nennt beide Klassen, damit die Fahrtbreite ueberall
   gewinnt. Das Skript nimmt die Klasse nach der Fahrt wieder weg. */
html.leiste-faehrt-ein,
html.leiste-breit.leiste-faehrt-ein { --leiste-breite: 60px; }

.leiste {
  width: var(--leiste-breite);
  flex: 0 0 var(--leiste-breite);
  /* Ohne Kante, nur eine eigene, etwas hellere Flaeche. Deckend und
     ohne Weichzeichner: Hinter der Leiste laeuft nichts durch, der
     Weichzeichner aenderte kein Pixel und kostete beim Ein- und
     Ausklappen jedes Bild (Prüfung, 31.10.2026). */
  background: color-mix(in srgb, var(--erhoben) 55%, var(--grund));
  padding: 20px 14px;
  display: flex;
  flex-direction: column;
  /* Kompakter, ohne Zahnluecken zwischen den Wegen (Florian, 02.11.2026):
     die Wege liegen dicht, die Gruppen trennt ein kleiner Abstand. */
  gap: 1px;
  /* Bleibt im Bild, auch wenn eine lange Liste nach unten läuft. Eigene
     Höhe und eigener Überlauf, damit die Leiste selbst scrollt, wenn sie
     einmal länger wird als das Fenster. */
  position: sticky;
  top: 0;
  align-self: flex-start;
  height: 100vh;
  overflow-y: auto;
  /* Waehrend die Leiste breiter wird, sind die Beschriftungen schon da.
     Ohne dieses "hidden" blitzte dabei ein Querbalken zum Schieben auf. */
  overflow-x: hidden;
  /* Ein- und Ausklappen wandert, statt zu springen. Die Buehne daneben
     folgt von selbst, sie nimmt den Rest (Florian, 09.10.2026). */
  /* Das Polster aendert sich nur um ein paar Pixel und faehrt nicht
     mit; jede animierte Groesse kostet je Bild ein neues Layout der
     ganzen Buehne (Prüfung, 30.10.2026). */
  transition: width 200ms var(--ease-schublade),
              flex-basis 200ms var(--ease-schublade);
}
@media (prefers-reduced-motion: reduce) {
  .leiste, .leistenkante { transition: none; }
}
/* Nichts in der Leiste wird gestaucht. Sie ist eine Spalte mit fester
   Hoehe; laeuft sie ueber, drueckte der Flex-Satz alle Teile ein wenig
   zusammen, und zwar unterschiedlich stark, je nachdem wie lang die
   Liste gerade ist. Eingeklappt standen die Zeichen dadurch anders als
   ausgeklappt (Florian, 09.10.2026). */
.leiste > * { flex: 0 0 auto; }

/* Das Logo steht für sich, der Zusatz nennt nur noch das Werkzeug.

/* Die Kante der Leiste ist der Schalter: ein Klick darauf klappt sie um
   (Florian, 09.10.2026). Sie steht fest im Fenster und wandert mit der
   Kante mit, in derselben Zeit wie die Leiste selbst. Zu sehen ist sie
   erst, wenn die Hand hinkommt. */
.leistenkante {
  position: fixed; top: 0; bottom: 0; left: var(--leiste-breite);
  width: 9px; margin: 0 0 0 -4px; padding: 0;
  border: none; background: none; cursor: pointer; z-index: 40;
  transition: left 200ms var(--ease-schublade);
}
.leistenkante::before {
  content: ""; position: absolute; top: 0; bottom: 0; left: 3px;
  width: 3px; border-radius: 2px; background: transparent;
  transition: background-color 120ms;
}
.leistenkante:hover::before, .leistenkante:focus-visible::before {
  background: var(--akzent);
}
.leistenkante:focus { outline: none; }
/* Der Finger trifft keine neun Pixel. */
@media (pointer: coarse) {
  .leistenkante { width: 22px; margin-left: -11px; }
  .leistenkante::before { left: 9px; }
}
@media print { .leistenkante { display: none; } }
/* Was eingeklappt verschwindet: alle Beschriftungen. Die Zeichen
   bleiben, die Titel sagen, wohin es geht. */
.wegname { display: var(--wegname); }
/* Der Name eines Weges ist eine eigene Reihe: Links steht er selbst,
   rechts aussen das GF-Zeichen. Ohne die Reihe klebte das Zeichen am
   Wort, und sobald die Schrift des aktiven Eintrags fett wurde, sass es
   fast daran fest (Florian, 09.10.2026). */
.weg .wegname {
  display: var(--wegname-reihe); align-items: center; gap: 8px;
  flex: 1 1 auto; min-width: 0;
}
/* Eingeklappt bleibt von der Gruppenueberschrift ein Haarstrich: Ohne
   ihn liefen alle Zeichen in einer Reihe durch, und die Ordnung der
   Leiste waere weg.

   Der Text bleibt stehen und wird nur unsichtbar. Dadurch behaelt die
   Ueberschrift ihren Platz aufs Pixel genau, und die Zeichen darunter
   stehen eingeklappt auf derselben Hoehe wie ausgeklappt (Florian,
   09.10.2026). Der Strich kommt als Hintergrund, nicht als Rahmen: Ein
   Rahmen waere einen Pixel hoch und verschoebe wieder alles. */
.leiste .gruppe.schmal, html.leiste-schmal .leiste .gruppe {
  color: transparent; overflow: hidden;
  background: linear-gradient(var(--flaeche-2), var(--flaeche-2)) no-repeat;
  background-size: calc(100% - 20px) 1px;
  background-position: 10px 0;
}
@media (max-width: 1000px) {
  .leiste .gruppe {
    color: transparent; overflow: hidden;
    background: linear-gradient(var(--flaeche-2), var(--flaeche-2)) no-repeat;
    background-size: calc(100% - 20px) 1px;
    background-position: 10px 0;
  }
  html.leiste-breit .leiste .gruppe {
    color: var(--sehr-leise); background: none;
  }
}

/* Die Gruppen in der Seitenleiste tragen die Hausfarbe: Sie gliedern,
   ohne mit den Wegen darunter um Aufmerksamkeit zu ringen. */
/* Klein, normal geschrieben und sehr leise wie im CMS der Einschlaf-App
   (Florian, 30.10.2026). Bis dahin Versalien in der Hausfarbe. */
.gruppe {
  margin-top: 12px; padding: 0 12px 4px;
  font-size: 12px; font-weight: 560; color: var(--sehr-leise);
}

.weg {
  display: flex; align-items: center; gap: 8px;
  padding: 6px 10px; border-radius: 999px; font-size: 14px;
  color: var(--leise); font-weight: 520; transition: background-color 160ms var(--ease-out), color 160ms var(--ease-out);
  /* 20 Zeilenhoehe plus 2 mal 6 Polster: Ohne das Mass waere die Reihe
     ohne Beschriftung nur so hoch wie das Zeichen, und beim Einklappen
     ruecken alle Zeichen nach oben (Florian, 09.10.2026). */
  min-height: 32px; box-sizing: border-box;
  /* Beim Ausklappen wird der Name sichtbar, bevor die Leiste breit ist.
     Umbrechen duerfte er dabei nicht; er wird abgeschnitten und waechst
     mit der Leiste heraus. */
  white-space: nowrap;
}
/* Symbol und Name ganz oben in der Leiste, wie eine App-Kachel mit
   Titel (Florian, 02.11.2026). Ausgeklappt steht das Symbol auf einer
   Flucht mit den Zeichen der Wege darunter. */
.leisten-marke {
  display: flex; align-items: center; gap: 10px;
  padding: 0 6px; margin-bottom: 6px; min-height: 32px;
  color: var(--schrift); font-size: 15px; font-weight: 650;
  letter-spacing: -0.015em; white-space: nowrap;
}
.leisten-marke:hover { color: var(--schrift); text-decoration: none; }
.leisten-marke img {
  flex: 0 0 auto; border-radius: 7px;
  box-shadow: 0 1px 3px color-mix(in srgb, var(--schrift) 14%, transparent);
}
/* Das Zeichen behaelt seine Breite, auch wenn der Name lang ist. */
.weg .symbol { flex: 0 0 auto; opacity: .75; }
.weg.hier .symbol { opacity: 1; }
@media (hover: hover) and (pointer: fine) {
  .weg:hover { color: var(--schrift); text-decoration: none; }
}
.weg:hover { text-decoration: none; }
/* Der aktive Eintrag traegt die Hausfarbe als Hauch und als Schrift, wie
   im CMS der App; eine volle rote Flaeche zog zu viel Aufmerksamkeit auf
   die Leiste (Florian, 07.10.2026). */
/* Der aktive Eintrag steht erhoben auf der Flaeche, wie der gewaehlte
   Weg im Podcast-Studio (Florian, 30.10.2026). Die Hausfarbe bleibt im
   Zeichen. */
.weg.hier {
  background: var(--erhoben); box-shadow: var(--schatten);
  color: var(--schrift); font-weight: 600;
}
.weg.hier .symbol { color: var(--akzent); }

/* Was nur die Geschäftsführung sieht, sagt es auch. Eine Notiz, kein
   Schloss: Der Zugriff hängt an der Rolle, nicht an diesem Zeichen. */
.nur-gf {
  font-size: 11px; font-weight: 600;
  color: var(--leise); background: var(--flaeche-2); border-radius: 999px;
  padding: 1px 7px; white-space: nowrap;
}
.weg .nur-gf { margin-left: auto; }
.weg.hier .nur-gf { color: var(--akzent-schrift); background: var(--erhoben); }
h1 .nur-gf, h2 .nur-gf, h3 .nur-gf { vertical-align: middle; margin-left: 8px; }
@media print { .nur-gf { display: none; } }

.leiste .fuss {
  margin-top: auto; padding-top: 16px; box-shadow: inset 0 1px 0 var(--flaeche-2);
  font-size: 11px; color: var(--leise);
}
.leiste .fuss b { display: block; color: var(--schrift); font-size: 12px; }
.leiste .fuss .eigenes, .leiste .fuss .abmelden {
  display: flex; align-items: center; gap: 10px; padding: 4px 2px;
}
html.leiste-schmal .leiste .fuss .eigenes,
html.leiste-schmal .leiste .fuss .abmelden { justify-content: center; }
@media (max-width: 1000px) {
  .leiste .fuss .eigenes, .leiste .fuss .abmelden { justify-content: center; }
  html.leiste-breit .leiste .fuss .eigenes,
  html.leiste-breit .leiste .fuss .abmelden { justify-content: flex-start; }
}
.leiste .fuss .abmelden {
  color: var(--leise); font-size: 12px;
  width: 100%; background: none; border: 0; cursor: pointer;
  font-family: inherit; text-align: left;
}
.leiste .fuss .abmelden:hover { color: var(--akzent-schrift); }
/* Von den drei Zeichen des Darstellungsknopfs steht nur das, was gilt. */
.thema-knopf .i-system, .thema-knopf .i-hell, .thema-knopf .i-dunkel { display: none; }
:root:not([data-theme]) .thema-knopf .i-system,
:root[data-theme="light"] .thema-knopf .i-hell,
:root[data-theme="dark"] .thema-knopf .i-dunkel { display: inline-flex; }
.kuerzel {
  display: none; flex: 0 0 auto;
  width: 26px; height: 26px; border-radius: 999px;
  background: var(--akzent-hell); color: var(--akzent-schrift);
  font-size: 12px; font-weight: 700; text-transform: uppercase;
  align-items: center; justify-content: center;
}
html.leiste-schmal .kuerzel { display: inline-flex; }
@media (max-width: 1000px) {
  .kuerzel { display: inline-flex; }
  html.leiste-breit .kuerzel { display: none; }
}

.buehne { flex: 1; padding: 20px 24px 64px; min-width: 0; }

/* Wie die Seitentitel im CMS der Einschlaf-App. */
h1 { margin: 0 0 4px; font-size: 26px; line-height: 1.15; font-weight: 650; letter-spacing: -0.025em; }
.unterzeile { margin: 0 0 20px; color: var(--leise); font-size: 13px; }

h2 { margin: 24px 0 10px; font-size: 15px; font-weight: 650; letter-spacing: -0.015em; }

/* ── Kennzahlen ──────────────────────────────────────────────────── */
.kacheln {
  display: grid; gap: var(--luft);
  grid-template-columns: repeat(auto-fit, minmax(172px, 1fr));
  margin-bottom: var(--luft);
}

.kachel {
  background: var(--erhoben);
  border-radius: var(--rundung); padding: 18px 18px 16px;
  box-shadow: var(--kartenschatten);
  /* Nebeneinander sollen die Zahlen auf einer Linie liegen. Eine
     Überschrift, die über zwei Zeilen geht, schob ihre Zahl sonst nach
     unten, und die Reihe sah schief aus (Florian, 07.10.2026). */
  display: flex; flex-direction: column;
}
.kachel .wert { margin-top: auto; }
/* Beschriftungen klein, normal geschrieben und sehr leise wie im CMS
   der Einschlaf-App (Florian, 30.10.2026). */
.kachel .titel {
  font-size: 12px; font-weight: 560; color: var(--sehr-leise); margin-bottom: 4px;
}
/* Ohne nowrap rutschte bei siebenstelligen Betraegen das € allein in
   die naechste Zeile. */
.kachel .wert { font-size: 20px; font-weight: 650; letter-spacing: -0.02em; line-height: 1.15; white-space: nowrap; }
.kachel .rand { font-size: 12px; color: var(--leise); margin-top: 2px; }

.plus { color: var(--gut); }
.minus { color: var(--warn); }

/* ── Tabellen ────────────────────────────────────────────────────── */
.karte {
  background: var(--erhoben);
  border-radius: 14px; overflow: hidden;
  margin-bottom: var(--luft); box-shadow: var(--kartenschatten);
}
/* In einem Raster sorgt die Lücke für den Abstand, nicht der Rand. */
.zweispaltig > .karte, .dreispaltig > .karte, .kacheln > .karte { margin-bottom: 0; }

table { width: 100%; border-collapse: collapse; }
/* Koepfe klein und ruhig, normal geschrieben; Zeilen trennt eine
   eingelassene Linie im leisen Flaechenton statt eines Randes, wie im
   CMS der Einschlaf-App (Florian, 30.10.2026). */
th {
  text-align: left; font-size: 12px; font-weight: 560;
  letter-spacing: normal; text-transform: none; color: var(--sehr-leise);
  padding: 10px 14px; white-space: nowrap;
}
td { padding: 10px 14px; box-shadow: inset 0 1px 0 var(--flaeche-2);
     font-variant-numeric: tabular-nums; }
/* Trennlinien und Hover laufen bis an die Kartenkante, wie im
   Podcast-Studio (Florian, 02.11.2026). Die Tabelle fuellt die Karte,
   die aeusseren Zellen ruecken ihren Text um 18 Pixel ein. Das sind
   dieselben wie an Kartenkopf und Kartenfuss, damit alles auf einer
   Flucht steht. */
.karte > table > * > tr > :first-child,
.karte > .scrollbar > table > * > tr > :first-child,
.karte > form > table > * > tr > :first-child,
.karte > form > .scrollbar > table > * > tr > :first-child { padding-left: 18px; }
.karte > table > * > tr > :last-child,
.karte > .scrollbar > table > * > tr > :last-child,
.karte > form > table > * > tr > :last-child,
.karte > form > .scrollbar > table > * > tr > :last-child { padding-right: 18px; }
tr:last-child td { border-bottom: none; }
/* Zeilen setzen sich beim Überfahren leicht ab (Florian, 04.10.2026).
   Nicht als Versprechen, dass die Zeile anklickbar wäre, sondern als
   Lineal: Bei einer breiten Tabelle hält es Datum und Betrag am rechten
   Rand zusammen. Nur im Körper, denn Kopf und Summenzeile sind nichts,
   dem das Auge folgt. */
@media (hover: hover) and (pointer: fine) {
  tbody tr:hover > td { background: var(--zeile-hover); }
  /* Felder haben dieselbe leise Flaeche wie die ueberfahrene Zeile und
     verschwanden darin (Florian, 03.11.2026). In der Zeile werden sie
     hell, so bleibt sichtbar, was sich aendern laesst. */
  tbody tr:hover > td :where(input:not([type="checkbox"], [type="radio"], [type="color"],
                                       [type="file"], [type="hidden"], [type="submit"],
                                       [type="button"]), select, textarea) {
    background-color: var(--erhoben) !important;
  }
}
/* Zahlenspalten nicht umbrechen: "30 Tage" soll nicht auf zwei Zeilen
   rutschen, nur weil die Spalte daneben viel Text trägt. */
td.zahl, th.zahl { text-align: right; font-variant-numeric: tabular-nums;
                   white-space: nowrap; }
.leise { color: var(--leise); }

/* ── Marken ──────────────────────────────────────────────────────── */
/* Eine Marke bricht nie um: "zu prüfen" auf zwei Zeilen in einer runden
   Kapsel liest sich wie ein Fehler (Florian, 06.10.2026). Lieber wird die
   Spalte breiter. */
.marke-punkt {
  display: inline-flex; align-items: center; height: 22px; padding: 0 9px;
  border-radius: 999px; font-size: 12px; font-weight: 600; white-space: nowrap;
}
/* Statusmarken mit Punkt, wie bei BoardUI (Florian, 03.11.2026): eine
   ruhige, neutrale Marke, die Farbe traegt nur der Punkt davor. Vorher
   war jede Marke ganz eingefaerbt, und eine Tabelle voller Marken wurde
   bunt. */
.marke-punkt {
  background: var(--flaeche-2); color: var(--schrift); gap: 6px; padding: 0 9px 0 8px;
  font-weight: 560;
}
.marke-punkt::before {
  content: ""; flex: 0 0 auto; width: 7px; height: 7px; border-radius: 50%;
  background: var(--ton);
}
.m-arbeitet { --ton: var(--gut); }
.m-frei { --ton: var(--sehr-leise); color: var(--leise); }
.m-urlaub { --ton: var(--gold); }
.m-krank { --ton: var(--warn); }

/* ── Balken für die Projektverteilung ────────────────────────────── */
.balken { height: 8px; background: var(--flaeche-2); border-radius: 999px; overflow: hidden; }
.balken i { display: block; height: 100%; background: var(--akzent); border-radius: 999px; }

.hinweis {
  background: var(--gold-flaeche); border: 0;
  border-radius: 12px; padding: 10px 14px; color: var(--gold);
  font-size: 13.5px; font-weight: 520;
}

/* Bei schmalem Fenster klappt die Leiste zusammen, statt sich oben in
   mehrere Zeilen zu legen. Das sah nach Unfall aus (Florian,
   08.10.2026); die Regeln dafuer stehen oben bei der Leiste. */
@media (max-width: 1000px) {
  .leiste { padding: 20px 10px; align-items: center; }
  html.leiste-breit .leiste { padding: 20px 14px; align-items: stretch; }
  .weg, .leisten-marke { justify-content: center; }
  html.leiste-breit :is(.weg, .leisten-marke) { justify-content: flex-start; }
  .buehne { padding: 20px 16px 40px; }
}
html.leiste-schmal .leiste { padding: 20px 10px; align-items: center; }
html.leiste-schmal :is(.weg, .leisten-marke) { justify-content: center; }

/* ── Abwesenheiten als Raster ────────────────────────────────────────
   Wie der Hörkalender im CMS der App: lauter kleine Blöcke, Tage als
   Spalten, eine Lücke nach jedem Sonntag, ein Band je Monat darüber. Das
   Muster springt ins Auge, bevor man eine Zahl liest. */
/* Alle Knöpfe tragen die Hausfarbe. Vorher sah ein Knopf aus wie eine
   Fläche mit Rand, und man musste raten, worauf sich klicken lässt. */
/* 10 px Ecken statt Pille, ohne Rand, wie die Knoepfe im CMS der
   Einschlaf-App (Florian, 30.10.2026). Pillen bleiben den Marken und der
   Leiste. Beim Zeigen wird die Flaeche einen Hauch heller. */
.knopf {
  padding: 7px 14px; border: 0; border-radius: 10px;
  background: var(--akzent); color: #fff; font-size: 14px;
  font-weight: 500; cursor: pointer;
}
.knopf:hover { color: #fff; text-decoration: none; }

.rasterrahmen { overflow-x: auto; padding: 14px 0 12px; }
.raster {
  display: grid; align-items: center; column-gap: 3px; row-gap: 4px;
  width: max-content; min-width: 100%;
}
.raster .namensspalte {
  position: sticky; left: 0; z-index: 2; background: var(--erhoben);
  padding: 0 16px; font-size: 12px; font-weight: 600; white-space: nowrap;
  height: 100%; display: flex; align-items: center;
}
.raster .namensspalte.kopf {
  font-size: 12px; font-weight: 560; color: var(--sehr-leise);
}
.raster .band {
  padding: 0 0 2px 2px; font-size: 11px; font-weight: 600; color: var(--leise);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  box-shadow: inset 1px 0 0 var(--flaeche-2); line-height: 1.2;
}
.raster .tagkopf {
  font-size: 11px; line-height: 1.15; text-align: center; color: var(--leise);
  font-variant-numeric: tabular-nums; padding-bottom: 2px;
}
.raster .tagkopf.wochenende { color: var(--akzent-schrift); }
/* Heute dunkel, nicht fett: Der Rahmen in der Spalte zeigt den Tag
   schon, zwei Zeilen Fettdruck darueber waren zu viel (Florian,
   10.10.2026). In beiden Kalendern gleich. */
.raster .tagkopf.heute-spalte { color: var(--schrift); }
.raster .zelle {
  height: 18px; border-radius: 4px; background: var(--grund);
  border: 1px solid transparent; box-sizing: border-box;
}
/* Wochenende hell, Feiertag dunkler: beides frei, aber verschieden.
   Krank als dunkleres Gelb, Kind krank als helleres: verwandt, aber
   unterscheidbar. */
.raster .belegung { font-size: 11px; line-height: 18px; text-align: center;
                    color: var(--leise); border-radius: 3px; }
.raster .belegung-name { font-size: 11px; color: var(--leise); }
.raster .zelle.frei { background: var(--frei); }
/* Feiertag blau: frei, aber nicht von dieser Person entschieden. */
.raster .zelle.feiertag { background: var(--feiertag); }
.raster .zelle.urlaub { background: var(--akzent); }
.raster .zelle.krank { background: var(--krank); }
.raster .zelle.kind-krank { background: var(--kind-krank); }
.raster .zelle.freistellung { background: var(--gut); opacity: 0.55; }
.raster .zelle.beantragt { background: var(--erhoben); border: 1.5px dashed var(--akzent); }
/* Heute als Rahmen um die Zelle, in jeder Zeile: eine senkrechte Linie
   durch das ganze Raster, ohne dass eine Person hervorgehoben wird.
   Der Rahmen sitzt auf der Zelle und ist einen Punkt stark, wie im
   Stundenraster der Personenseite (Florian, 10.10.2026). */
.raster .zelle.heute { box-shadow: inset 0 0 0 1px var(--schrift); }
.raster .summe {
  position: sticky; z-index: 2; background: var(--erhoben);
  text-align: center; font-size: 11px; color: var(--leise);
  height: 100%; display: flex; align-items: center; justify-content: center;
  box-shadow: inset 1px 0 0 var(--rand);
}
.raster .summe.kopf { font-size: 11px; font-weight: 700; letter-spacing: 0.05em; }
.raster .summe.u { right: 108px; }
.raster .summe.k { right: 74px; }
.raster .summe.kk { right: 34px; }
.raster .summe.f { right: 0; }
/* Die Zeile unter dem Mauszeiger: leicht getönt, Summen und Name mit. */
/* Grau wie die Tabellenzeile, deckend, weil Name und Summen kleben
   und Darunterliegendes sonst durchscheint (Prüfung, 30.10.2026). */
.raster .hervor, .raster .namensspalte.hervor, .raster .summe.hervor { background: var(--neutral-hover); }
.punkt {
  width: 9px; height: 9px; border-radius: 3px; display: inline-block;
  margin-right: 8px; vertical-align: 1px;
}

.probe {
  width: 16px; height: 11px; border-radius: 3px; display: inline-block;
  border: 1px solid transparent;
}
.probe.urlaub { background: var(--akzent); }
.probe.krank { background: var(--krank); }
.probe.kind-krank { background: var(--kind-krank); }
.probe.freistellung { background: var(--gut); opacity: 0.55; }
.probe.beantragt { background: var(--erhoben); border: 1.5px dashed var(--akzent); }
.probe.frei-tag { background: var(--frei); border-color: var(--frei); }
.probe.feiertag-tag { background: var(--feiertag); border-color: var(--feiertag); }
/* Legende der Säulengrafik, dieselben Farben wie die Säulen */
.probe.saeule-wert { background: var(--akzent); }
.probe.saeule-vergleich { background: var(--diagramm-zweit); border-color: var(--diagramm-zweit); }
.legende-punkt { display: inline-flex; align-items: center; gap: 7px; font-size: 12px; }
.legende-reihe { display: flex; flex-wrap: wrap; gap: 14px; margin-left: auto; }
.zeitraumwahl .legende-reihe { display: inline-flex; }

/* ── Filterleiste ────────────────────────────────────────────────── */
.filter { display: flex; flex-wrap: wrap; gap: 10px; align-items: center;
          margin-bottom: 16px; }
.filter select, .filter input {
  padding: 8px 12px; border: 1px solid var(--rand); border-radius: 8px;
  background: var(--erhoben); color: var(--schrift);
}

/* ── Formulare, Knöpfe, Meldungen ────────────────────────────────── */
/* Alle drei Knopfarten gleich hoch, damit sie nebeneinander auf einer
   Linie stehen (Prüfung, 30.10.2026). Der Warnknopf als Flaeche. */
.knopf-haupt {
  padding: 8px 18px; border: none; border-radius: 10px; font-size: 14px;
  background: var(--akzent); color: #fff; font-weight: 600; cursor: pointer;
}
.knopf-haupt:hover { text-decoration: none; }
.knopf-warn {
  padding: 7px 14px; border: none; border-radius: 10px; font-size: 14px;
  background: color-mix(in srgb, var(--warn) 8%, transparent);
  color: var(--warn); font-weight: 500; cursor: pointer;
}
.knopf-warn:hover { background: color-mix(in srgb, var(--warn) 14%, transparent); text-decoration: none; }
/* Der stille Knopf: eine Hauch Hausfarbe als Flaeche. */
/* Der zweitrangige Knopf: neutral auf dem leisen Flaechenton, wie im
   Podcast-Studio. */
.knopf-leise {
  padding: 7px 14px; border: 0; border-radius: 10px; font-size: 14px;
  background: var(--flaeche-2); color: var(--schrift); font-weight: 500; cursor: pointer;
}
.knopf-leise:hover { background: var(--flaeche-3); }
.knopf.klein { padding: 4px 10px; font-size: 12px; border-radius: 8px; }
:is(.knopf, .knopf-haupt, .knopf-warn, .knopf-leise):disabled {
  opacity: .4; cursor: not-allowed; filter: none;
}

form input[type="text"], form input[type="date"], form input[type="time"],
form select {
  width: 100%; padding: 9px 12px; border: 1px solid var(--rand);
  border-radius: var(--rundung-klein); background: var(--grund);
  color: var(--schrift);
}

/* Die Art traegt die Flaeche, nicht ein Streifen am Rand: Raender wirken
   billig (Florian; Prüfung, 30.10.2026). */
.meldung {
  padding: 10px 14px; border-radius: 12px; margin-bottom: 18px;
  border: 0; background: var(--erhoben); font-size: 13.5px; font-weight: 520;
}
.meldung.success { background: var(--gut-flaeche); }
.meldung.error { background: var(--warn-flaeche); }
.meldung.info { background: var(--akzent-hell); }
.meldung .rueckgaengig { display: inline-flex; margin-left: 12px; vertical-align: middle; }
.meldung .rueckgaengig .knopf { display: inline-flex; align-items: center; gap: 5px; }
/* Meldungen als Mitteilungen oben rechts: Sie schieben den Inhalt nicht
   mehr nach unten, gehen nach zwanzig Sekunden von selbst und lassen
   sich wegklicken (Florian, 05.10.2026). Ohne Javascript bleiben sie im
   Fluss, wo sie vorher standen. */
.mitteilungen {
  position: fixed; top: 16px; right: 16px; z-index: 60;
  display: flex; flex-direction: column; gap: 10px;
  width: min(380px, calc(100vw - 32px));
}
.mitteilungen .meldung {
  margin: 0; display: flex; align-items: flex-start; gap: 10px;
  box-shadow: 0 12px 30px -14px rgba(0, 0, 0, .35);
}
/* Ein langer Dateiname bricht um, statt das Kreuz aus dem Kasten zu
   schieben (Prüfung, 30.10.2026). */
.meldungstext { flex: 1 1 auto; min-width: 0; overflow-wrap: anywhere; }
/* 24 Pixel Trefferflaeche: Das Kreuz allein war 14 mal 17 gross. */
.mitteilungen .meldung > .zu {
  margin: -3px -4px -3px auto; border: none; background: none; cursor: pointer;
  color: var(--leise); font-size: 16px; line-height: 1;
  width: 24px; height: 24px; padding: 0; flex: none; border-radius: 999px;
  display: inline-flex; align-items: center; justify-content: center;
  transition: background-color 120ms;
}
.mitteilungen .meldung > .zu:hover { color: var(--schrift); background: color-mix(in srgb, var(--schrift) 8%, transparent); }
/* Hinaus schneller als herein: Was das System wegnimmt, soll nicht
   trödeln. Die Wartezeit im Skript haengt an diesen 200 ms. */
.mitteilungen .meldung.geht {
  opacity: 0; transform: translateX(16px);
  transition: opacity 200ms var(--ease-out),
              transform 200ms var(--ease-out);
}
/* Wegwischen nach rechts. Waehrend die Hand zieht, darf nichts
   nachfedern, darum keine Ueberblendung; losgelassen federt sie zurueck
   oder fliegt ganz hinaus (Florian, 09.10.2026). Senkrecht bleibt dem
   Finger das Schieben der Seite. */
.mitteilungen .meldung { touch-action: pan-y; cursor: grab; }
.mitteilungen .meldung.wischt {
  transition: none; cursor: grabbing; user-select: none;
}
/* Herein per Uebergang statt per Keyframes: Ein Uebergang laesst sich
   unterbrechen, wenn die Hand schon zieht, waehrend sie noch kommt. */
.mitteilungen .meldung:not(.wischt):not(.geht) {
  transition: transform 200ms var(--ease-out),
              opacity 200ms var(--ease-out);
}
@starting-style {
  .mitteilungen .meldung { opacity: 0; transform: translateX(20px); }
}
.mitteilungen .meldung.geht.gewischt { transform: translateX(110%); }
/* Weniger Bewegung: Blenden bleibt, Schieben faellt weg. Das Wegwischen
   bleibt, die Hand hat es selbst dorthin gezogen. */
@media (prefers-reduced-motion: reduce) {
  .mitteilungen .meldung:not(.wischt):not(.geht) { transition: opacity 200ms ease; }
  @starting-style { .mitteilungen .meldung { transform: none; } }
  .mitteilungen .meldung.geht:not(.gewischt) { transform: none; }
}
@media print { .mitteilungen { display: none; } }

/* ── Personalblatt ───────────────────────────────────────────────── */
.blatt-kopf { display: flex; justify-content: space-between; align-items: flex-start;
              gap: 16px; margin-bottom: 22px; }
.blatt-kopf h1 { display: flex; align-items: center; gap: 10px; }
/* Oben rechts steht, was mit der Seite etwas tut: Drucken, Zurueck, Heute,
   ein Fenster oeffnen. Was die Seite veraendert (Jahr, Zeitraum, Person),
   steht darunter in der Werkzeugleiste (Florian, 04.10.2026). */
.aktionen { display: flex; align-items: center; gap: 8px; flex-shrink: 0; }
.aktionen > *:not(dialog) { align-self: center; margin: 0; }
/* Auf dem Telefon rutschen die Knoepfe unter die Ueberschrift und brechen
   um. Nebeneinander machten sie die Seite doppelt so breit wie den
   Bildschirm, und Safari zoomte alles klein (Florian, 01.11.2026). */
@media (max-width: 600px) {
  .blatt-kopf { flex-wrap: wrap; }
  .aktionen { flex-wrap: wrap; flex-shrink: 1; min-width: 0; }
}
.punkt.gross { width: 14px; height: 14px; border-radius: 4px; margin: 0; }

form input[type="color"] { width: 54px; height: 36px; padding: 2px;
                           border: 1px solid var(--rand); border-radius: 8px; }
form input[type="number"], form input[type="email"] {
  width: 100%; padding: 9px 12px; border: 1px solid var(--rand);
  border-radius: 8px; background: var(--grund); color: var(--schrift);
}
form ul { list-style: none; padding: 0; margin: 4px 0 0; display: flex;
          flex-wrap: wrap; gap: 12px; }
form ul li label { font-weight: 500; display: inline-flex; align-items: center;
                   gap: 6px; }
form ul li input { width: auto; }

/* ── Drucken ─────────────────────────────────────────────────────────
   Jede Seite soll sich als PDF sichern lassen. Weg muss, was auf Papier
   nichts verloren hat: Navigation, Knöpfe, Formulare. Tabellen dürfen nicht
   mitten in einer Zeile umbrechen, und Überschriften nicht allein am
   Seitenende stehen. */
@media print {
  @page { size: A4; margin: 14mm 12mm; }

  body { background: #fff; font-size: 10.5pt; }
  .leiste, .nur-bildschirm, .filter, .meldung, .zeitraumwahl,
  .knopf, .knopf-haupt, .knopf-warn, form, details { display: none !important; }
  .rahmen { display: block; }
  .buehne { padding: 0; }

  h1 { font-size: 17pt; }
  h2 { font-size: 12pt; margin-top: 16pt; break-after: avoid; }
  h3 { font-size: 10pt; margin: 12pt 0 5pt; break-after: avoid; }
  .unterzeile { margin-bottom: 12pt; }

  .karte, .kachel {
    border: 1px solid #ccc; box-shadow: none; break-inside: avoid;
  }
  .kacheln { display: grid; grid-template-columns: repeat(4, 1fr); gap: 6mm; }
  .kachel .wert { font-size: 15pt; }

  table { break-inside: auto; }
  tr { break-inside: avoid; break-after: auto; }
  thead { display: table-header-group; }
  th, td { padding: 4pt 6pt; }

  a { color: inherit; text-decoration: none; }
  .balken i { background: #666 !important; }

  /* Datum und Herkunft auf jedes Blatt, damit ein Ausdruck später noch
     einzuordnen ist. */
  .buehne::after {
    content: "Checkin · Ausdruck vom " attr(data-gedruckt);
    display: block; margin-top: 10mm; padding-top: 3mm;
    border-top: 1px solid #ccc; font-size: 8pt; color: #666;
  }
}

/* ── Symbole ─────────────────────────────────────────────────────── */
.symbol { vertical-align: -3px; flex: 0 0 auto; }
/* ── Knöpfe: wo sie stehen und wie sie heißen ──────────────────────
   Festgehalten am 07.10.2026, weil beides auseinandergelaufen war.

   Wo:
   * In einem Formular steht der Knopf unter den Feldern, in .aktionen.
   * Was eine ganze Seite tut, steht oben rechts neben der Überschrift,
     in .blatt-kopf .aktionen.
   * Was zu einem Abschnitt gehört, steht neben dessen h3, in
     .abschnitt-kopf.
   * Was unter einer Tabelle über alle Zeilen entscheidet, steht in
     .kartenfuss.
   * Was eine Zeile tut, steht in der Zeile, rechtsbündig.

   Wie:
   * Anlegen, Eintragen, Ablegen, Ausgeben: Es entsteht etwas Neues. Der
     Knopf trägt das Zeitwort aus der Überschrift des Fensters.
   * Speichern: Etwas Vorhandenes ändert sich. Ohne Hauptwort davor, die
     Überschrift sagt schon, worum es geht.
   * Übernehmen und Verwerfen: Über einen Vorschlag des Werkzeugs wird
     entschieden.
   * Löschen: Es verschwindet etwas.
   Zwei Zeitwörter in einem Knopf ("Speichern und suchen") sagen nicht
   mehr als eines; was danach von selbst geschieht, gehört nicht auf den
   Knopf. */
.knopf, .knopf-haupt, .knopf-warn {
  display: inline-flex; align-items: center; gap: 7px;
  text-decoration: none; line-height: 1.3;
}
.knopf .symbol { color: inherit; }

/* Nur-Symbol-Knöpfe in Tabellenzeilen: quadratisch, damit die Spalte schmal
   bleibt. Was sie tun, steht im title-Attribut. */
/* Still wie die Zeilenknoepfe im CMS der Einschlaf-App: eine leise
   Flaeche, Farbe erst beim Zeigen, Loeschen dann rot. Eine Liste voller
   roter Knoepfe liest sich wie eine Warnung (Florian, 30.10.2026). */
.knopf.symbolisch {
  padding: 6px; width: 32px; height: 32px; justify-content: center;
  background: var(--flaeche-2); color: var(--leise);
}
.knopf.symbolisch:hover { filter: none; color: var(--schrift); background: var(--flaeche-3); }
.knopf.symbolisch:is([title^="Lösch"], [title*="löschen"], [title^="Entfern"]):hover {
  color: var(--warn); background: color-mix(in srgb, var(--warn) 12%, transparent);
}
/* Zwei Symbolknoepfe in einer Zelle klebten aneinander und sahen aus wie
   einer (Florian, 06.10.2026). */
.knopf.symbolisch + .knopf.symbolisch,
form.inline + form.inline > .knopf.symbolisch,
.knopf.symbolisch + form.inline > .knopf.symbolisch { margin-left: 6px; }
@media print { .symbol { display: none; } }

/* ── Sortierbare Tabellenköpfe ───────────────────────────────────── */
/* Als Verweis (Server sortiert) oder als Knopf (Seite sortiert selbst),
   beide sehen gleich aus. */
a.sortierkopf, button.sortierkopf {
  display: inline-flex; align-items: center; gap: 5px;
  color: inherit; font: inherit; text-decoration: none;
  background: none; border: 0; padding: 0; cursor: pointer;
  letter-spacing: inherit; text-transform: inherit;
}
a.sortierkopf:hover, button.sortierkopf:hover { color: var(--akzent-schrift); text-decoration: none; }
/* Ruhende Pfeile blass, damit erkennbar ist, dass die Spalte sortierbar ist,
   ohne dass der Kopf unruhig wirkt. */
.sortierkopf.ruhend .symbol { opacity: 0.3; }
.sortierkopf.aktiv { color: var(--akzent-schrift); }
@media print { .sortierkopf { color: inherit; } .sortierkopf .symbol { display: none; } }

/* ── Abschnitte im Personalblatt ──────────────────────────────────────
   Die Seite trägt viel Stoff. Gegliedert wird nur über die kleinen
   Überschriften; eine zweite Ebene darüber wäre eine Hierarchie, die es
   inhaltlich nicht gibt. */
/* Normal geschrieben statt gesperrter Versalien, wie die Kastentitel im
   CMS der Einschlaf-App (Florian, 30.10.2026). */
h3 {
  margin: 36px 0 14px;
  font-size: 15px;
  font-weight: 650;
  color: var(--schrift);
  letter-spacing: -0.015em;
}
h3.erste { margin-top: 18px; }
.abschnitt-kopf {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 12px;
}
.abschnitt-kopf { margin-bottom: 10px; }
.abschnitt-kopf h3 { margin-bottom: 0; }

/* ── Aufklappbare Formulare ───────────────────────────────────────────
   Eingabefelder stehen nicht dauerhaft auf der Seite. Der Zusammenfassungs-
   knopf sieht aus wie ein Knopf, ohne dass dafür Skript nötig wäre. */
details.aufklapp { margin: 14px 0 8px; }
details.aufklapp > summary {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  cursor: pointer;
  list-style: none;
  user-select: none;
}
details.aufklapp > summary::-webkit-details-marker { display: none; }
details.aufklapp[open] > summary {
  background: var(--erhoben);
  color: var(--akzent-schrift);
}
details.aufklapp[open] > summary .symbol { transform: rotate(45deg); }
.aufklapp-inhalt { margin-top: 12px; padding: 22px; max-width: 760px; }

/* Dasselbe Formular als Fenster über der Seite: Es schiebt die Liste
   darunter nicht weg, und man sieht, dass gerade etwas eingegeben wird.
   Ohne Javascript bleibt es ein gewöhnliches <details> an Ort und Stelle. */
dialog.fenster {
  border: 0; border-radius: var(--rundung);
  background: var(--erhoben); color: var(--schrift);
  padding: 0; max-width: 760px; width: calc(100% - 40px);
  border-radius: 18px;
  box-shadow: 0 25px 50px -12px rgb(0 0 0 / .25);
}
dialog.fenster.breit { max-width: 1180px; }
/* Das Fenster entsteht neben seinem Aufklapper, und der steht oft in
   einer Zelle. Deren Ausrichtung und Umbruchsperre gelten drinnen
   nicht: In der Vertragskarte lief der Hilfetext sonst als eine Zeile
   quer durch die Felder daneben (Florian, 11.10.2026). */
dialog.fenster { white-space: normal; text-align: left; }
dialog.fenster::backdrop {
  background: color-mix(in srgb, var(--schrift) 55%, transparent);
  -webkit-backdrop-filter: blur(4px); backdrop-filter: blur(4px);
}
/* Das Fenster blendet kurz ein, statt in einem Bild dazustehen. Am Ende
   steht kein transform, auch kein scale(1): Sonst wuerde das Fenster zum
   Bezug fuer das fest stehende Kalenderblatt darin. Schliessen springt. */
dialog.fenster[open] {
  transition: opacity 150ms var(--ease-out),
              transform 150ms var(--ease-out);
}
dialog.fenster[open]::backdrop { transition: opacity 150ms ease-out; }
@starting-style {
  dialog.fenster[open] { opacity: 0; transform: scale(0.98); }
  dialog.fenster[open]::backdrop { opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  @starting-style { dialog.fenster[open] { transform: none; } }
}
.fensterkopf {
  display: flex; align-items: center; justify-content: space-between;
  gap: 16px; padding: 16px 20px 4px;
}
.fensterkopf b { font-size: 14px; font-weight: 600; }
/* Das Kreuz oben rechts, rund und leise wie im CMS der Einschlaf-App. */
.fenster-zu {
  display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px; border: 0; border-radius: 999px;
  background: none; color: var(--leise); cursor: pointer;
  transition: background-color 160ms var(--ease-out), color 160ms var(--ease-out);
}
.fenster-zu:hover { background: var(--flaeche-2); color: var(--schrift); }
dialog.fenster .aufklapp-inhalt {
  margin-top: 0; max-width: none; max-height: 70vh; overflow-y: auto;
}
dialog.fenster .karte { border: none; box-shadow: none; }
@media print { dialog.fenster { display: none; } }

/* ── Zeitraumwahl ─────────────────────────────────────────────────── */
.zeitraumwahl {
  display: flex;
  align-items: flex-end;
  flex-wrap: wrap;
  gap: 10px;
  margin-bottom: 18px;
}
/* Die Auswahlliste für den Zeitraum, wie im CMS der App. */
.zeitraumwahl label { display: block; }
.zeitraumwahl .feldname {
  display: block;
  font-size: 11px;
  color: var(--leise);
}
.zeitraumwahl select,
.zeitraumwahl input[type="text"],
.zeitraumwahl input[type="date"] {
  margin-top: 4px;
  padding: 6px 11px;
  font: inherit;
  font-size: 12px;
  color: inherit;
  border: 1px solid var(--rand);
  border-radius: var(--rundung);
  background: var(--grund);
}
/* Der gewaehlte Bereich in Tagen, neben der Wahl: Die Liste nennt ihn beim
   Namen ("Aktuelles Jahr"), die Zahlen brauchen das Datum. */
.zeitraumwahl .bereich { align-self: center; font-size: 12px; color: var(--leise); }

/* ── Formularfelder: ein Raster, alle Beschriftungen auf einer Linie ──
   Für Eingabemasken mit mehreren Feldern. Die Zeitraumwahl ist dafür
   nicht gedacht: dort sitzen Felder verschiedener Höhe nebeneinander, und
   die Beschriftungen rutschen auseinander. */
.formularfelder {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
  gap: 14px 16px;
  align-items: start;
  padding: 20px 22px;
  margin: 0;
}
.formularfelder label { display: block; min-width: 0; }
.formularfelder .feldname {
  display: block; font-size: 11px; color: var(--leise); margin-bottom: 5px;
}
.formularfelder input:not([type="checkbox"]):not([type="radio"]),
.formularfelder select,
.formularfelder textarea {
  width: 100%; box-sizing: border-box;
  padding: 7px 11px; font: inherit; font-size: 12px; color: inherit;
  border: 1px solid var(--rand); border-radius: var(--rundung);
  background: var(--grund);
}
.formularfelder input:focus, .formularfelder select:focus {
  outline: none; border-color: var(--akzent);
}
.formularfelder textarea { min-height: 72px; resize: vertical; }
.formularfelder .breit { grid-column: 1 / -1; }
/* Letzte Spalte, egal wie viele es sind: unter dem, was dort steht. */
.formularfelder .rechts { grid-column: -2 / -1; }
.formularfelder .aktionen { grid-column: 1 / -1; margin-top: 4px; display: flex; gap: 8px; }
.formularfelder .hilfe, .formularfelder .fehler { display: block; font-size: 11px; margin-top: 4px; }
.formularfelder .fehler { color: var(--warn); }
.formularfelder .schalter { display: flex; align-items: center; gap: 8px; align-self: end;
                            padding: 8px 0; font-size: 12px; flex-wrap: wrap; }
.formularfelder .schalter input { width: auto; }
.formularfelder .wahlliste label { display: flex; align-items: center; gap: 7px; font-size: 12px; padding: 2px 0; }
.formularfelder .wahlliste input { width: auto; }
.formularfelder .schalter .hilfe { flex-basis: 100%; margin: 0; }
/* In einer Aufklappkarte polstert schon die Karte. */
.aufklapp-inhalt .formularfelder { padding: 0; }

/* ── Ablage fürs Hochladen ───────────────────────────────────────── */
.ablage {
  display: block; padding: 34px 22px; text-align: center; cursor: pointer;
  border: 2px dashed color-mix(in srgb, var(--leise) 35%, transparent);
  border-radius: var(--rundung); background: var(--flaeche-2);
  transition: background-color 150ms ease, border-color 150ms ease;
}
.ablage:hover, .ablage.aktiv { border-color: var(--akzent); background: var(--flaeche-3); }
.ablage input[type="file"] { position: absolute; width: 1px; height: 1px; opacity: 0; }
/* Im Formularraster gilt fuer Eingaben "width: 100%". Das zoege das
   versteckte Dateifeld ueber die ganze Ablage und faenge die Klicks ab. */
.formularfelder .ablage input[type="file"] { width: 1px; }
/* In einem Formular neben anderen Feldern darf die Ablage nicht so viel
   Platz nehmen wie die eine grosse auf der Upload-Seite. */
.formularfelder .ablage { padding: 20px 18px; }
.ablage-text { display: block; font-size: 12px; line-height: 1.5; }

/* Mit Dateien darin ist die Ablage nicht mehr leer, und das soll sie
   zeigen: voller Rand statt gestrichelt, Hausfarbe, und an der Stelle der
   Aufforderung stehen die Namen (Florian, 06.10.2026). */
/* Gefuellt als Flaeche statt als roter Rand (Prüfung, 31.10.2026). */
.ablage.gefuellt { border-color: transparent; background: var(--akzent-flaeche); }
.ablage.gefuellt .ablage-text { display: none; }
.ablage-gewaehlt { display: none; }
.ablage.gefuellt .ablage-gewaehlt {
  display: flex; flex-wrap: wrap; gap: 8px; justify-content: center;
  align-items: center;
}
.ablage-datei {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 7px 12px; border-radius: var(--rundung);
  background: var(--akzent-hell); color: var(--schrift);
  font-size: 13px; font-weight: 600; word-break: break-word;
}
.ablage-datei .leise { font-weight: 500; }
.ablage-hinweis { flex-basis: 100%; font-size: 11px; color: var(--leise); }
.fortschritt { margin-top: 12px; }
.fortschritt-balken { height: 8px; border-radius: 4px; background: var(--rand); overflow: hidden; }
/* Skaliert statt breiter: Das kostet kein Layout. Gleichmaessig, weil
   Fortschritt keine Geste ist. */
.fortschritt-balken i {
  display: block; height: 100%; width: 100%; background: var(--akzent);
  transform: scaleX(0); transform-origin: left; transition: transform 200ms linear;
}
/* Die Zeile unter dem Balken traegt .reihe und lebt von deren Luecke
   zwischen Kreis und Text. "display: block" nahm sie ihr wieder weg, und
   der Kreis klebte am Wort (Florian, 07.10.2026). */
.fortschritt .leise { display: flex; margin-top: 6px; font-size: 11px; }

/* Breite Prüftabellen schieben sich waagerecht, statt rechts abzuschneiden. */
.scrollbar { overflow-x: auto; }
table.pruefung td, table.pruefung th { white-space: nowrap; }

/* Eine Karte mit Text und Knopf, nicht mit Tabelle: braucht Innenabstand. */
.karte.gepolstert { padding: 16px 22px; }

/* Schalter in einer Tabellenzeile: Zustand und Knopf nebeneinander. */
.schalterzeile {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 0;
}
/* Das Kaestchen sass auf der Schriftlinie und damit zehn Pixel ueber der
   Mitte seiner Beschriftung (Florian, 07.10.2026). */
.schalterzeile label { display: flex; align-items: center; gap: 6px; }

/* Mehrere Kästchen nebeneinander, etwa die Gegenparteien einer Quelle.
   Jedes ist ein Feld mit Rand: So sieht man, welcher Name zu welchem
   Kästchen gehört, und kein Name bricht von seinem Kästchen weg
   (Florian, 05.10.2026). Angekreuztes hebt sich ab. */
.ankreuzliste { display: flex; flex-wrap: wrap; gap: 6px; }
.ankreuzliste label {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 5px 10px; border: 0;
  border-radius: var(--rundung); background: var(--flaeche-2);
  white-space: nowrap; cursor: pointer; line-height: 1.2;
}
.ankreuzliste label:hover { background: var(--flaeche-3); }
.ankreuzliste label:has(input:checked) {
  background: var(--akzent-hell); font-weight: 600;
}

.ankreuzliste input { width: auto; margin: 0; flex: 0 0 auto; }

/* Eine Reihe von Filtern über einer Liste, gebaut wie im CMS der App:
   eine Gruppe mit hellem Grund, darin Pillen. Nur die gewählte ist
   gefüllt, die übrigen halten sich zurück. */
/* Seitenzahlen unter einer langen Liste. */
.blaettern {
  display: flex; flex-wrap: wrap; align-items: center; gap: 4px;
  margin-top: 14px; font-size: 12px;
}
.seitenzahl {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 28px; padding: 5px 9px; border-radius: 999px;
  color: var(--leise); text-decoration: none;
  font-variant-numeric: tabular-nums;
}
.seitenzahl:hover { background: var(--erhoben); color: var(--schrift); text-decoration: none; }
.seitenzahl.hier { background: var(--akzent); color: #fff; font-weight: 500; }

/* Reiter wie im CMS der Einschlaf-App: Knoepfe auf einer gemeinsamen
   Flaeche, der gewaehlte steht erhoben darauf. Er wechselt ohne
   Bewegung, weil er oft benutzt wird (Florian, 30.10.2026). */
.reiterzeile {
  display: inline-flex; flex-wrap: wrap; gap: 2px; padding: 3px;
  background: var(--flaeche-2);
  border-radius: 11px; margin-bottom: 14px;
}
.reiter {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 12px; border-radius: 8px; font-size: 13px;
  border: none; background: none; color: var(--leise);
  text-decoration: none; line-height: 1.3; cursor: pointer;
}
.reiter:hover { color: var(--schrift); text-decoration: none; }
.reiter .anzahl { color: var(--akzent); font-variant-numeric: tabular-nums; }
.reiter.hier {
  background: var(--erhoben); color: var(--schrift); font-weight: 500;
  box-shadow: 0 1px 3px color-mix(in srgb, var(--schrift) 10%, transparent);
}
.reiter.hier:hover { background: var(--erhoben); color: var(--schrift); }

/* Das Suchfeld daneben, ebenfalls wie im CMS der App. Gesucht wird beim
   Tippen; der Knopf daneben ist nur da, solange kein Javascript läuft. */
.suchfeld {
  width: 220px; padding: 7px 12px; font: inherit; font-size: 12px;
  color: inherit; border: 1px solid var(--rand); border-radius: var(--rundung);
  background: var(--grund);
}
/* In einer Reihe neben anderen Feldern behaelt die Suche ihre Breite.
   Ohne das zieht sie die Zeile auseinander, denn `form input` ist auf
   volle Breite gestellt und waere hier staerker. */
form .reihe .suchfeld, .reihe .suchfeld { width: 220px; flex: 0 0 auto; }
.reihe .zeilenwahl.schmal { flex: 0 0 auto; }
/* Knöpfe sind inline-flex; ohne diese Zeile setzt sich das gegen hidden
   durch und ein ausgeblendeter Knopf bliebe sichtbar. */
[hidden] { display: none !important; }

/* Ein Schalter für an und aus. Zwei Zustände, kein Text daneben: Was er
   schaltet, steht in der Spaltenüberschrift. */
.schalter-knopf { display: inline-flex; cursor: pointer; }
.schalter-knopf input { position: absolute; opacity: 0; width: 0; height: 0; }
.schalter-knopf span {
  width: 34px; height: 20px; border-radius: 999px; background: var(--rand);
  position: relative; transition: background-color 150ms var(--ease-out);
}
.schalter-knopf span::after {
  content: ""; position: absolute; top: 2px; left: 2px; width: 16px; height: 16px;
  border-radius: 50%; background: #fff; transition: transform 150ms var(--ease-out);
  box-shadow: 0 1px 2px rgba(0, 0, 0, .2);
}
.schalter-knopf input:checked + span { background: var(--akzent); }
.schalter-knopf input:checked + span::after { transform: translateX(14px); }
.schalter-knopf.gesperrt { opacity: .45; cursor: not-allowed; }
/* Eine Gegenpartei, deren Buchungen aufgeteilt sind: Symbol und Zahl,
   mehr braucht die Spalte nicht (Florian, 05.10.2026). */
.geteiltmarke { display: inline-flex; align-items: center; gap: 5px; color: var(--gold); }
/* Blau heisst: gelesen, wartet noch auf einen Menschen. Diese Farbe
   bedeutet im Werkzeug sonst nichts (Florian, 05.10.2026). */
.marke-punkt.m-vorschlag { --ton: var(--vorschlag-schrift); }
/* Eine Buchung, die an einer Abrechnung haengt: gesperrt, blasser, und
   die Zeile sagt, wo geaendert wird (Florian, 08.10.2026). */
tr.abrechnung > td { color: var(--leise); }
tr.abrechnung > td b, tr.abrechnung > td a { color: inherit; }


/* Eine aufgeklappte Zeile und ihr Inhalt gehoeren zusammen und sollen
   das auch zeigen: die Hauptzeile in der Hausfarbe, der Inhalt darunter
   blasser (Florian, 06.10.2026). */
tr.aufgeklappt > td { background: var(--akzent-hell); }
tr.klappe.offen > td { background: var(--flaeche-2); }

/* Der Pfeil zum Aufklappen dreht sich, wenn die Zeile offen ist. */
.klappknopf { border: none; background: none; color: var(--leise); padding: 2px; margin-right: 4px; }
.klappknopf:hover { color: var(--akzent-schrift); }
.klappknopf .symbol { transition: transform 150ms var(--ease-out); }
.klappknopf.offen .symbol { transform: rotate(90deg); }

/* Eine Auswahl direkt in einer Tabellenzeile. */
.zeilenwahl {
  padding: 4px 9px;
  font: inherit;
  font-size: 12px;
  color: inherit;
  border: 1px solid var(--rand);
  border-radius: 8px;
  background: var(--erhoben);
}
/* Was nach dem Neuladen zurueckgeholt wurde, ist gewaehlt, aber noch
   nicht gespeichert. Das muss man sehen, sonst haelt man es fuer
   gespeichert (Florian, 09.10.2026). */
.zeilenwahl.offen { background-color: var(--akzent-hell) !important; }
/* Eine Auswahl in einer Werkzeugleiste: so breit, dass die üblichen
   Namen hineinpassen, und nicht breiter. Lange Namen schneidet der
   Browser selbst ab. */
.zeilenwahl.schmal { width: 150px; }
/* Die Steuer in der Buchungszeile: vier Werte, der laengste heisst
   "19 % geschaetzt". Breiter braucht sie nicht zu sein; auf 13 Zoll
   entscheidet jede Spalte darueber, ob die Zeile passt (Florian,
   08.10.2026). Seit dem eigenen Pfeil mit Luft zum Rand 136 statt 118,
   sonst brach der Text mitten im Wort ab (Prüfung, 31.10.2026). */
.zeilenwahl.steuer { width: 136px; }

/* Ein Zeitraum, der zum Bearbeiten in der Tabelle aufgeklappt ist. Die
   Zeile steht unter ihrer eigenen und trägt die Felder nebeneinander. */
tr.bearbeitet > td { background: var(--flaeche-2); }
.zeilenbearbeitung {
  display: flex; flex-wrap: wrap; gap: 12px 14px; align-items: flex-end;
  padding: 6px 0 8px;
}
.zeilenbearbeitung .feld { flex: 0 1 150px; }
.zeilenbearbeitung .feld-weit { flex: 1 1 220px; }
.zeilenbearbeitung .feldname {
  display: block; font-size: 11px; color: var(--leise); margin-bottom: 5px;
}
.zeilenbearbeitung input, .zeilenbearbeitung select {
  width: 100%; padding: 7px 10px; font: inherit; font-size: 12px;
  color: inherit; border: 1px solid var(--rand); border-radius: 8px;
  background: var(--erhoben);
}
.zeilenbearbeitung .aktionen { display: flex; gap: 8px; align-items: center; }

/* Der eigene Name in der Leiste führt auf das eigene Blatt. */
.fuss .eigenes {
  display: block;
  margin-bottom: 6px;
  color: inherit;
  text-decoration: none;
}
.fuss .eigenes:hover b { color: var(--akzent-schrift); }
.fuss .eigenes .leise { display: block; font-size: 11px; }

/* ── Checkins je Tag ─────────────────────────────────────────────── */
.nowrap { white-space: nowrap; }
.block {
  display: inline-flex; align-items: baseline; gap: 6px;
  margin: 2px 6px 2px 0; padding: 3px 9px; border-radius: 999px;
  background: var(--flaeche-2); font-size: 12px; white-space: nowrap;
}
.block i { font-style: normal; color: var(--leise); }
/* Ein geratenes Ende sieht anders aus als ein gestempeltes. */
.block.offen { border: 1px dashed var(--warn); background: var(--erhoben); }

details.stempel { position: relative; display: inline-block; }
details.stempel > summary { list-style: none; cursor: pointer; }
details.stempel > summary::-webkit-details-marker { display: none; }
/* Die Liste waechst aus ihrem Knopf oben rechts. */
details.stempel[open] > .stempelliste {
  transform-origin: top right;
  transition: opacity 150ms var(--ease-out),
              transform 150ms var(--ease-out);
}
@starting-style {
  details.stempel[open] > .stempelliste { opacity: 0; transform: scale(0.97); }
}
@media (prefers-reduced-motion: reduce) {
  @starting-style { details.stempel[open] > .stempelliste { transform: none; } }
}
.stempelliste {
  position: absolute; right: 0; z-index: 5; min-width: 360px;
  margin-top: 6px; padding: 8px 10px; text-align: left;
  background: var(--erhoben);
  border-radius: var(--rundung); box-shadow: 0 8px 24px rgba(36, 26, 30, 0.12);
}
/* Auf dem Telefon schiebt sich die Tagesliste seitlich, statt die Seite
   breiter als den Bildschirm zu machen. Auf dem Desktop bleibt sie ohne
   Schieberahmen, der wuerde die Stempelliste abschneiden. Die Liste steht
   auf dem Telefon deshalb unten am Bildschirm (Florian, 01.11.2026). */
@media (max-width: 600px) {
  .nur-schmal-schieben { overflow-x: auto; }
  .stempelliste {
    position: fixed; left: 16px; right: 16px; bottom: 16px; z-index: 60;
    min-width: 0; max-height: 60vh; overflow-y: auto;
  }
}
.stempelzeile {
  display: grid; grid-template-columns: 48px 70px 1fr auto;
  align-items: center; gap: 10px; padding: 5px 0; font-size: 12px;
  box-shadow: inset 0 -1px 0 var(--flaeche-2);
}
.stempelzeile:last-child { box-shadow: none; }
@media print { .block.offen { border-style: dashed; } .rasterrahmen { overflow: visible; } }

/* ── Grafiken ────────────────────────────────────────────────────────
   Alles SVG aus kern/grafik.py. Farben über die Variablen, damit die
   Grafik aussieht wie der Rest und im Druck mit ihm grau wird. */
.grafik { display: block; overflow: visible; }
.sparkline path, .sparkline polyline { fill: none; stroke-linejoin: round; stroke-linecap: round; }
/* Linien sind seit dem 03.11.2026 Pfade statt Polylinien. Ein Pfad ist
   ohne Angabe schwarz gefuellt; das stand als schwarze Flaeche unter
   jeder kleinen Verlaufslinie. Hier fuer alle Linien einmal ausgeschlossen. */
.grafik path.zug, .grafik path.soll, .grafik path.ist { fill: none; }
.sparkline .ist { stroke: var(--akzent); stroke-width: 2; }
.sparkline .soll { stroke: color-mix(in srgb, var(--leise) 45%, transparent); stroke-width: 2; }
.sparkline circle.ist { fill: var(--akzent); stroke: none; }

.saeulen .wert { fill: var(--akzent); fill: url(#vl-saeule); }
/* Die Stopps der Verlaeufe aus basis.html (Florian, 03.11.2026): leicht,
   damit man den Verlauf spuert, aber nicht sieht. */
.verlaeufe { position: absolute; width: 0; height: 0; overflow: hidden; }
.vl-hell { stop-color: color-mix(in srgb, var(--akzent) 82%, #fff); }
.vl-tief { stop-color: color-mix(in srgb, var(--akzent) 90%, #000); }
.vl-flaeche-oben { stop-color: var(--akzent); stop-opacity: 0.18; }
.vl-flaeche-unten { stop-color: var(--akzent); stop-opacity: 0; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .vl-hell { stop-color: color-mix(in srgb, var(--akzent) 90%, #fff); }
  :root:not([data-theme="light"]) .vl-flaeche-oben { stop-opacity: 0.12; }
}
:root[data-theme="dark"] .vl-hell { stop-color: color-mix(in srgb, var(--akzent) 90%, #fff); }
:root[data-theme="dark"] .vl-flaeche-oben { stop-opacity: 0.12; }
.grafik .flaeche { fill: url(#vl-flaeche); stroke: none; }
.saeulen .vergleich { fill: var(--diagramm-zweit); }
.saeulen text { font-size: 11px; fill: var(--leise); }
/* "balken" ist schon der Anteilsbalken in Tabellen, deshalb "waagerecht". */
.waagerecht .wert { fill: var(--akzent); fill: url(#vl-quer); }
.waagerecht .minus { fill: var(--warn); }
.waagerecht .null { stroke: var(--rand); stroke-width: 1; }
.waagerecht text { font-size: 11px; fill: var(--leise); }
.waagerecht text.name { fill: var(--schrift); font-weight: 600; }
/* Das Jahr in Stunden: Spalte je Tag, Zeile je Stunde. Die Deckkraft je
   Kachel setzt die Grafik, die Farbe steht hier (Florian, 10.10.2026). */
/* Das Jahr in Stunden, im Satz des Abwesenheitskalenders: Die Achse
   steht fest, das Raster schiebt sich daneben (Florian, 10.10.2026). */
.stundenrahmen { display: flex; align-items: flex-start; padding: 0 18px 14px; }
.stundenschiene { overflow-x: auto; flex: 1; min-width: 0; }
/* Stufen als Mischung zur Hausfarbe statt als Deckkraft: Auf dunklem
   Grund verschwanden die blassen Stufen sonst im Hintergrund. */
.stundenraster .stueck { fill: color-mix(in srgb, var(--akzent) calc(var(--stufe, 1) * 100%), var(--stufen-ende)); }
/* Dieselben Toene wie die Zellen dort: frei hell, Wochenende dunkler. */
.stundenraster .leer { fill: var(--grund); }
.stundenraster .frei { fill: var(--frei); }
.stundenraster .trenner { stroke: var(--rand); stroke-width: 1; }
.stundenraster .heute { fill: none; stroke: var(--schrift); stroke-width: 1; }
.stundenraster text { font-size: 11px; fill: var(--leise); }
.stundenraster text.monat {
  font-size: 11px; font-weight: 600; fill: var(--leise);
}
.stundenraster text.tagkopf { font-variant-numeric: tabular-nums; }
.stundenraster text.tagkopf.wochenende { fill: var(--akzent-schrift); }
.stundenraster text.tagkopf.heute { fill: var(--schrift); }
/* Wie viele an dem Tag gearbeitet haben: dieselbe Reihe wie "Abwesend"
   im Abwesenheitskalender und wie dort leise, auch heute. Der Tag ist
   oben schon fett, die Zahl muss es nicht auch sein (Florian,
   10.10.2026). */
.stundenraster text.anwesend { font-variant-numeric: tabular-nums; }
.stundenachse text { font-size: 11px; fill: var(--leise); }
/* Die Linie im Dashboard: darüber alle, darunter nur die Geschäftsführung. */




@media print {
  .sparkline .ist, .saeulen .wert { fill: #555; stroke: #555; }
  .grafik .flaeche { display: none; }
  .sparkline .ist { fill: none; }
  .saeulen .vergleich { fill: #ccc; }
}


/* Jahresknöpfe in einer Schiene, wie die Zeitraumpillen im CMS der App. */
/* Datumsfeld mit eigenem Kalender. Der Kalender des Browsers sieht in
   jedem Browser anders aus und nirgends nach diesem Werkzeug; dieser hier
   gehoert dazu (Florian, 04.10.2026). Ohne JavaScript bleibt das Feld des
   Browsers stehen, deshalb steht hier nichts, was es kaputtmachen wuerde. */
.datumsfeld { position: relative; display: inline-flex; align-items: stretch; }
.datumsfeld input.datumsanzeige { padding-right: 34px; width: 100%; }
/* Ein falsches Datum im Warnrot, nicht in der Hausfarbe. */
.datumsfeld input.datumsanzeige.falsch { box-shadow: 0 0 0 2px var(--warn); }
.datumsknopf {
  position: absolute; right: 1px; top: 1px; bottom: 1px; width: 32px;
  display: inline-flex; align-items: center; justify-content: center;
  border: 0; background: none; color: var(--leise); cursor: pointer;
  border-radius: var(--rundung);
}
.datumsknopf:hover { color: var(--akzent); background: var(--erhoben); }
.kalenderblatt {
  position: fixed; z-index: 60;
  width: 252px; padding: 10px; background: var(--erhoben);
  border: 0; border-radius: var(--rundung);
  box-shadow: 0 10px 30px rgba(36, 26, 30, 0.14);
}
.kalenderkopf {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: 8px;
}
.kalenderkopf b { font-size: 13px; }
.kalenderkopf button {
  border: 0; background: none; color: var(--leise); cursor: pointer;
  padding: 4px 6px; border-radius: var(--rundung); line-height: 0;
}
.kalenderkopf button:hover { color: var(--akzent); background: var(--flaeche-2); }
.kalendergitter { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; }
.kalendergitter .wtag {
  font-size: 11px; color: var(--leise); text-align: center; padding: 2px 0 4px;
  letter-spacing: 0.04em;
}
.kalendergitter button {
  border: 0; background: none; cursor: pointer; padding: 6px 0;
  font-size: 12px; color: var(--schrift); border-radius: var(--rundung);
}
.kalendergitter button:hover { background: var(--flaeche-2); }
.kalendergitter button.fremd { color: var(--leise); opacity: 0.5; }
.kalendergitter button.wochenende { color: var(--leise); }
.kalendergitter button.heute { box-shadow: inset 0 0 0 1.5px var(--leise); }
.kalendergitter button.gewaehlt { background: var(--akzent); color: #fff; }
/* Zwoelf Monate statt eines Monatsgitters, sonst dasselbe Blatt. */
.monatsgitter { display: grid; grid-template-columns: repeat(4, 1fr); gap: 4px; }
.monatsgitter button {
  padding: 8px 0; font: inherit; font-size: 12px; color: inherit;
  border: none; border-radius: var(--rundung); background: none; cursor: pointer;
}
.monatsgitter button:hover { background: var(--flaeche-2); }
.monatsgitter button.heute { box-shadow: inset 0 0 0 1.5px var(--leise); }
.monatsgitter button.gewaehlt { background: var(--akzent); color: #fff; }
.monatsblatt { min-width: 236px; }
.kalenderfuss {
  display: flex; gap: 8px; justify-content: space-between; margin-top: 8px;
}
.kalenderfuss button {
  border: 0; background: none; color: var(--leise); cursor: pointer;
  font-size: 12px; padding: 4px 6px; border-radius: var(--rundung);
}
.kalenderfuss button:hover { color: var(--akzent); background: var(--flaeche-2); }

/* Eine Werkzeugleiste: Jahre, Knoepfe und Legende auf einer Linie. Der
   Knopf bringt ein eigenes align-self mit, ein aufklappbares Formular
   einen Aussenabstand; in dieser Reihe gilt beides nicht. Das Fenster,
   das aus dem Aufklappen entsteht, bleibt aussen vor: Es zentriert sich
   selbst ueber der Seite. */
.werkzeugleiste {
  display: flex; align-items: center; flex-wrap: wrap; gap: 10px;
  margin-bottom: 18px;
}
.werkzeugleiste > *:not(dialog) { align-self: center; margin: 0; }
.schiene {
  display: inline-flex; align-items: center; gap: 2px; padding: 3px;
  border-radius: 11px; background: var(--flaeche-2);
}
.pille {
  padding: 6px 12px; border-radius: 8px; font-size: 13px;
  color: var(--leise); text-decoration: none; white-space: nowrap;
}
.pille:hover { color: var(--schrift); text-decoration: none; }
.pille.aktiv {
  background: var(--erhoben); color: var(--schrift); font-weight: 500;
  box-shadow: 0 1px 3px color-mix(in srgb, var(--schrift) 10%, transparent);
}
.nur-druck { display: none; }
@media print { .nur-druck { display: block; } }


/* ── Weitere Diagrammformen ──────────────────────────────────────── */
.linie .zug, .doppelt .zug { fill: none; stroke: var(--schrift); stroke-width: 2; stroke-linejoin: round; }
.linie .punkt, .doppelt .punkt { fill: var(--erhoben); stroke: var(--schrift); stroke-width: 2; }
.linie text, .doppelt text, .streu text, .matrix text { font-size: 11px; fill: var(--leise); }
.linie text.zahl { fill: var(--schrift); font-weight: 600; }
.streu .gitter { stroke: var(--rand); stroke-width: 1; }
.streu .achse { stroke: var(--leise); stroke-width: 1; }
.streu .punkt { fill: var(--akzent); fill-opacity: 0.85; }
.streu text.name { fill: var(--schrift); font-weight: 600; }
/* Die Linie der Kostendeckung: gestrichelt, damit sie nicht wie eine
   Achse aussieht, und leise, damit sie die Blasen nicht ueberstimmt. */
.streu .schwelle { stroke: var(--leise); stroke-width: 1; stroke-dasharray: 4 4; opacity: 0.7; }
.streu text.schwellenname { fill: var(--leise); font-style: italic; }
.ring .stueck { stroke: color-mix(in srgb, var(--akzent) calc(var(--stufe, 1) * 100%), var(--stufen-ende)); }
/* Drei Balken, eine Farbe in drei Stufen: kräftig, mittel, hell.
   Eine zweite Farbe gibt es nicht (Florian, 03.10.2026). */
.paare .vergleich { fill: var(--akzent); opacity: 0.45; }
.paare .zweit { fill: var(--diagramm-zweit); }
.grafikprobe.zweit { background: var(--diagramm-zweit); }
.paare text.zahl { font-size: 11px; }
.matrix .leer { fill: var(--grund); }
.matrix .wert { fill: color-mix(in srgb, var(--akzent) calc(var(--stufe, 1) * 100%), var(--stufen-ende)); }
.matrix .minus { fill: color-mix(in srgb, var(--warn) calc(var(--stufe, 1) * 100%), var(--stufen-ende)); }
.matrix text.name { fill: var(--schrift); font-weight: 600; }
.matrix text.innen { font-size: 11px; fill: var(--schrift); }
.matrix text.innen.hell { fill: #fff; }
/* Zwei Karten nebeneinander, etwa zwei Ringe; untereinander, wenn es eng wird. */
.zweispaltig { display: grid; grid-template-columns: 1fr 1fr; gap: var(--luft); margin-bottom: var(--luft); }
@media (max-width: 1000px) { .zweispaltig { grid-template-columns: 1fr; } }
/* Wird die Karte zu schmal fuer Ring und Namen nebeneinander, rutscht
   die Legende unter den Ring, statt die Namen zu zerhacken. */
.ringkarte { display: flex; flex-wrap: wrap; gap: 18px; align-items: center; padding: 16px 18px; }
.ringkarte .grafik.ring { flex: none; }
.ringkarte .legende { display: flex; flex-direction: column; gap: 5px; font-size: 12px; min-width: 0; flex: 1 1 260px; }
.ringkarte .legende > span { display: flex; align-items: flex-start; gap: 8px; white-space: nowrap; }
.ringkarte .legende .probe { margin-top: 3px; }
/* Der Name darf auf zwei Zeilen: Er ist es, an dem man das Projekt
   erkennt, und "Einschlafen mit Gesc…" erkannte keiner (Prüfung,
   30.10.2026). Erst danach wird gekuerzt. */
.ringkarte .legende .name {
  flex: 1 1 auto; min-width: 0; overflow: hidden; white-space: normal;
  /* Getrennt wird an der Silbe, nicht mitten im Wort. */
  overflow-wrap: break-word; hyphens: auto; display: -webkit-box;
  -webkit-line-clamp: 2; -webkit-box-orient: vertical;
}
.ringkarte .legende b { flex: none; padding-left: 10px; font-variant-numeric: tabular-nums; }
.ringkarte .legende em { flex: none; font-style: normal; color: var(--leise); min-width: 38px; text-align: right;
                        font-variant-numeric: tabular-nums; }
.ringkarte .titel { font-size: 12px; font-weight: 560; color: var(--sehr-leise); margin-bottom: 8px; }

/* ── Wartekreis ──────────────────────────────────────────────────────
   Ein Knopf mit data-warten zeigt nach dem Absenden einen Kreis und den
   Text, damit klar ist: Hier passiert noch etwas. */
.wartekreis {
  display: inline-block; width: 14px; height: 14px; border-radius: 50%;
  border: 2px solid currentColor; border-right-color: transparent;
  animation: drehen .8s linear infinite; flex: none;
}
/* Den Abstand zum Wort gibt der Behaelter. Der Kreis steht nur in Knoepfen
   und in der Zeile unter dem Fortschrittsbalken, beide sind flex mit
   Luecke. Ein eigener Rand am Kreis kam dort obendrauf, und wo kein Wort
   steht, schob er ihn aus der Mitte (Florian, 07.10.2026). */
@keyframes drehen { to { transform: rotate(360deg); } }
/* Gesperrt, weil es nichts zu speichern gibt. Anderer Grund als das
   Warten oben, deshalb auch ein anderer Zeiger. */
.knopf-haupt.nichts-geaendert, .knopf.nichts-geaendert {
  opacity: .4; cursor: default;
}
.dreifach .zug.einnahmen, .dreifach .punkt:not(.tkp) { stroke: var(--schrift); }
.dreifach .zug { fill: none; stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.dreifach .punkt { fill: var(--erhoben); stroke-width: 2; }
.dreifach .zug.tkp { stroke: var(--diagramm-zweit); stroke-width: 2.6; }
.dreifach .punkt.tkp { stroke: var(--diagramm-zweit); }
.dreifach .zug.tkp { stroke-dasharray: 5 4; }
.dreifach text { font-size: 11px; fill: var(--leise); }
.probe.linie-dunkel { background: var(--schrift); }
.probe.linie-warn { background: var(--diagramm-zweit); }
/* Drei Ringe bleiben nebeneinander, auch auf einem 13-Zoll-Schirm
   (Florian, 03.10.2026). Wird es eng, rückt die Legende unter den Ring,
   statt die Projektnamen abzuschneiden. */
.dreispaltig { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: var(--luft); margin-bottom: var(--luft); }
@media (max-width: 820px) { .dreispaltig { grid-template-columns: 1fr; } }
@media (max-width: 1500px) {
  .dreispaltig .ringkarte { flex-direction: column; align-items: stretch; gap: 12px; }
  .dreispaltig .ringkarte .grafik.ring { align-self: center; }
}
.wochenlinien .zug { fill: none; stroke-width: 2.2; stroke-linejoin: round; stroke-linecap: round; }
.wochenlinien .zug.ist { stroke: var(--akzent); }
.wochenlinien .zug.soll { stroke: var(--akzent); opacity: 0.32; stroke-width: 2; }
.wochenlinien .punkt { stroke-width: 2; fill: var(--erhoben); }
.wochenlinien .punkt.ist { stroke: var(--akzent); }
.wochenlinien .punkt.soll { stroke: var(--akzent); opacity: 0.4; }
.wochenlinien .feld { fill: transparent; }
.wochenlinien text { font-size: 11px; fill: var(--leise); }
/* Die Linien tragen ihren Namen am Ende selbst (Florian, 03.11.2026). */
.wochenlinien text.zugname, .saldoverlauf text.zugname { font-size: 12px; font-weight: 600; }
.wochenlinien text.zugname.ist { fill: var(--akzent-schrift); }
.wochenlinien text.zugname.soll { fill: var(--sehr-leise); }

/* Zeitkonto mit Prognose, wie bei Ebbline: bis heute voll, danach
   gepunktet in der Farbe der Ampel, die Null als gestrichelte Schwelle. */
.saldoverlauf .zug { fill: none; stroke-width: 2.2; stroke-linejoin: round; stroke-linecap: round; }
/* Drei Linien gleich stark (Florian, 03.11.2026): der Kontostand
   schwarz, Ist pink, Soll blass pink, die Prognose gepunktet. */
.saldoverlauf .zug.konto { stroke: var(--schrift); }
.saldoverlauf .zug.prognose { stroke: var(--leise); stroke-dasharray: 1 6; }
.saldoverlauf.gut .zug.prognose { stroke: var(--gut); }
.saldoverlauf.knapp .zug.prognose { stroke: var(--gold); }
.saldoverlauf.warn .zug.prognose { stroke: var(--warn); }
.saldoverlauf .null { stroke: var(--sehr-leise); stroke-width: 1; stroke-dasharray: 4 5; opacity: 0.6; }
.saldoverlauf text { font-size: 11px; fill: var(--leise); }
.saldoverlauf text.nullname { font-style: italic; fill: var(--sehr-leise); }
.saldoverlauf text.zugname { fill: var(--schrift); }
.saldoverlauf .punkt.heute { fill: var(--schrift); stroke: var(--erhoben); stroke-width: 2.5; }
.saldoverlauf .punkt.ende { fill: var(--leise); stroke: var(--erhoben); stroke-width: 2; }
.saldoverlauf.gut .punkt.ende { fill: var(--gut); }
.saldoverlauf.knapp .punkt.ende { fill: var(--gold); }
.saldoverlauf.warn .punkt.ende { fill: var(--warn); }
.grafik-kopf .ampel { margin-left: auto; font-size: 13px; font-weight: 600; }
/* Die untere Spur: Ist und Soll je Woche, leiser als das Konto. */
.saldoverlauf .zug.woche-ist { stroke: var(--akzent); }
.saldoverlauf .zug.woche-soll { stroke: var(--akzent); opacity: 0.32; }
.saldoverlauf text.zugname.woche-ist { fill: var(--akzent-schrift); font-size: 11px; }
.saldoverlauf text.zugname.woche-soll { fill: var(--sehr-leise); font-size: 11px; }
/* Beschriftungen bekommen einen Hof in der Kartenfarbe, damit eine Linie
   darunter sie nicht durchstreicht. */
.saldoverlauf text.nullname, .saldoverlauf text.zugname {
  paint-order: stroke; stroke: var(--erhoben); stroke-width: 4px; stroke-linejoin: round;
}
.grafikprobe.woche-ist { background: var(--akzent); }
.grafikprobe.woche-soll { background: var(--akzent); opacity: 0.32; }
.grafikprobe.konto, .probe.strich.konto { background: var(--schrift); }
/* Die Probe der Prognose ist gepunktet wie die Linie, in der Ampelfarbe. */
.probe.strich.prognose {
  background: radial-gradient(circle, var(--leise) 1.4px, transparent 1.6px) 0 50% / 6px 3px repeat-x;
}
.probe.strich.prognose.ampel-gut { background-image: radial-gradient(circle, var(--gut) 1.4px, transparent 1.6px); }
.probe.strich.prognose.ampel-knapp { background-image: radial-gradient(circle, var(--gold) 1.4px, transparent 1.6px); }
.probe.strich.prognose.ampel-warn { background-image: radial-gradient(circle, var(--warn) 1.4px, transparent 1.6px); }
.grafikprobe.prognose { background: var(--leise); }
.grafik-kopf { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 12px; margin-bottom: 6px; }
.grafik-kopf b { font-size: 14px; }
.grafik-kopf .leise { font-size: 12px; }

/* Ampel mit fester Bedeutung, überall gleich (Florian, 03.11.2026):
   passt, wird knapp, ist drüber. Ein Punkt vor dem Text trägt die Farbe. */
.ampel::before {
  content: ""; display: inline-block; width: 7px; height: 7px; border-radius: 50%;
  margin-right: 6px; vertical-align: 1px; background: var(--leise);
}
.ampel-gut::before { background: var(--gut); }
.ampel-knapp::before { background: var(--gold); }
.ampel-warn::before { background: var(--warn); }
.ampel-warn { color: var(--warn); }

/* Auftakt: bis das Skript eine Grafik oder Zahl aufzieht, bleibt sie
   unsichtbar, sonst blitzte sie fertig auf und finge dann von vorn an.
   Laeuft das Skript nicht, holt die Notfall-Animation nach zwei
   Sekunden alles herein. Im Druck steht immer alles da. */
@media screen {
  .auftakt svg.grafik:not(.da), .auftakt .kachel .wert:not(.da) {
    opacity: 0; animation: auftakt-notfall 0s 2s forwards;
  }
}
@keyframes auftakt-notfall { to { opacity: 1; } }
/* Probe für Linien statt Flächen: ein Strich, kein Klotz. */
.probe.strich { height: 3px; border-radius: 2px; background: var(--akzent); }
.probe.strich.blass { opacity: 0.32; }

/* ── Heute: wer fehlt, wer arbeitet gerade ───────────────────────────
   Steht ganz oben und nur dann, wenn es etwas zu sagen gibt. */
.heute-streifen { padding: 12px 18px; margin-bottom: 14px; }
/* Links der Name der Reihe, rechts die Personen untereinander in zwei
   Spalten (Florian, 03.11.2026). Vorher liefen sie als Fliesstext
   nebeneinander, und Name und Projekt waren schwer auseinanderzuhalten. */
.heute-reihe {
  display: grid; grid-template-columns: 128px minmax(0, 1fr); align-items: start;
  gap: 8px 18px; padding: 7px 0;
}
.heute-reihe .heute-label { padding-top: 4px; }
/* So viele Spalten, wie die Breite zulaesst (Florian, 03.11.2026). */
.heute-liste {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(min(290px, 100%), 1fr)); gap: 6px 24px;
}
.heute-liste > .leise { grid-column: 1 / -1; padding-top: 3px; }
@media (max-width: 760px) {
  .heute-reihe { grid-template-columns: minmax(0, 1fr); gap: 6px; }
}
.heute-reihe + .heute-reihe { box-shadow: inset 0 1px 0 var(--flaeche-2); }
.heute-label {
  font-size: 12px; font-weight: 560; color: var(--sehr-leise); min-width: 128px;
}
.heute-eintrag { display: flex; align-items: center; gap: 8px; font-size: 11px; min-width: 0; }
.heute-eintrag > .leise { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* ── Diagramme überfahren ────────────────────────────────────────────
   Der Kasten folgt dem Zeiger, die Markierungen sitzen auf den
   Messpunkten. Beides baut das Skript in basis.html. */
/* Hell auf erhobener Flaeche wie im CMS der Einschlaf-App (Florian,
   30.10.2026). Bis dahin dunkel. */
.diagramm-hinweis {
  position: fixed; z-index: 60; pointer-events: none;
  background: var(--erhoben); color: var(--schrift);
  border-radius: 10px; padding: 8px 12px; min-width: 144px;
  font-size: 12px; line-height: 1.45; max-width: 300px;
  box-shadow: var(--schatten-hoch);
}
.diagramm-hinweis .titel {
  display: block; font-weight: 600; margin-bottom: 4px;
}
.diagramm-hinweis .zeile { display: flex; align-items: center; gap: 7px; white-space: nowrap; }
/* Ein langer Reihenname bricht um, statt den Wert aus dem dunklen
   Kasten zu schieben (Prüfung, 30.10.2026). */
.diagramm-hinweis .zeile .name { color: var(--leise); white-space: normal; min-width: 0; }
.diagramm-hinweis .zeile b { flex: none; margin-left: auto; padding-left: 14px; font-variant-numeric: tabular-nums; }
.grafikprobe {
  width: 8px; height: 8px; border-radius: 2px; flex: none;
  background: var(--diagramm-zweit);
  /* Ein leiser Ring, damit auch eine helle Probe im hellen Kasten als
     Flaeche zu sehen ist. */
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--schrift) 12%, transparent);
}
.grafikprobe.wert, .grafikprobe.ist { background: var(--akzent); }
/* Die Einnahmen laufen im Zwölfmonatsbild als dunkle Linie, nicht als
   Säule: Die Probe im Kasten muss dieselbe Farbe tragen. */
.grafikprobe.einnahmen { background: var(--schrift); }
.grafikprobe.vergleich, .grafikprobe.soll { background: var(--akzent); opacity: 0.4; }
.grafikprobe.tkp { background: var(--diagramm-zweit); }
.grafikprobe.minus { background: var(--warn); }
.grafikprobe.summe { background: var(--flaeche-3); }

.grafik .spur { fill: transparent; }
.grafik .marker { pointer-events: none; }
.grafik .fuehrung { stroke: var(--leise); stroke-width: 1; opacity: 0.35; }
.grafik .treffer { fill: var(--erhoben); stroke: var(--akzent); stroke-width: 2.5; }
.grafik .treffer.einnahmen { stroke: var(--schrift); }
.grafik .treffer.vergleich, .grafik .treffer.soll { stroke: var(--akzent); opacity: 0.55; }
.grafik .treffer.tkp { stroke: var(--diagramm-zweit); }
.grafik .treffer.minus { stroke: var(--warn); }
.grafik [data-werte]:not(.spur):hover { filter: brightness(1.12); }
.saeulen text.zahl { font-size: 11px; fill: var(--leise); font-weight: 600; }
.dreifach text.zahl { fill: var(--schrift); }
.dreifach text.zahl.tkp { fill: var(--leise); }
@media print { .diagramm-hinweis { display: none !important; } }
/* Eine Linie in eigenem Maßstab über den Säulen, etwa Arbeitsstunden über Geld. */
.saeulen .zug.linie { fill: none; stroke: var(--schrift); stroke-width: 2;
                      stroke-linejoin: round; stroke-linecap: round; }
.saeulen .punkt.linie { fill: var(--erhoben); stroke: var(--schrift); stroke-width: 2; }
.saeulen text.zahl.linie { fill: var(--schrift); }
.grafikprobe.linie { background: var(--schrift); }
.grafik .treffer.linie { stroke: var(--schrift); }
/* Zwei Blasen je Stelle: kräftig das Geld, rosa die Reichweite. */
.streu .punkt.zweit { fill: var(--diagramm-zweit); }
.streu text.achsenname { font-size: 11px; fill: var(--sehr-leise); font-weight: 560; }
/* Die Legende des Quellenrings ist eine kleine Tabelle: Name, Geld,
   Anteil, Downloads, TKP. Sie trägt die Farbe des Rings als Punkt. */
.ringkarte table.quellen { flex: 1; min-width: 0; }
.ringkarte table.quellen th { padding: 0 10px 8px; border: 0; }
.ringkarte table.quellen td { padding: 7px 10px; }
.ringkarte table.quellen tr:last-child td { border-bottom: none; }
.ringkarte table.quellen .probe { margin-right: 8px; }
.ringkarte table.quellen tfoot td { box-shadow: inset 0 1px 0 var(--flaeche-3); }
/* Der Schein in der Zielecke des Blasendiagramms: blass, hinter allem. */
.diagramm-hinweis .zeile.ohne-probe { padding-left: 15px; }

/* ── Kleine Klassen statt Inline-Stilen ─────────────────────────────
   Jede steht fuer ein Muster, das in den Vorlagen wiederkehrte: 180 Mal
   style="...", davon ein Dutzend Mal derselbe Innenabstand einer Karte
   mit Grafik. Ein Muster wird jetzt an einer Stelle geaendert, und die
   Vorlagen bleiben frei von style= (Florian, 04.10.2026). */
.karte.grafik { padding: 16px 18px 10px; }
.legende-reihe.unter-grafik { margin: 8px 0 0; justify-content: flex-start; }
.ringkarte.knapp { padding: 0 0 6px; }
.ringkarte.knapp .titel { margin: 0; }
.klein { font-size: 12px; }
.winzig { font-size: 11px; }
/* Ein erklaerender Absatz, ueber oder unter einer Tabelle. `innen` steht
   er in einer Karte und traegt deren Innenabstand selbst. */
.erklaerung { margin: 0 0 12px; font-size: 12px; color: var(--leise); }
.erklaerung.innen { margin: 0; padding: 10px 18px 14px; }
/* Eine Zeile mit Feldern im Innern einer Karte, auf gleicher Flucht
   mit dem Text darueber. */
.reihe.innen { padding: 10px 18px 0; align-items: end; display: flex; }
/* Die Auswahl der Buchung nimmt die Breite, die da ist: Datum,
   Verwendungszweck und Betrag sollen in eine Zeile passen. */
.reihe.innen label.breit { flex: 1 1 auto; min-width: 0; }
.reihe.innen label.breit select { width: 100%; }
.inline { display: inline; }
.reihe { display: inline-flex; align-items: center; gap: 8px; flex-wrap: wrap; }
/* Zwei Knoepfe in einer schmalen Tabellenzelle: Ohne das bricht die Reihe
   um und sie stehen uebereinander (Florian, 08.10.2026). */
.reihe.nowrap { flex-wrap: nowrap; }
.voll { width: 100%; }
.dehnbar { flex: 1; }
.rechts { margin-left: auto; }

/* ── Monatsraster ───────────────────────────────────────────────────
   Zeile je Monat, Spalte je Quelle. Die Kopfzeile sagt, was von selbst
   kommt; die Zellen tragen die Marken des Hauses (Florian, 08.10.2026). */
/* Glatte Zeilenhoehe im Kopf: 26 Pixel Knopf minus zweimal 5 Abstand
   sind genau 16, und damit stehen Koepfe mit und ohne Knopf auf
   derselben Grundlinie. Mit den geerbten 16,5 blieb ein Pixel Versatz
   (Florian, 09.10.2026). */
.raster-monate th {
  text-align: center; vertical-align: bottom; line-height: 16px;
}
.raster-monate thead tr:first-child th { border-bottom: none; padding-bottom: 2px; }
.raster-monate th:first-child { text-align: left; }
.raster-monate td { text-align: center; }
.raster-monate td:first-child { text-align: left; white-space: nowrap; }
.raster-monate .marke-punkt { white-space: nowrap; }
.raster-monate a.marke-punkt { text-decoration: none; }
.raster-monate a.marke-punkt:hover { filter: brightness(0.95); }
/* Der Knopf am Spaltenkopf: Die Quelle kommt von selbst, und ein Klick
   holt sie sofort. Er sitzt in der Zeile des Namens, damit die Kopfzeile
   einzeilig bleibt, und ist kraeftiger als der Kopftext, damit man ihn
   als Knopf erkennt (Florian, 08.10.2026). */
.abrufknopf {
  display: inline-flex; align-items: center; justify-content: center;
  /* Der Knopf ist 26 Pixel hoch, die Zeile des Spaltenkopfs nur 16,5.
     Als eigenstaendiger Kasten in der Zeile zoege er sie auseinander,
     und die Koepfe mit Knopf staenden hoeher als die ohne (Florian,
     09.10.2026). Negative Abstaende oben und unten nehmen ihm genau den
     Unterschied wieder weg; er ragt ueber die Zeile hinaus, ohne sie zu
     verschieben. */
  vertical-align: top; margin: -5px 0 -5px 3px; padding: 5px;
  border: none; border-radius: 999px; cursor: pointer;
  /* In der Farbe des Spaltenkopfs: Das Zeichen gehoert zum Namen und
     soll ihn nicht ueberstrahlen (Florian, 08.10.2026). Dass es ein
     Knopf ist, zeigt der Zeiger und die Hausfarbe beim Darueberfahren. */
  background: none; color: var(--leise);
}
/* Ein leicht graues Feld unter dem Zeichen, kein roter Punkt: Der Knopf
   sitzt in einem Spaltenkopf und soll ihn nicht uebertoenen (Florian,
   09.10.2026). Die Hausfarbe traegt das Zeichen selbst. */
.abrufknopf:hover {
  background: color-mix(in srgb, var(--leise) 14%, transparent);
  color: var(--akzent);
}
.abrufknopf .wartekreis { margin: 0; }
/* Eine Zeile, zu der jemand ueber einen Verweis gesprungen ist. */
tr.hervorgehoben > td, .karte.hervorgehoben {
  background: var(--akzent-hell);
  animation: angesprungen 1200ms ease-out;
}
/* Kurz kraeftiger, dann zur Ruhe: Das Auge findet die Zeile, ohne zu
   suchen. Nur Farbe, deshalb auch bei weniger Bewegung. */
@keyframes angesprungen {
  from { background: color-mix(in srgb, var(--akzent) 28%, var(--erhoben)); }
}
.rechtsbuendig { justify-content: flex-end; }
.abstand-oben { margin-top: var(--luft); }
.abstand-unten { margin-bottom: var(--luft); }
.abstand-links { margin-left: 6px; }
.abstand-seitlich { margin: 0 10px; }
/* Kopf und Fuss einer Karte, wenn dort Knoepfe und Text statt einer
   Tabellenzeile stehen. */
.kartenkopf { padding: 14px 18px 0; display: flex; gap: 18px; flex-wrap: wrap; align-items: baseline; }
.kartenfuss { padding: 14px 18px; display: flex; gap: 12px; align-items: center; flex-wrap: wrap; }
.kartenfuss.getrennt { box-shadow: inset 0 1px 0 var(--flaeche-2); }
.eingerueckt { padding: 0 18px 12px; }
.karte.schmal { max-width: 620px; }
.karte.mittel { max-width: 860px; }
.wahlspalte { min-width: 150px; }
/* Ein langer Verwendungszweck steht gekuerzt in der Zeile und ganz im
   Titel; sonst dehnt eine einzige Buchung die Tabelle ueber den Rand. */
td.kurztext { max-width: 150px; overflow: hidden; text-overflow: ellipsis;
              white-space: nowrap; }
.balkenspalte { width: 40%; }
.zeilenwahl.kurz { width: 110px; text-align: right; }
.zeilenwahl.halb { width: 160px; }
.zeilenwahl.lang { width: 230px; }
.schalter.knapp { padding: 0; }
.hinweis.warn { background: var(--warn-flaeche); color: var(--warn); }
/* Ein einzelnes Wort, das in einer leisen Zeile nicht untergehen darf. */
.warnschrift { color: var(--warn); }

/* ── Assistent ───────────────────────────────────────────────────────
   Die Frage als Blase rechts, die Antwort über die ganze Breite: Dort
   stehen Zahlen und Aufzählungen, und die brauchen Platz. Die Eingabe
   klebt unten am Bild, damit sie beim langen Gespräch nicht wegläuft. */
.gespraech { display: flex; flex-direction: column; gap: 12px; margin-bottom: var(--luft); }
.blase { border-radius: var(--rundung); }
.blase.frage {
  align-self: flex-end; max-width: 70%; padding: 10px 16px;
  background: var(--akzent); color: #fff; font-weight: 500;
}
.blase.antwort {
  background: var(--erhoben); box-shadow: var(--kartenschatten); padding: 16px 22px;
}
/* Während der Assistent nachdenkt: drei Punkte, die der Reihe nach
   aufleuchten. Mehr verspricht die Anzeige nicht, denn mehr weiss sie
   auch nicht (Florian, 05.10.2026). */
.blase.denkt { display: flex; align-items: center; gap: 10px; color: var(--leise); font-size: 13px; }
.punkte { display: inline-flex; gap: 4px; }
.punkte i {
  width: 6px; height: 6px; border-radius: 50%; background: var(--leise);
  animation: tippen 1.2s ease-in-out infinite;
}
.punkte i:nth-child(2) { animation-delay: .15s; }
.punkte i:nth-child(3) { animation-delay: .3s; }
@keyframes tippen {
  0%, 60%, 100% { opacity: .25; transform: translateY(0); }
  30% { opacity: 1; transform: translateY(-3px); }
}
@media (prefers-reduced-motion: reduce) { .punkte i { animation: none; opacity: .5; } }
.fliesstext p { margin: 0 0 10px; line-height: 1.55; }
.fliesstext p:last-child { margin-bottom: 0; }
.fliesstext ul, .fliesstext ol { margin: 0 0 10px; padding-left: 20px; line-height: 1.55; }
.fliesstext li { margin-bottom: 4px; }
.fliesstext li:last-child { margin-bottom: 0; }
.fliesstext ul:last-child, .fliesstext ol:last-child { margin-bottom: 0; }
.fliesstext code { font-size: 12px; background: var(--flaeche-2); padding: 1px 5px; border-radius: 5px; }
.herkunft { margin-top: 12px; box-shadow: inset 0 1px 0 var(--flaeche-2); padding-top: 10px; }
.herkunft > summary { cursor: pointer; font-size: 12px; color: var(--leise); }
.herkunft ul { margin: 8px 0 0; padding-left: 18px; font-size: 12px; color: var(--leise); }
.herkunft code { font-size: 12px; color: var(--schrift); }
.fragefeld {
  display: flex; gap: 10px; align-items: flex-end;
  position: sticky; bottom: 0; z-index: 2;
  box-shadow: 0 -8px 20px -12px rgba(0, 0, 0, .25);
}
.fragefeld textarea {
  flex: 1; padding: 9px 12px; font: inherit; font-size: 13px; color: inherit;
  border: 1px solid var(--rand); border-radius: 8px; background: var(--grund);
  resize: vertical;
}

/* ── Assistenz als schwebendes Fenster ───────────────────────────────
   Ein runder Knopf unten rechts ueber jeder Seite, wie bei Qonto
   (Florian, 31.10.2026). Er oeffnet ein Fenster ueber der Seite, ohne
   Schleier: Die Seite darunter bleibt bedienbar. Auf dem Telefon nimmt
   das Fenster den ganzen Bildschirm. */
.assistenz-knopf {
  position: fixed; right: 20px; bottom: 20px; z-index: 50;
  display: inline-flex; align-items: center; justify-content: center;
  width: 52px; height: 52px; border-radius: 999px;
  background: linear-gradient(#fff, #f4eef1); color: #1a1a1a; text-decoration: none;
  box-shadow: var(--schatten-hoch), 0 0 0 1px rgb(0 0 0 / .06),
              inset 0 1px 0 #fff;
  transition: transform 160ms var(--ease-out);
}
/* Weiss mit pinkem Kopf, wie das App-Symbol (Florian, 01.11.2026). Das
   Weiss bleibt auch im Dunkeln, es ist die Kachel des Symbols. */
/* Beim Zeigen wird nichts abgedunkelt, die Figur tanzt (Florian,
   01.11.2026). */
.assistenz-knopf:hover { text-decoration: none; }
.assistenz-knopf:active { transform: scale(0.95); }
.assistenz-knopf .i-zu { display: none; font-size: 18px; line-height: 1; }
.assistenz-knopf.offen .i-auf { display: none; }
.assistenz-knopf.offen .i-zu { display: inline; }
/* ── Assistenz tanzt ────────────────────────────────────────────────
   Die Figur auf dem Knopf steht still, bis man ihr naeher kommt: Beim
   Zeigen oder Fokussieren und waehrend die Assistenz nachdenkt, wippt
   der Kopf, die Beine kicken, das Auge blinzelt. Immer tanzen soll sie
   nicht, unten rechts waere das auf Dauer Unruhe. */
.tanz { overflow: visible; display: block; }
.tanz-kopf { transform-box: fill-box; transform-origin: 50% 100%; }
.tanz-auge { transform-box: fill-box; transform-origin: center; }
.tanz-haken { transform-box: view-box; transform-origin: 80px 74px; }
.assistenz-knopf:hover .tanz-kopf, .assistenz-knopf:focus-visible .tanz-kopf,
.assistenz-knopf.denkt .tanz-kopf { animation: tanz-kopf 640ms ease-in-out infinite; }
.assistenz-knopf:hover .tanz-haken, .assistenz-knopf:focus-visible .tanz-haken,
.assistenz-knopf.denkt .tanz-haken { animation: tanz-haken 640ms ease-in-out infinite; }
.assistenz-knopf:hover .tanz-auge, .assistenz-knopf:focus-visible .tanz-auge,
.assistenz-knopf.denkt .tanz-auge { animation: tanz-auge 2.4s ease-in-out infinite; }
@keyframes tanz-kopf {
  0%, 100% { transform: translateY(0) rotate(0); }
  25% { transform: translateY(-5px) rotate(-8deg); }
  50% { transform: translateY(1px) rotate(0); }
  75% { transform: translateY(-5px) rotate(8deg); }
}
@keyframes tanz-haken {
  0%, 100% { transform: rotate(0); }
  25% { transform: rotate(16deg) translateX(2px); }
  50% { transform: rotate(0); }
  75% { transform: rotate(-12deg) translateX(-2px); }
}
@keyframes tanz-auge {
  0%, 90%, 100% { transform: scaleY(1); }
  95% { transform: scaleY(.1); }
}
@media (prefers-reduced-motion: reduce) {
  .tanz-kopf, .tanz-haken, .tanz-auge { animation: none !important; }
}

/* Damit der Knopf nicht das Letzte auf der Seite verdeckt. */
body:has(.assistenz-knopf) .buehne-innen { padding-bottom: 72px; }

.assistenz-fenster {
  position: fixed; right: 20px; bottom: 84px; z-index: 55;
  display: flex; flex-direction: column;
  width: min(420px, calc(100vw - 40px));
  height: min(640px, calc(100dvh - 108px));
  background: var(--erhoben-hoch); color: var(--schrift);
  border-radius: 18px; overflow: hidden;
  box-shadow: 0 25px 50px -12px rgb(0 0 0 / .3), 0 0 0 1px var(--rand);
  transform-origin: bottom right;
  transition: opacity 180ms var(--ease-out), transform 180ms var(--ease-out);
}
.assistenz-fenster[hidden] { display: none; }
/* Einblenden aus der Ecke, in der der Knopf sitzt. Schliessen springt,
   wie bei den anderen Fenstern. Beim Weiterklicken auf eine neue Seite
   steht es ohne Einblenden da, sonst wackelt es bei jedem Klick. */
@starting-style {
  .assistenz-fenster:not([hidden]) { opacity: 0; transform: translateY(8px) scale(0.97); }
}
.assistenz-fenster.ohne-einblenden { transition: none; }
@media (prefers-reduced-motion: reduce) {
  @starting-style { .assistenz-fenster:not([hidden]) { transform: none; } }
}
.assistenz-kopf {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; padding: 12px 12px 10px 20px;
  box-shadow: inset 0 -1px 0 var(--flaeche-2);
}
.assistenz-kopf b { font-size: 14px; font-weight: 600; }
.assistenz-kopf-knoepfe { display: inline-flex; gap: 2px; }
.assistenz-verlauf {
  flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain;
  display: flex; flex-direction: column; gap: 10px; padding: 16px;
}
.assistenz-verlauf .blase.frage { max-width: 85%; padding: 8px 14px; font-size: 13px; }
.assistenz-verlauf .blase.antwort { padding: 12px 16px; font-size: 13px; overflow-x: auto; }
.assistenz-verlauf .hinweis { margin: 0; }
.assistenz-leer { margin: auto 0; text-align: center; color: var(--leise); font-size: 13px; line-height: 1.5; padding: 0 12px; }
.assistenz-leer[hidden] { display: none; }
.assistenz-eingabe {
  display: flex; gap: 8px; align-items: flex-end; padding: 12px;
  box-shadow: inset 0 1px 0 var(--flaeche-2);
}
.assistenz-eingabe textarea {
  flex: 1; padding: 9px 12px; font: inherit; font-size: 13px; color: inherit;
  border: 1px solid var(--rand); border-radius: 10px; background: var(--grund);
  resize: none; max-height: 120px;
}
/* Der Hinweis im leeren Feld bleibt eine Zeile. Auf dem Telefon brach
   er sonst um und das einzeilige Feld schnitt ihn ab. */
.assistenz-eingabe textarea::placeholder {
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.assistenz-eingabe .knopf-haupt { padding: 8px 12px; display: inline-flex; }
@media (max-width: 600px) {
  .assistenz-fenster {
    inset: 0; width: auto; height: auto; border-radius: 0;
  }
  .assistenz-knopf.offen { display: none; }
  /* Unter 16 Pixeln zoomt iOS beim Tippen ins Feld. */
  .assistenz-eingabe textarea { font-size: 16px; }
}

/* ── Lange Dateinamen ────────────────────────────────────────────────
   Hochgeladene Dateien heissen oft lang und unterscheiden sich erst am
   Ende, im Datum. Der Server kuerzt deshalb in der Mitte, der volle Name
   steht im title (Prüfung, 30.10.2026). */
.kartenkopf > b { min-width: 0; overflow-wrap: anywhere; }

/* Diagramme wachsen auf breiten Bildschirmen nicht ohne Ende: Ab 1280
   Pixeln wuerde aus 10 Pixel Schrift sonst 24. Nur die, die mit der
   Seite mitwachsen (width="100%"). Das Stundenraster ist ein Jahr breit
   und schiebt sich seitlich; gedeckelt schrumpfte es auf einen Strich
   (Florian, 30.10.2026). */
svg.grafik[width="100%"] { max-width: 1280px; margin-inline: auto; }

/* Ein langer Projektname darf umbrechen. Mit nowrap lief die Rentabilität
   auf 13 Zoll so breit, dass Marge und Marge % erst nach dem Schieben zu
   sehen waren (Prüfung, 30.10.2026). */
td.umbruch { min-width: 10em; white-space: normal; }
span.umbruch { white-space: normal; }

/* ── Weniger Bewegung ────────────────────────────────────────────────
   Wenn das System darum bittet: Farbe und Deckkraft wechseln weiter
   sanft, alles, was sich bewegt oder dreht, springt. Wie im CMS der
   Einschlaf-App (Florian, 30.10.2026). Der Wartekreis dreht weiter,
   er ist eine Auskunft und keine Zier. */
@media (prefers-reduced-motion: reduce) {
  *, ::before, ::after {
    transition-property: color, background-color, border-color, opacity,
                         box-shadow, outline-color !important;
  }
  /* Ausgenommen: der Wartekreis (eine Auskunft) und das Aufleuchten
     einer angesprungenen Zeile (nur Farbe). */
  *:not(.wartekreis, .hervorgehoben, .hervorgehoben > td) { animation: none !important; }
}

/* Der Inhalt steht mittig mit hoechstens 1200 Pixeln Breite, wie im
   Podcast-Studio. Auf breiten Bildschirmen liefen Tabellen sonst so weit,
   dass das Auge in der Zeile verrutscht (Florian, 30.10.2026). */
.buehne-innen { max-width: 1200px; margin-inline: auto; }

/* ── Prüfung mit allen Skills (31.10.2026) ───────────────────────── */

/* Hover nur mit echter Maus: auf Touch blieb die Farbe nach dem Tippen
   haengen. Die Hausfarbe wird beim Zeigen einen Hauch heller, als
   Hintergrund statt als Filter; das ist billiger und bekommt keine
   eigene Ebene. */
@media (hover: hover) and (pointer: fine) {
  :is(.knopf, .knopf-haupt):not(.symbolisch):not(:disabled):hover {
    background-color: color-mix(in srgb, var(--akzent) 88%, #fff);
  }
}

/* Fokus mit der Tastatur erscheint sofort, nicht eingeblendet: Wer mit
   Tab durchgeht, wartet sonst bei jedem Schritt. */
:is(a, button, summary, [tabindex], input, select, textarea):focus-visible {
  transition-duration: 0s;
}
.probe.stufe { background: color-mix(in srgb, var(--akzent) calc(var(--stufe, 1) * 100%), var(--stufen-ende)); }

/* Der Schleier hinter einem Fenster dunkelt ab, auch im Dunkeln. */
dialog.fenster::backdrop { background: var(--schleier); }

/* Was ueber einer Karte schwebt, liegt hoeher: im Dunkeln hellere
   Flaeche, tieferer Schatten. Aktive Reiter mit dem gewoehnlichen
   Schatten, der im Dunkeln nicht hell schimmert. */
dialog.fenster, .stempelliste, .kalenderblatt, .diagramm-hinweis,
.mitteilungen .meldung:not(.success):not(.error):not(.info) {
  background-color: var(--erhoben-hoch);
}
dialog.fenster, .mitteilungen .meldung, .stempelliste, .kalenderblatt {
  box-shadow: var(--schatten-hoch);
}
.reiter.hier, .pille.aktiv { box-shadow: var(--schatten); }

/* Fokus als Flaeche, an jedem Knopf. Mit !important, weil sonst jede
   spaetere Regel mit eigenem Hintergrund den Fokus verschluckte; volle
   Knoepfe werden tief rot statt fast unsichtbar dunkler. */
:is(a, button, summary, [tabindex]):focus-visible {
  outline: none; background-color: var(--akzent-flaeche) !important; border-radius: 8px;
}
:is(.knopf, .knopf-haupt):not(.symbolisch):focus-visible {
  background-color: var(--akzent-tief) !important; color: #fff;
}
.ankreuzliste label:has(input:focus-visible) { box-shadow: none; background: var(--akzent-flaeche); }
.schalter-knopf input:focus-visible + span { outline: none; box-shadow: 0 0 0 3px var(--akzent-flaeche); }
.abrufknopf:focus-visible { outline: none; color: var(--akzent-schrift); }

/* Gesperrt heisst "geht nicht", Warten heisst "laeuft". Nur der Knopf,
   der wirklich wartet, traegt den Wartezeiger. */
.knopf[data-urtext], .knopf-haupt[data-urtext] { opacity: .7; cursor: progress; }

/* Leere Listen als bewusster Zustand: mittig, mit Luft, ohne Lineal. */
tbody tr > td[colspan].leise:only-child { padding: 28px 0; text-align: center; }
@media (hover: hover) and (pointer: fine) {
  tbody tr:has(> td[colspan].leise:only-child):hover > td { background: none; }
}

/* Ziffern stehen untereinander, auch ausserhalb von Tabellenzellen. */
.raster, .heute-eintrag, .zeitraumwahl .bereich, .kachel .rand { font-variant-numeric: tabular-nums; }

/* Felder einheitlich: 13 Pixel Schrift neben 14 Pixel Text, Beschriftung
   darueber 12 Pixel. In Tabellenzeilen knapper, damit Felder und
   Auswahllisten einer Zeile gleich hoch stehen. Auf Touch 16 Pixel,
   sonst zoomt das Telefon beim Tippen hinein. */
:is(.zeitraumwahl, .formularfelder, .zeilenbearbeitung) :is(input, select, textarea),
.suchfeld, .zeilenwahl { font-size: 13px; }
:is(.zeitraumwahl, .formularfelder, .zeilenbearbeitung) .feldname { font-size: 12px; font-weight: 520; }
input.zeilenwahl { padding: 4px 9px; }
form input[type="color"] { border: 0; background: var(--flaeche-2); border-radius: var(--rundung-klein); }
@media (pointer: coarse) {
  input, select, textarea { font-size: 16px !important; }
}

/* Die Stempelliste klappt nach unten auf; in der letzten Zeile schnitt
   die Karte sie ab. */
.karte:has(details.stempel) { overflow: visible; }

/* Freitext ohne Leerzeichen (IBAN, Verwendungszweck, E-Mail) bricht um,
   statt die Tabelle ueber die Karte hinaus zu schieben. */
td.freitext { overflow-wrap: anywhere; min-width: 10em; }

/* Lange Namen im Abwesenheitsraster werden gekuerzt, statt ueber die
   Tage zu laufen; der volle Name steht im title. */
.raster .namensspalte > .name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ── Anmelden ────────────────────────────────────────────────────────
   Wie die Anmeldung im Podcast-Studio: eine Karte mittig, Felder mit
   Beschriftung darueber, 40 Pixel hoch (Prüfung, 31.10.2026). */
.anmelden-seite { min-height: 100vh; display: grid; place-items: center; padding: 16px; }
.anmelden-karte {
  width: min(360px, 100%); background: var(--erhoben); border-radius: 18px;
  box-shadow: var(--schatten-hoch); padding: 28px;
}
.anmelden-symbol { display: block; width: 56px; height: 56px; margin-bottom: 14px; }
.anmelden-karte h1 { font-size: 20px; margin: 0; }
.anmelden-karte > .leise { margin: 2px 0 22px; font-size: 13px; }
.anmelden-karte .hinweis { margin-bottom: 16px; }
.anmelde-feld { display: block; margin-bottom: 12px; }
.anmelde-feld span { display: block; font-size: 12.5px; color: var(--leise); margin-bottom: 5px; }
.anmelde-feld input { width: 100%; height: 40px; padding: 0 12px; font-size: 14px; }
.bleiben { display: flex; align-items: center; gap: 8px; margin: 4px 0 18px; font-size: 13px; cursor: pointer; }
.bleiben input { margin: 0; width: 16px; height: 16px; accent-color: var(--akzent); }
.anmelden-knopf { width: 100%; height: 40px; justify-content: center; }


/* ── Nach BoardUI (Florian, 03.11.2026) ────────────────────────────── */

/* Fuellstand: wie viel vom Urlaub genommen ist, in der Farbe der Ampel. */
.meter {
  display: block; width: 100%; min-width: 80px; max-width: 160px; height: 8px;
  border-radius: 999px; background: var(--flaeche-2); overflow: hidden;
}
.meter > i {
  display: block; height: 100%; border-radius: 999px; background: var(--leise);
  transition: width 600ms var(--ease-out);
}
.meter.ampel-gut > i { background: var(--gut); }
.meter.ampel-knapp > i { background: var(--gold); }
.meter.ampel-warn > i { background: var(--warn); }

/* Zaehler in der Seitenleiste: offene Urlaubsantraege. Eingeklappt
   bleibt ein Punkt am Zeichen. */
.weg .zaehler {
  margin-left: auto; min-width: 20px; height: 18px; padding: 0 6px;
  border-radius: 999px; background: var(--akzent); color: #fff;
  font-size: 11px; font-weight: 650; line-height: 18px; text-align: center;
  font-variant-numeric: tabular-nums;
}
.weg { position: relative; }
.weg .zaehler-punkt {
  display: none; position: absolute; top: 5px; left: 24px;
  width: 8px; height: 8px; border-radius: 50%; background: var(--akzent);
  box-shadow: 0 0 0 2px var(--erhoben);
}
html.leiste-schmal .weg .zaehler-punkt { display: block; }
@media (max-width: 1000px) {
  .weg .zaehler-punkt { display: block; }
  html.leiste-breit .weg .zaehler-punkt { display: none; }
}

/* Pfeile neben der Zeitraumwahl: ein Zeitraum zurueck oder vor. */
.zeitraum-blaettern { display: inline-flex; align-items: center; gap: 4px; }
.zeitraum-pfeil {
  display: inline-grid; place-items: center; width: 30px; height: 32px;
  border-radius: var(--rundung-klein); color: var(--leise);
  font-size: 18px; line-height: 1; text-decoration: none;
}
a.zeitraum-pfeil:hover { background: var(--flaeche-2); color: var(--schrift); text-decoration: none; }
.zeitraum-pfeil.aus { opacity: 0.3; }

/* Jahresraster: ein Kaestchen je Tag, wie das Beitragsraster bei GitHub. */
.jahresraster text { font-size: 10px; fill: var(--leise); }
.jahresraster .tag, .probe.tag { fill: var(--flaeche-2); background: var(--flaeche-2); }
.jahresraster .stufe-1, .probe.tag.stufe-1 {
  fill: color-mix(in srgb, var(--akzent) 25%, var(--erhoben));
  background: color-mix(in srgb, var(--akzent) 25%, var(--erhoben)); }
.jahresraster .stufe-2, .probe.tag.stufe-2 {
  fill: color-mix(in srgb, var(--akzent) 50%, var(--erhoben));
  background: color-mix(in srgb, var(--akzent) 50%, var(--erhoben)); }
.jahresraster .stufe-3, .probe.tag.stufe-3 {
  fill: color-mix(in srgb, var(--akzent) 78%, var(--erhoben));
  background: color-mix(in srgb, var(--akzent) 78%, var(--erhoben)); }
.jahresraster .stufe-4, .probe.tag.stufe-4 { fill: var(--akzent-tief); background: var(--akzent-tief); }
.jahresraster .urlaub, .probe.tag.urlaub { fill: var(--gold-hell); background: var(--gold-hell); }
.jahresraster .krank, .probe.tag.krank { fill: var(--warn-flaeche); background: var(--warn-flaeche); }
.jahresraster .zukunft { fill: transparent; stroke: var(--flaeche-2); stroke-width: 1; }
.probe.tag { width: 11px; height: 11px; border-radius: 3px; }
