:root {
  color-scheme: light dark;
  /* Formen- und Schrift-Variablen (2026-08-03, Vorbereitung
     Design-Umschalter): Vorgabewerte exakt wie die bisher harten
     Werte -- ohne gewaehltes Design aendert sich NICHTS. Ein Design
     unter designs/ ueberschreibt sie. Die zwei Radius-Familien sind
     die aus OBERFLAECHE.md ("Gewachsen"): Flaechen und Pillen.
     Sonderfaelle (50% Kreise, 6/8px Kleinakzente) bleiben bewusst
     hart -- sie gehoeren keiner der beiden Familien an. */
  --radius-flaeche: 10px;
  --radius-pille: 999px;
  /* Dritter, kleiner Radius (Marken, Cover-Miniaturen, verknuepfte
     Treffer) und die zwei Rahmenbreiten -- seit 2026-08-04 Token,
     damit Designs sie mitpraegen koennen (Notebook: eckig und 2px).
     .marke hatte vorher 6px, jetzt einheitlich 8px -- die einzige
     sichtbare Angleichung. 50%-Kreise bleiben bewusst hart. */
  --radius-klein: 8px;
  --rahmen-fein: 1px;
  --rahmen-stark: 2px;
  --schrift-fliess: -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
  --schrift-titel: var(--schrift-fliess);

  /* Schriftgrad-Skala (2026-08-04): vorher 20 verschiedene Werte an
     33 Stellen -- jetzt 8 Stufen. Zuordnung beim Einfuehren:
       klein 0.8      <- 0.75 / 0.78 / 0.8
       neben 0.85     <- 0.85 / 0.88
       kompakt 0.95   <- 0.9 / 0.92 / 0.95
       basis 1        <- 1 / 1.02 / 16px (Eingabefelder: 1rem = 16px,
                         die iOS-Zoom-Regel aus OBERFLAECHE.md haengt
                         an dieser Stufe -- nie darunter!)
       betont 1.15    <- 1.1 / 1.15
       zwischentitel 1.35 <- 1.3 / 1.35 / 1.4
       gross 1.7      <- 1.7
       anzeige 2.2    <- 2.2 (grosse Zahlen, z.B. BPM)
     Bewusst NICHT auf der Skala: die Avatar-Initialen (0.6/1.6rem,
     an die Kreisgroessen 28/96px gekoppelt). */
  --schriftgrad-klein: 0.8rem;
  --schriftgrad-neben: 0.85rem;
  --schriftgrad-kompakt: 0.95rem;
  --schriftgrad-basis: 1rem;
  --schriftgrad-betont: 1.15rem;
  --schriftgrad-zwischentitel: 1.35rem;
  --schriftgrad-gross: 1.7rem;
  --schriftgrad-anzeige: 2.2rem;

  /* Abstands-Skala (gap und einfache paddings; zusammengesetzte
     paddings mit env()/Mehrachsen folgen in einem eigenen Schritt):
       0.15 / 0.3 / 0.5 / 0.75 / 1 / 1.5 / 2 rem.
     Zuordnung: 0.1->0.15, 0.25/0.35->0.3, 0.4->0.5 -- maximale
     sichtbare Verschiebung 1.6px, dafuer ein durchgehender Rhythmus. */
  --abstand-1: 0.15rem;
  --abstand-2: 0.3rem;
  --abstand-3: 0.5rem;
  --abstand-4: 0.75rem;
  --abstand-5: 1rem;
  --abstand-6: 1.5rem;
  --abstand-7: 2rem;
  --bg: #ffffff;
  --fg: #111111;
  /* YouTube-Rot fuer den externen Link (Auftrag "YouTube entdoppeln"):
     nur Rahmen + Symbol, NIE die Flaeche fuellen -- weisser Text auf
     #FF0000 erreicht nur 4,00:1 und verfehlt 4,5:1 (WCAG-Text-
     Schwelle). Als grafisches Element (Rahmen/Symbol, 3:1-Schwelle)
     traegt derselbe Ton in beiden Farbschemata: 4,00:1 gegen --bg
     (#ffffff), 4,69:1 gegen die dunkle Seitenfarbe (#121212) --
     deshalb EIN Wert statt eines hell/dunkel-Paars. */
  --youtube-rot: #ff0000;
  --rand: #ddd;
  /* Nebentext: bis 2026-08-03 #888 (3,54:1 gegen --bg, APCA Lc 63 --
     nach BEIDEN Verfahren zu schwach, war als Altlast akzeptiert).
     Jetzt 4,54:1 / Lc 72 gegen --bg -- erreicht WCAG AA, bleibt
     sichtbar gedaempft. Dunkel unveraendert #999 (6,58:1). Gefunden
     von pruefe_kontraste.py, das seither beide Verfahren prueft. */
  --gedaempft: #767676;
  --kachel-bg: #eef0f2;
  --kachel-aktiv-bg: #2b6cb0;
  --kachel-aktiv-fg: #ffffff;
  --marke-bg: #eef2f7;
  /* Eigener Ton fuer die Bereiche-Leiste (Punkt 6, Nachtrag): deutlich
     von --bg UND von --kachel-bg abgesetzt (1,52 bzw. 1,33 Kontrast),
     damit sie als eigene Zone erkennbar bleibt und die Kacheln darin
     nicht mit ihr verschmelzen. Blauton passend zur bestehenden
     --kachel-aktiv-bg-Familie, keine neue Farbe im System. Text auf
     diesem Ton (die "Bereiche"-Beschriftung, --fg) liegt bei 12,4:1 --
     weit ueber WCAG AA. */
  --bereichsleiste-bg: #c3d3e8;

  /* Vier gedaempfte Akzenttoene, einer pro Filterzeile -- nur auf der
     AKTIVEN Kachel sichtbar. Gleiche Saettigung/Helligkeit ueber alle
     vier, damit es nach einer Familie aussieht, nicht nach Farbkasten.
     Das eigentliche "wozu gehoert diese Kachel" beantwortet der
     Textlabel ueber der Zeile -- Farbe ist hier nur Zugabe, kein
     Signal, auf das man sich verlassen muesste (Farbsehschwaeche). */
  --akzent-familie-bg: #2b6cb0;
  --akzent-familie-fg: #ffffff;
  --akzent-stil-bg: #2f855a;
  --akzent-stil-fg: #ffffff;
  --akzent-status-bg: #92400e;
  --akzent-status-fg: #ffffff;
  --akzent-art-bg: #6b46c1;
  --akzent-art-fg: #ffffff;

  /* Signature-Herz: Kontrast 6,22:1 gegen --bg -- weit ueber WCAG AA.
     Form (Herz-Glyphe) ist das eigentliche Signal, nicht die Farbe --
     ein Screenreader liest zusaetzlich das aria-label. */
  --signatur: #c1121f;
  /* Vordergrund fuer die Signatur-Kachel-Flaeche (fuenfte Filterzeile,
     Startseite): 6,22:1 gegen --signatur als Hintergrund -- eigener
     Kontrastfall, auch wenn die Zahl zufaellig dieselbe ist wie beim
     Herz-Kontrast oben (Text auf Seitenhintergrund vs. Text auf
     Signatur-Flaeche, nur numerisch identisch wegen Symmetrie). */
  --akzent-signatur-fg: #ffffff;

  /* Diagramm-Palette (PLAN-auswertungen.md, Fundament-Entscheidung 3):
     sechs Verweise auf LAENGST bestehende, je Design schon definierte
     Farben -- keine einzige neue Farbe im System. Dadurch folgen alle
     sieben Designs UND jedes Eigenbau-Design automatisch (die Werte
     werden erst dort aufgeloest, wo --diagramm-N tatsaechlich benutzt
     wird, nicht hier an der Definitionsstelle) -- kein zweiter Ort,
     der bei einer neuen Design-Datei mitgepflegt werden muesste.
     Kontrast unkritisch: Diagrammflaechen tragen nie Text
     (Entscheidung 4), nur eine 1px --rand-Kontur gegen Nachbarflaechen
     aehnlicher Toene -- die eigentlichen Zahlen stehen als Fliesstext
     in der Legende daneben, dort gelten die laengst gemessenen
     fg/bg-Paare unveraendert. */
  --diagramm-1: var(--akzent-familie-bg);
  --diagramm-2: var(--akzent-stil-bg);
  --diagramm-3: var(--akzent-status-bg);
  --diagramm-4: var(--akzent-art-bg);
  --diagramm-5: var(--signatur);
  --diagramm-6: var(--kachel-aktiv-bg);

  /* Sterne-Bewertung (PLAN-sterne.md): 4,64:1 gegen --bg -- ueber
     WCAG AA. Eigene Farbe statt Wiederverwendung von --signatur/--
     akzent-*, weil eine Bewertung ein anderes Konzept als Signature-
     Figur oder Filter-Achse ist -- keine der bestehenden Farben passt
     semantisch, und eine neue ist hier billiger als eine
     Verwechslungsgefahr. */
  --stern-gefuellt: #9c6b0a;

  /* Bearbeiten-Modus (Auftrag "Sieben Punkte", Punkt 7): eigener
     Seitenhintergrund fuer ALLE Bearbeiten-/Anlegen-Formulare, damit
     der Modus schon am Hintergrund erkennbar ist, nicht erst an der
     Ueberschrift. Gleiche Blaufamilie wie --kachel-aktiv-bg/
     --bereichsleiste-bg (Punkt 6, Nachtrag) -- keine neue Farbe im
     System, wie dort vorgemacht. Bewusst ein ANDERER Ton als
     --bereichsleiste-bg (nicht derselbe Wert): die feste Leiste am
     unteren Rand bleibt so als eigene, unveraenderte Zone erkennbar,
     auch wenn eine Bearbeiten-Seite den Rest der Flaeche einfaerbt --
     beide Blautoene wuerden sonst ineinanderlaufen.
     Nachgemessen (nicht geschaetzt), Kontrast hell:
       vs --bg 1,26 (deutlich wahrnehmbarer Farbstich, kein neuer Ton)
       vs --fg (Fliesstext) 14,99:1 -- weit ueber WCAG AA
       vs --gedaempft (Nebentext) 3,60:1 (seit --gedaempft am
         2026-08-03 auf #767676 nachgedunkelt wurde; vorher 2,81:1) --
         weiterhin unter AA fuer normalen Text, offengelegt akzeptiert:
         Nebentext bleibt lesbar, keine essenzielle Information haengt
         allein daran. pruefe_kontraste.py wacht ueber die 2,5-Grenze.
       vs --rand (Eingabefeld-Rahmen) 1,08:1 -- Eingabefelder haben
         zusaetzlich einen eigenen weissen Fuellhintergrund (siehe
         .bearbeiten-formular input weiter unten), der sie als helle
         Flaeche vom getoenten Seitenhintergrund abhebt; der Rahmen
         selbst war schon vorher kaum sichtbar (1,36:1 gegen --bg). */
  --bearbeiten-bg: #dbe6f5;

  /* Loeschen-Modus (Auftrag "Loeschen -- sachlogisch stringent"):
     eigener, warmer Ton statt der blauen Bearbeiten-Familie -- die
     Bestaetigungsseite handelt eine unwiderrufliche Handlung ab,
     "es sieht aus wie Bearbeiten" waere die falsche Auskunft. Gleiche
     Bauart wie --bearbeiten-bg (schwacher Farbstich, kein Warnrot):
     nachgemessen, hell:
       vs --bg 1,30 (wahrnehmbarer, aber kein grelles Rot)
       vs --fg (Ueberschrift/Name) 14,52:1 -- weit ueber WCAG AA
       vs --gedaempft (Nebentext, z.B. "eintrag-neben") 3,49:1 (seit
         #767676 am 2026-08-03; vorher 2,73:1) -- gleiche
         Groessenordnung wie bei --bearbeiten-bg (3,60:1) */
  --loeschen-bg: #f5dcdc;

  /* Endgueltig-loeschen-Knopf hell: weisser Text auf #cc0000, 5,89:1
     -- weit ueber WCAG AA. Dunkler Ton bewusst NICHT gefuellt fuer
     .loeschen-knopf (siehe dort), nur fuer den tatsaechlich
     loeschenden Knopf auf der Bestaetigungsseite. */
  --loeschen-knopf-bg: #cc0000;
  --loeschen-knopf-fg: #ffffff;
  /* Marken-Gold fuer das "vault" der Wortmarke (D1b,
     IDEEN-dancevault.md). ZWEI Werte, weil ein einziger es nicht
     tut: das Gold der App-Kachel (#c9a05a) steht dort auf fast
     Schwarz und ist dafuer gebaut -- auf hellem Grund faellt es auf
     2,0:1 und waere unlesbar. Der Hellwert ist derselbe Ton,
     abgedunkelt bis er traegt. Gemessen gegen --bg:
       hell  #96702f auf #ffffff = 4,51:1  (ueber AA 4,5)
       dunkel #c9a05a auf #121212 = 7,72:1
     Beide Paare stehen in pruefe_kontraste.py und werden bei jeder
     Farbaenderung nachgerechnet. */
  --marke-gold: #96702f;

  /* Auftrag "Feste Kopfbereiche absetzen und begrenzen": .kopf
     (Listenseiten, sticky oben) hatte bislang exakt --bg als
     Hintergrund -- beim Scrollen wanderte Inhalt unsichtbar darunter
     durch, der Kopf wirkte wie mitscrollend statt fest. Gleiche
     Blaufamilie wie --kachel-aktiv-bg/--bereichsleiste-bg/
     --bearbeiten-bg, aber bewusst ein EIGENER Ton (weder deren Wert),
     da .kopf eine eigene feste Zone ist -- dieselbe Begruendung wie
     bei --bearbeiten-bg vs --bereichsleiste-bg oben. Auch fuer
     .kopfzeile (Detailseiten) verwendet, damit beide feste Kopf-Zonen
     wie eine Sache aussehen.
     Nachgemessen (nicht geschaetzt), Kontrast hell:
       vs --bg 1,31 (deutlich wahrnehmbarer Farbstich)
       vs --fg (Ueberschrift) 14,38:1 -- weit ueber WCAG AA
       vs --gedaempft (filter-titel-Beschriftungen) 3,46:1 (seit
         #767676 am 2026-08-03; vorher 2,70:1) -- weiterhin unter AA,
         offengelegt akzeptiert, gleiches Muster wie bei
         --bearbeiten-bg oben.
       vs --bg als Komponente (Suchfeld-Fuellung bleibt --bg) 1,31:1 --
         Suchfeld bleibt als helle Flaeche erkennbar.
       vs --kachel-bg als Komponente (inaktive Kachel-Fuellung) 1,15:1
         -- in derselben Groessenordnung wie der bereits akzeptierte
         Ausgangswert --bereichsleiste-bg vs --kachel-bg (1,33:1),
         keine neue Schwaeche.
       vs --kachel-aktiv-bg (Suchen-Knopf-Fuellung, = Akzent "familie")
         4,13:1 -- Knopf bleibt klar als eigene Flaeche erkennbar.
     Die vier Filterkachel-Akzente als Komponente gegen den neuen
     Untergrund (WCAG 1.4.11, Schwelle 3:1 fuer Nicht-Text-Elemente --
     seinerzeit einzeln gegen den ALTEN Untergrund --bg gerechnet,
     hier nachgerechnet): familie 4,13:1, stil 3,46:1 (der knappste),
     status 5,40:1, art 4,89:1 -- alle vier bleiben ueber 3:1, keiner
     faellt unter AA. */
  --kopf-bg: #d6e2f0;

  /* Auftrag "Titel klebt unter der Navigationszeile": Kleberand des
     Titels = die tatsaechliche Hoehe von .kopfzeile, rein rechnerisch
     aus deren eigenen Werten abgeleitet (kein Messwert per JS noetig):
     deren Padding oben (max(safe-area-inset-top, 0.75rem)) + die 44px
     Mindesthoehe von .zurueck/.bearbeiten-knopf (Apples Mindest-
     Tippbereich, beide Kinder der Zeile) + Padding unten (0.5rem) +
     1px Rahmenlinie. Dadurch klebt der Titel schon rein per CSS an
     der richtigen Stelle -- ganz ohne JavaScript (titel_klebt.js
     ergaenzt nur das Schrumpfen beim Scrollen, nie das Kleben selbst). */
  --kopfzeile-hoehe: calc(max(env(safe-area-inset-top, 0px), 0.75rem) + 44px + 0.5rem + 1px);

  /* Auftrag "Titelfeld je Bereich einfaerben": neun Toene, einer pro
     Bereich aus der Bereiche-Leiste (rahmen.html), NICHT zehn -- Track
     und Playlist teilen sich den Bereich "Musik". Bewusst gleiche
     Helligkeit/Saettigung ueber alle neun (rechnerisch auf dieselbe
     rel. Leuchtdichte ~0,35 gebracht) -- unterscheidbar wird die Reihe
     NUR ueber den Farbton, in exakt 40°-Schritten rund um den
     Farbkreis (0/40/80/.../320°, keiner ausgelassen oder gerundet).
     Waere die Helligkeit stattdessen zufaellig verteilt, waere das
     selbst schon ein zweites, unbeabsichtigtes Signal neben dem
     Farbton. Textfarbe bleibt ueberall die normale --fg (kein eigenes
     fg je Bereich noetig -- 9 Werte statt 18). Farbe ist dabei nicht
     das einzige Signal: der Titeltext selbst und "← Zur Liste" in der
     Navigationszeile darueber nennen den Bereich ohnehin schon.
     Kontrast gegen --fg (Text), nachgemessen, nicht geschaetzt --
     alle neun weit ueber WCAG AA 4,5:1:
       moves 7,15 · technik 7,19 · musik 7,22 · notizen 7,19
       · choreografien 7,15 · personen 7,24 · ressourcen 7,20
       · uebungseinheiten 7,25 · quellen 7,15
     Kontrast gegen --kopf-bg (die Zone direkt darueber, .kopfzeile) --
     alle neun bei ca. 2,0:1, klar erkennbar als eigenes Feld, deutlich
     ueber dem in diesem Projekt bereits akzeptierten Mindestabstand
     fuer eigene Zonen (--bearbeiten-bg vs --bereichsleiste-bg 1,3:1). */
  --titel-moves-bg: #5ba8cf;
  --titel-personen-bg: #c7993c;
  --titel-quellen-bg: #34b389;
  --titel-uebungseinheiten-bg: #35b835;
  --titel-technik-bg: #9999e1;
  --titel-ressourcen-bg: #84ad32;
  --titel-notizen-bg: #db83bd;
  --titel-musik-bg: #c28bdd;
  --titel-choreografien-bg: #dd8888;

  /* Auftrag "Bereichsfarben auf Kopf/Kopfzeile/Bereichsleiste
     ausweiten": dieselben neun Farbtoene wie --titel-*-bg (exakt
     dieselben Farbtoene/Winkel), aber ABGEBLASST statt kraeftig --
     dieselbe Saettigung/Helligkeit, die --kopf-bg/--bereichsleiste-bg/
     --bearbeiten-bg schon fuer die neutrale Blau-Variante verwenden
     (HSL S=46%, L=89% -- aus #d6e2f0 zurueckgerechnet), nur um den
     jeweiligen Bereichs-Hue gedreht. Getrennte Variablen von
     --titel-*-bg (nicht derselbe Wert nur heller), weil .kopf/
     .kopfzeile UND .titel-klebt aufeinandertreffen (Titelfeld sitzt
     direkt unter .kopfzeile) -- ohne sichtbaren Helligkeitssprung
     waeren die beiden Zonen nicht mehr auseinanderzuhalten. Kontrast
     Feld-gegen-Feld (Beispiel moves): 2,08:1 hell / 2,1:1 dunkel --
     deutlich unterscheidbar, beide klar in derselben Farbfamilie.
     Kontrast gegen --fg (Text/Ueberschrift), nachgemessen: alle neun
     11,2–16,0:1 hell, weit ueber WCAG AA. Gegen --gedaempft (Filter-
     Beschriftungen, nur auf der Moves-Listenseite relevant): 3,19–
     3,86:1 hell (seit #767676 am 2026-08-03; vorher 2,49–3,01) -- in
     derselben Groessenordnung wie der dokumentierte, akzeptierte
     Ausgangswert von --kopf-bg (3,46:1), keine neue Schwaeche. Die vier Filterkachel-Akzente (nur Moves,
     Schwelle 3:1) bleiben alle darueber: familie 4,27 · stil 3,58 ·
     status 5,59 · art 5,06. */
  --bereich-moves-bg: #d6e7f0;
  --bereich-personen-bg: #f0e7d6;
  --bereich-quellen-bg: #d6f0e7;
  --bereich-uebungseinheiten-bg: #d6f0d6;
  --bereich-technik-bg: #d6d6f0;
  --bereich-ressourcen-bg: #e7f0d6;
  --bereich-notizen-bg: #f0d6e7;
  --bereich-musik-bg: #e7d6f0;
  --bereich-choreografien-bg: #f0d6d6;
}
@media (prefers-color-scheme: dark) {
  :root {
    --bg: #121212;
    --fg: #eeeeee;
    --rand: #333333;
    --gedaempft: #999;
    --kachel-bg: #232323;
    --kachel-aktiv-bg: #4a90d9;
    --kachel-aktiv-fg: #08121c;
    --marke-bg: #1e2a35;
    /* Kontrast dunkel: vs bg 1,55, vs kachel-bg 1,30, vs fg 10,4:1. */
    --bereichsleiste-bg: #26374d;

    --akzent-familie-bg: #4a90d9;
    --akzent-familie-fg: #08121c;
    --akzent-stil-bg: #48bb78;
    --akzent-stil-fg: #07170f;
    --akzent-status-bg: #d69e4e;
    --akzent-status-fg: #1a1206;
    --akzent-art-bg: #9f7aea;
    --akzent-art-fg: #150b26;

    /* Kontrast dunkel: 6,75:1 gegen --bg. */
    --signatur: #ff6b6b;
    /* Kontrast dunkel: 6,75:1 gegen --signatur als Hintergrund. */
    --akzent-signatur-fg: #121212;

    /* Kontrast dunkel: 9,57:1 gegen --bg. */
    --stern-gefuellt: #e0b34d;

    /* Bearbeiten-Modus dunkel -- nachgemessen:
         vs --bg 1,32
         vs --fg (Fliesstext) 12,25:1
         vs --gedaempft (Nebentext) 4,99:1 -- hier sogar UEBER dem
           bisherigen Wert gegen --bg (6,58:1 waere staerker, aber
           4,99:1 liegt noch ueber WCAG AA 4,5:1 fuer normalen Text,
           anders als im Hellmodus keine Verschlechterung unter AA)
         vs --rand 1,13:1 (Eingabefelder haben wieder ihren eigenen
           Fuellhintergrund, siehe oben). */
    --bearbeiten-bg: #1c2c3d;

    /* Loeschen-Modus dunkel -- nachgemessen:
         vs --bg 1,15
         vs --fg (Ueberschrift/Name) 14,09:1
         vs --gedaempft (Nebentext) 5,74:1 -- ueber WCAG AA. */
    --loeschen-bg: #331818;

    /* Endgueltig-loeschen-Knopf dunkel: seit 2026-08-03 wieder
       DERSELBE Knopf wie hell (#cc0000 mit weissem Text), erste
       Anwendung der APCA-Erweiterung der Kontrastregel
       (OBERFLAECHE.md). Der fruehere Umweg (#e53e3e mit dunklem Text)
       stammte allein aus der WCAG-2-Flaechenschwelle: Flaeche #cc0000
       gegen --loeschen-bg/--kachel-bg dunkel 2,78/2,67:1, unter 3:1.
       Nachgemessen mit beiden Verfahren:
         Text weiss auf #cc0000: WCAG 5,89:1 UND APCA Lc 82 --
           besteht beide, keine Ausnahme noetig.
         Flaeche #cc0000 vs --loeschen-bg/--kachel-bg dunkel:
           WCAG 2,78/2,67:1 (unter 3:1) -- APCA Lc 23,0/22,6, ueber
           der APCA-Nicht-Text-Schwelle (Lc 15). Widerspruch der
           Verfahren, APCA entscheidet; der Knopf traegt zudem einen
           Textlabel, die Flaeche ist nicht das einzige Merkmal.
         Zum Vergleich der alte Umweg: #111111 auf #e53e3e war nach
           APCA nur Lc 36 -- die alte Formel hatte die perzeptiv klar
           schlechtere Variante erzwungen.
       Gleiches Rot als Glocke-Ungelesen-Punkt (PLAN-glocke.md G1)
         gegen --bereichsleiste-bg dunkel: WCAG 2,05:1 (unter 3:1),
         APCA Lc 18 (ueber 15) -- dieselbe Ausnahme; der Punkt ist
         zudem kein reines Farbsignal (siehe .glocke-punkt-Kommentar
         unten bei der Glocke-Regel). */
    --loeschen-knopf-bg: #cc0000;
    --loeschen-knopf-fg: #ffffff;
    /* Marken-Gold, Dunkelwert -- siehe Kommentar im Hellblock oben.
       Derselbe Ton wie auf der App-Kachel. */
    --marke-gold: #c9a05a;

    /* .kopf/.kopfzeile dunkel -- nachgemessen:
         vs --bg 1,34
         vs --fg (Ueberschrift) 12,04:1 -- weit ueber WCAG AA
         vs --gedaempft (filter-titel) 4,90:1 -- niedriger als der
           bisherige Wert gegen --bg (6,58:1), bleibt aber ueber WCAG
           AA 4,5:1, anders als im Hellmodus keine Verschlechterung
           unter AA
         vs --bg als Komponente (Suchfeld-Fuellung) 1,34:1
         vs --kachel-bg als Komponente 1,13:1 -- in derselben
           Groessenordnung wie --bereichsleiste-bg vs --kachel-bg
           (1,30:1)
         vs --kachel-aktiv-bg (Suchen-Knopf/Akzent familie) 4,18:1
       Vier Filterkachel-Akzente als Komponente (Schwelle 3:1):
         familie 4,18:1 (der knappste), stil 5,76:1, status 5,89:1,
         art 4,29:1 -- alle vier ueber 3:1. */
    --kopf-bg: #1f2d3e;

    /* Bereichs-Titeltoene dunkel -- gleiche Herleitung wie hell (rel.
       Leuchtdichte ~0,12 je Farbton, exakt dieselben 40°-Hues, nur der
       Farbton variiert). Kontrast gegen --fg: moves 5,33 · technik
       5,34 · musik 5,33 · notizen 5,33 · choreografien 5,35 ·
       personen 5,31 · ressourcen 5,29 · uebungseinheiten 5,31 ·
       quellen 5,37 -- alle ueber WCAG AA 4,5:1. Gegen --kopf-bg dunkel
       (0,025 Leuchtdichte, sehr dunkles Marineblau) alle bei ca.
       2,25:1 -- deutlicher erkennbares eigenes Feld als im Hellmodus,
       weil --kopf-bg dunkel selbst naeher am Schwarzpunkt liegt. */
    --titel-moves-bg: #316782;
    --titel-personen-bg: #765e2d;
    --titel-quellen-bg: #296c56;
    --titel-uebungseinheiten-bg: #2a6f2a;
    --titel-technik-bg: #5454be;
    --titel-ressourcen-bg: #536928;
    --titel-notizen-bg: #9e3c7d;
    --titel-musik-bg: #8841ac;
    --titel-choreografien-bg: #a53f3f;

    /* Bereichs-Kopftoene dunkel -- gleiche Herleitung wie hell (HSL
       S=33%, L=18%, aus --kopf-bg dunkel #1f2d3e zurueckgerechnet, nur
       um den Bereichs-Hue gedreht). Kontrast gegen --fg: 9,76–13,67:1,
       weit ueber WCAG AA. Gegen --gedaempft dunkel: 3,97–5,57:1 --
       durchweg ueber WCAG AA (anders als hell, da --gedaempft dunkel
       selbst heller ist). Vier Filterkachel-Akzente (nur Moves,
       Schwelle 3:1): familie 3,88 · stil 5,35 · status 5,47 · art
       3,98 -- niedriger als der bisherige Ausgangswert von --kopf-bg
       dunkel (4,18–4,29), aber alle vier bleiben ueber 3:1, keiner
       faellt unter AA -- offengelegte Verschlechterung, kein Bruch
       einer bestehenden Garantie. */
    --bereich-moves-bg: #1f343e;
    --bereich-personen-bg: #3e341f;
    --bereich-quellen-bg: #1f3e34;
    --bereich-uebungseinheiten-bg: #1f3e1f;
    --bereich-technik-bg: #1f1f3e;
    --bereich-ressourcen-bg: #343e1f;
    --bereich-notizen-bg: #3e1f34;
    --bereich-musik-bg: #341f3e;
    --bereich-choreografien-bg: #3e1f1f;
  }
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  background: var(--bg);
  color: var(--fg);
  font-family: var(--schrift-fliess);
}

/* Ueberschriften ueber die eigene Variable -- Vorgabe ist dieselbe
   Systemschrift wie der Fliesstext (var oben), ein Design darf hier
   z.B. eine Serifenschrift setzen, ohne den Fliesstext anzufassen. */
h1, h2, h3 {
  font-family: var(--schrift-titel);
}

/* 52px = Hoehe der zugeklappten .bereichsleiste, damit sie nichts am
   Seitenende verdeckt. */
body { padding-bottom: calc(52px + env(safe-area-inset-bottom, 0px)); }

/* Bearbeiten-Modus (Auftrag "Sieben Punkte", Punkt 7): eigener
   Seitenhintergrund fuer alle Bearbeiten-/Anlegen-Formulare (Klasse
   kommt aus rahmen.html, {% block body_klasse %}), gleich fuer jede
   Entitaet, nicht nur Moves. Farbe ist dabei NICHT das einzige
   Signal: jede dieser Seiten hat ohnehin schon eine eigene
   Ueberschrift ("X bearbeiten" / "Neuen X anlegen") und einen eigenen
   Knopftext ("Speichern"/"Anlegen"/"Trotzdem anlegen"), die den Modus
   unabhaengig von der Farbe erkennen lassen -- fuer Farbsehschwaeche
   oder in praller Sonne unverzichtbar (OBERFLAECHE.md, "Farbe ist nie
   das einzige Signal"). .bereichsleiste bleibt bewusst unveraendert
   (eigener, fester Navigations-Ton, unabhaengig vom Seitenmodus). */
body.bearbeiten-modus { background: var(--bearbeiten-bg); }
body.loeschen-modus { background: var(--loeschen-bg); }

/* --bereich-aktiv-bg (Auftrag "Bereichsfarben ausweiten"): eine
   Custom Property statt fester Werte, damit EIN Klassenname pro Seite
   (.bereich-farbe--X, siehe .titel-bereich--* weiter unten) reicht, um
   sowohl .kopf/.kopfzeile als auch .bereichsleiste/.bereichsraster
   einzufaerben -- Custom Properties vererben sich automatisch an
   Nachfahren im DOM (anders als background selbst), .bereichsraster
   braucht dadurch keine eigene Regel. var(...,Fallback) sorgt dafuer,
   dass Seiten ohne aktiven Bereich (Suche, Bearbeiten-Formulare) beim
   bisherigen neutralen Ton bleiben. */
.kopf {
  position: sticky;
  top: 0;
  z-index: 10;
  background: var(--bereich-aktiv-bg, var(--kopf-bg));
  border-bottom: var(--rahmen-fein) solid var(--rand);
  padding: max(env(safe-area-inset-top, 0px), 0.75rem) 0.75rem 0.5rem;
}

/* Bereichswechsel (Punkt 7): feste Leiste am unteren Rand, mit
   demselben details/summary-Aufklapp-Muster wie .abschnitte -- kein
   neues Bedienkonzept. z-index bewusst zwischen .kopf (10) und
   .video-wrapper.vollbild (100): der Vollbild-Player MUSS die Leiste
   ueberdecken, sonst liegt sie quer ueber dem Video (a34d4c6 war
   derselbe Fehlertyp beim Zoom -- hier vorher vermieden, nicht erst
   auf dem Geraet gefunden). */
.bereichsleiste {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 20;
  background: var(--bereich-aktiv-bg, var(--bereichsleiste-bg));
  border-top: var(--rahmen-fein) solid var(--rand);
}
/* Suche (Punkt 8) als eigener Link statt in der Bereiche-Leiste
   verschachtelt: ein <a> innerhalb von <summary> reagiert je nach
   Browser unzuverlaessig auf Klicks (das Aufklappen "gewinnt" oft).
   Stattdessen zwei Geschwister in einer Reihe. */
/* SYMBOL-LEISTE, Variante C (F16, PLAN-feinschliff.md, Timms Wahl nach
   Mockup-Vergleich): ruhende Eintraege zeigen NUR ihr Symbol, der
   aktive bzw. geoeffnete waechst zur beschrifteten Pille.

   AUSNAHME VON DER HAUSREGEL, ausdruecklich dokumentiert (F16 Punkt 4):
   "Zustand steht im Text" bzw. "ein Symbol traegt sein Wort" gilt hier
   NUR noch fuer den aktiven/geoeffneten Eintrag -- die ruhenden tragen
   ihr Wort nicht sichtbar. Timms Entscheidung zugunsten einer ruhigen
   Leiste. Der Ausgleich ist verbindlich und steht in rahmen.html an
   jedem Eintrag: JEDES Symbol traegt aria-label (Sprachausgabe) UND
   title (Tooltip am Zeiger), die 44px-Tippflaeche bleibt unangetastet.
   Wer die Leiste nicht sehen kann, verliert dadurch nichts; wer sie
   sieht, bekommt das Wort dort, wo er gerade steht.

   Das Raster von F15 (fuenf exakt gleiche Spalten) faellt damit weg:
   gleich grosse Felder waren die richtige Antwort auf gleich lange
   BESCHRIFTUNGEN. Jetzt sind die ruhenden Felder gleich grosse
   QUADRATE und nur der aktive darf breiter werden -- dafuer ist
   Flexbox das passende Werkzeug (siehe unten). */
/* DAS AKTIV-SIGNAL (F17 Punkt 2, Timms zweite Leisten-Sichtung):
   die Strichstaerke des Symbols, sonst nichts. Keine Flaeche, keine
   Pille, keine Farbe -- die Leiste ist durchgehend transparent.
   2 -> 3,25 auf dem 24er-Raster, bei 22px Anzeigegroesse also rund
   1,83px gegen 2,98px echte Strichbreite: gut zwei Drittel mehr, das
   traegt auch als EINZIGES Signal (nachgemessen, siehe Fertigmeldung).
   stroke-width als CSS-Eigenschaft schlaegt das gleichnamige
   Praesentationsattribut im SVG -- die Symbol-Bausteine bleiben
   unveraendert bei 2. */
.leisten-symbol { flex: 0 0 auto; display: block; stroke-width: 2; }
.bereichsleiste-zeile > a[aria-current] .leisten-symbol,
.bereichsleiste-zeile > details[open] > summary .leisten-symbol {
  stroke-width: 3.25;
}
/* DOPPEL-AKTIV (F17 Punkt 1, Timms Fehlerbefund): war ein Aufklapper
   offen, trug ER das Aktiv-Signal UND zusaetzlich der Eintrag der
   aktuellen Seite -- zwei "aktive" Eintraege gleichzeitig. Solange
   irgendein Aufklapper offen ist, faellt der Seiten-Aktivzustand
   deshalb auf die normale Strichstaerke zurueck; der offene
   Aufklapper ist dann der einzige hervorgehobene Eintrag.
   Reines CSS mit :has() -- die Regel gilt auch ohne JavaScript, wo
   leisten_aufklapper.js die Geschwister nicht schliessen kann. */
.bereichsleiste-zeile:has(details[open]) > a[aria-current] .leisten-symbol {
  stroke-width: 2;
}

/* RUECKWEG (F17 Punkt 3): das Wort am aktiven Eintrag ist auf Timms
   ausdruecklichen Wunsch weg -- entgegen der Hausregel "ein Symbol
   traegt sein Wort". Damit sind aria-label UND title an jedem Eintrag
   (rahmen.html) die EINZIGE Beschriftung; sie sind ab jetzt nicht mehr
   nur Ausgleich, sondern tragende Substanz und duerfen an keinem
   Eintrag fehlen.
   Das Wort-/Pillen-CSS bleibt vollstaendig erhalten und wird von einer
   Klasse an der Leiste geweckt (.bereichsleiste--mit-wort). Faellt der
   Alltagstest schlecht aus, ist der Rueckweg genau diese eine Klasse
   in rahmen.html -- kein CSS neu zu schreiben. */
.leisten-wort {
  max-width: 0;
  overflow: hidden;
  white-space: nowrap;
  opacity: 0;
  transition: max-width 0.18s ease, opacity 0.18s ease, margin-left 0.18s ease;
  margin-left: 0;
  font-weight: 600;
  font-size: var(--schriftgrad-klein);
}
.bereichsleiste--mit-wort .bereichsleiste-zeile > a[aria-current] > .leisten-wort,
.bereichsleiste--mit-wort .bereichsleiste-zeile > details[open] > summary > .leisten-wort {
  max-width: 8rem;
  opacity: 1;
  margin-left: var(--abstand-2);
}
@media (prefers-reduced-motion: reduce) {
  .leisten-wort { transition: none; }
}

/* RASTER statt Flexbox (F15 dritte Fassung, PLAN-feinschliff.md):
   Timms Befund "Heute sieht kleiner aus" stimmte -- nachgemessen stand
   Heute auf flex: 0 0 auto (64,6px), waehrend die flex:1-Nachbarn auf
   67,9px wuchsen. Der erste Versuch, allen fuenf Feldern flex: 1 1 0
   zu geben, brachte sie NICHT auf dasselbe Mass: Heute und Suche
   blieben exakt 9,6px breiter, und 9,6px ist genau ihr eigener
   waagerechter Innenabstand (2 x 0,3rem). Grund: die Flex-Basisgroesse
   eines Elements schliesst seinen Innenabstand mit ein, auch bei
   box-sizing: border-box und flex-basis: 0 -- Heute/Suche/Glocke sind
   SELBST das Feld und tragen den Abstand am Flex-Element, waehrend
   Bereiche/Neu ihn am inneren <summary> tragen (dort muss er bleiben,
   sonst reicht ihre Farbflaeche nicht mehr bis an die Feldkanten).
   Rasterspalten werden dagegen unabhaengig vom Innenabstand der
   Elemente bemessen: fuenf 1fr-Spalten sind exakt gleich breit, egal
   wo der Abstand sitzt. Konto bekommt eine auto-Spalte -- es traegt
   den runden Knopf, keine Beschriftung (eigene Regel weiter unten). */
.bereichsleiste-zeile {
  display: flex;
  align-items: start;
  /* Der Platz, den die ruhenden Symbolfelder nicht brauchen, verteilt
     sich gleichmaessig zwischen ihnen -- so bleibt die Leiste ruhig,
     egal ob die Glocke mitlaeuft (ab zwei Mitgliedern) oder nicht. */
  justify-content: space-between;
}
/* Jedes Feld ist im Ruhezustand ein gleich grosses Quadrat und waechst
   nur ueber seinen Inhalt (das eingeblendete Wort). flex-shrink 0,
   damit die 44px-Tippflaeche auch dann steht, wenn der aktive Eintrag
   viel Platz nimmt. */
.bereichsleiste-zeile > * {
  flex: 0 0 auto;
  min-width: 44px;
  min-height: 52px;
}
/* .such-link: das Boxmodell fuer FESTBREITE Leisten-Eintraege am Rand
   (heute nur noch Heute) -- Suche trug es bis F1/F4 (PLAN-
   feinschliff.md) ebenfalls, zusammen mit einem eigenen vollgesaettigten
   Ton (--kachel-aktiv-bg), Timms "grosse Suche": ein fester,
   herausgehobener Randplatz UND die kraeftigste Flaeche der ganzen
   Leiste. F4 gibt diesen Randplatz an Konto ab (siehe .leisten-eintrag--
   konto unten) -- Suche wird seitdem flex:1 (oben) mit demselben
   dezenten Farbmuster wie Bereiche/Neu (unten, .leisten-eintrag--suche),
   kein eigenes Boxmodell mehr. */
.such-link {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 52px;
  /* 0.3rem statt frueher 1.1rem und dann 0.75rem (F15 dritte Fassung,
     PLAN-feinschliff.md): "Heute" ist der einzige Nutzer dieser Klasse
     (F4). Solange es als einziges Feld einen groesseren Innenabstand
     trug, konnte es gar nicht gleich gross wie die Nachbarn werden --
     jetzt derselbe Mindest-Innenabstand wie .leisten-eintrag--suche
     und .bereichsleiste summary, die Breite kommt allein aus dem
     gleichmaessigen flex-Anteil (oben). */
  padding: 0 0.25rem;
  padding-bottom: env(safe-area-inset-bottom, 0px);
  font-weight: 600;
  /* --schriftgrad-klein (F15 dritte Fassung, PLAN-feinschliff.md,
     vorher --schriftgrad-neben): seit alle sechs Felder gleich breit
     sind, hat das laengste Wort "Bereiche" genau ein Feld zur
     Verfuegung, nicht mehr das breiteste. Bei Notebooks Monospace-
     Schrift fehlte damit 1px (nachgemessen) -- der naechstkleinere
     BEREITS BESTEHENDE Schriftgrad schafft wieder Luft, ohne einen
     neuen zu erfinden und ohne Notebook-Sonderfall (F15 Punkt 1:
     gemeinsame Leisten-Regel). Gilt gemeinsam mit den beiden
     Leisten-Regeln unten. */
  font-size: var(--schriftgrad-klein);
  /* Flaeche/Farbe/Trennlinie hier entfernt (F16 Variante C): Heute
     bekommt sein Aussehen jetzt aus den gemeinsamen Leisten-Regeln
     weiter unten -- ruhend ohne Flaeche, aktiv als Pille. */
  text-decoration: none;
}
/* Suches eigenes, schlichtes Boxmodell (F4) -- Groesse/Zentrierung wie
   .bereichsleiste summary, aber ohne dessen gap (kein Icon daneben). */
.leisten-eintrag--suche {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 52px;
  /* Mindest-Innenabstand (F15 Punkt 1, PLAN-feinschliff.md): GEMEINSAME
     Regel fuer alle Leisten-Eintraege, kein Notebook-Sonderfall --
     Notebooks Monospace-Schrift (--schrift-fliess) ist je Zeichen
     breiter als die anderen sechs Designs und stiess ohne diesen
     Abstand an den eigenen Rand. */
  padding: 0 0.25rem;
  padding-bottom: env(safe-area-inset-bottom, 0px);
  font-weight: 600;
  font-size: var(--schriftgrad-klein);
  text-decoration: none;
  cursor: pointer;
}
.bereichsleiste summary {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--abstand-3);
  min-height: 52px;
  /* Mindest-Innenabstand, gleiche Begruendung wie .leisten-eintrag--
     suche oben. */
  padding: 0 0.25rem;
  padding-bottom: env(safe-area-inset-bottom, 0px);
  font-weight: 600;
  font-size: var(--schriftgrad-klein);
  cursor: pointer;
  list-style: none;
}
.bereichsleiste summary::-webkit-details-marker { display: none; }
/* Kein +/--Zeichen mehr (F6, PLAN-feinschliff.md, Timms Sichtung):
   der aktive Zustand zeigt sich schon ueber die Akzentfarbe unten --
   das Zeichen war ein doppeltes Signal und kostete Platz. */

/* Vier Leisteneintraege, vier Toene (Timm, 2026-08-04): jeder Eintrag
   mischt 22% eines Akzentpaars der AKTIVEN Palette in den
   Leistengrund -- color-mix statt vier neuer Variablen je Palette,
   damit jedes Design automatisch seine eigenen Toene bekommt (keine
   Drift-Pflege). Der Eintrag der aktuellen Seite (aria-current) bzw.
   der offene Aufklapper traegt das VOLLE Akzentpaar (bereits
   gemessene Kombination). Text im Ruhezustand ist --fg auf dem
   Mischton -- alle vier Kombinationen stehen in pruefe_kontraste.py
   (mix:-Paare) und bestehen in allen 7 Paletten. Die Abgrenzung der
   Eintraege haengt NICHT an der Farbe: feine Trennlinien dazwischen,
   Beschriftung sowieso (Farbe nie einziges Signal). */
/* RUHEND: keine Flaeche, keine Trennlinie (F16 Variante C). Beides war
   die richtige Antwort auf BESCHRIFTETE Felder -- die Mischtoene
   trennten Wort von Wort, die Linien zogen die Feldgrenzen nach. Mit
   nur noch Symbolen trennt der Abstand (justify-content: space-between)
   von selbst, und fuenf verschiedene Farbfelder wuerden neben der einen
   farbigen Pille bloss laut. Die Toene sind nicht geloescht, sie sind
   in den aktiven Zustand gewandert (unten) -- dort tragen sie jetzt
   allein die Bedeutung "hier stehst du".
   Farbe ist weiterhin nicht das einzige Signal: der aktive Eintrag
   traegt zusaetzlich sein WORT und die Pillenform. */
.leisten-eintrag--heute,
.leisten-eintrag--suche,
.leisten-eintrag--glocke,
.bereichsleiste summary {
  background: none;
  color: var(--fg);
}
/* Die vier Akzent-Flaechen des aktiven Zustands hingen bis F16 hier
   ohne Bedingung. Seit F17 Punkt 2 ist die Leiste durchgehend
   transparent -- das Aktiv-Signal ist allein die Strichstaerke (oben).
   Die Regeln bleiben als Rueckweg erhalten, geweckt von derselben
   Klasse wie das Wort (.bereichsleiste--mit-wort): eine Klasse in
   rahmen.html bringt Flaeche UND Wort gemeinsam zurueck, so wie sie
   zusammengehoerten. */
.bereichsleiste--mit-wort .leisten-eintrag--heute[aria-current] {
  background: var(--akzent-stil-bg);
  color: var(--akzent-stil-fg);
}
.bereichsleiste--mit-wort .leisten-eintrag--suche[aria-current] {
  background: var(--akzent-status-bg);
  color: var(--akzent-status-fg);
}
.bereichsleiste--mit-wort .leisten-eintrag--bereiche[open] > summary {
  background: var(--akzent-familie-bg);
  color: var(--akzent-familie-fg);
}
.bereichsleiste--mit-wort .leisten-eintrag--neu[open] > summary {
  background: var(--akzent-art-bg);
  color: var(--akzent-art-fg);
}
/* Werkzeuge (F16 Punkt 1): fuenftes Akzentpaar gab es nicht -- der
   Eintrag teilt sich Familie/Stil/Status/Art nicht, sondern nimmt den
   neutralen Kachel-Ton, denselben, den auch Konto traegt. Begruendung
   wie dort: Werkzeuge ist kein Inhaltsbereich. Kein neues Farb-Literal,
   keine erfundene fuenfte Akzentfarbe. */
.bereichsleiste--mit-wort .leisten-eintrag--werkzeuge[open] > summary {
  background: var(--kachel-aktiv-bg);
  color: var(--kachel-aktiv-fg);
}
/* Glocke traegt im Rueckweg dasselbe Paar wie Heute -- sie ist der
   zweite Eintrag ohne eigenes Akzentpaar (siehe oben). */
.bereichsleiste--mit-wort .leisten-eintrag--glocke[aria-current] {
  background: var(--akzent-stil-bg);
  color: var(--akzent-stil-fg);
}

/* DIE PILLE (F16 Punkt 3): der aktive bzw. geoeffnete Eintrag ist das
   einzige Feld mit Wort -- und bekommt dafuer die Pillenform, damit er
   sich auch ohne Farbwahrnehmung als "der hier" von den ruhenden
   Quadraten abhebt (Form ist das zweite Signal neben der Flaeche).
   Der Innenabstand waechst mit, sonst klebte das Wort am Rand. */
.bereichsleiste--mit-wort .bereichsleiste-zeile > a[aria-current],
.bereichsleiste--mit-wort .bereichsleiste-zeile > details[open] > summary {
  border-radius: var(--radius-pille);
  padding-left: var(--abstand-4);
  padding-right: var(--abstand-4);
  transition: padding 0.18s ease;
}
@media (prefers-reduced-motion: reduce) {
  .bereichsleiste--mit-wort .bereichsleiste-zeile > a[aria-current],
  .bereichsleiste--mit-wort .bereichsleiste-zeile > details[open] > summary { transition: none; }
}

/* Werkzeuge-Aufklappflaeche: schlichte Zeilenliste statt des
   Kachelrasters von Bereiche/Neu -- es sind drei Ziele, kein Bereich
   mit Zahlen. Gleiche Flaeche und Position wie das Raster (siehe
   .bereichsraster unten), nur der Inhalt ist eine Liste. */
.werkzeug-liste {
  position: absolute;
  left: 0;
  right: 0;
  /* Gleiche Verankerung wie .bereichsraster: ueber der 52px hohen
     Leiste, nicht ueber dem eigenen summary -- sonst saesse die Liste
     an der Feldbreite geklebt statt ueber der ganzen Leiste. */
  bottom: calc(52px + env(safe-area-inset-bottom, 0px));
  display: flex;
  flex-direction: column;
  background: var(--bereich-aktiv-bg, var(--bereichsleiste-bg));
  border-top: var(--rahmen-fein) solid var(--rand);
  padding: var(--abstand-3);
  gap: var(--abstand-2);
}
.werkzeug-liste a {
  display: flex;
  align-items: center;
  min-height: 44px;
  padding: 0 var(--abstand-4);
  border-radius: var(--radius-klein);
  background: var(--bg);
  color: var(--fg);
  text-decoration: none;
  font-weight: 600;
  font-size: var(--schriftgrad-neben);
}
.werkzeug-liste a[aria-current] {
  background: var(--kachel-aktiv-bg);
  color: var(--kachel-aktiv-fg);
}
/* Konto-Menue, schwebende Variante (Timm, 2026-08-05, dritter Anlauf
   fuer Vokabulare/Mitglieder/Profil/Design/Abmelden): fest positioniert,
   unabhaengig von .kopf/.kopfzeile. Seit F4 (PLAN-feinschliff.md,
   vierter Anlauf, Timms Entscheidung) NICHT MEHR VERWENDET -- rahmen.html
   rendert stattdessen .leisten-eintrag--konto weiter unten, fest IN der
   Bereichsleiste. Diese Regeln bleiben bewusst im Stylesheet (Rueckbau-
   Weg): faellt Timms Alltagstest fuer die Leisten-Loesung schlecht aus,
   braucht rahmen.html nur wieder die alte Klasse zu tragen, kein CSS
   neu zu schreiben. */
.konto-menue {
  position: fixed;
  right: max(env(safe-area-inset-right, 0px), 0.75rem);
  bottom: calc(52px + env(safe-area-inset-bottom, 0px) + 0.75rem);
  z-index: 21;
}
.konto-menue > summary {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: var(--kachel-aktiv-bg);
  color: var(--kachel-aktiv-fg);
  font-weight: 600;
  cursor: pointer;
  list-style: none;
  /* Gleicher Schatten wie .filter-aufklapper-inhalt -- der einzige
     schon im Projekt gemessene/verwendete Schatten fuer eine
     schwebende Flaeche, keine neue Werteerfindung. */
  box-shadow: 0 12px 28px rgba(0, 0, 0, 0.25);
}
.konto-menue > summary::-webkit-details-marker { display: none; }
.konto-menue > summary img.avatar { width: 100%; height: 100%; }

/* Konto-Menue, Leisten-Variante (F4, PLAN-feinschliff.md, Timms
   Entscheidung 2026-08-05): nimmt Suches alten festen Randplatz ein --
   gleiches Boxmodell wie .such-link (52px, Trennlinie links, fest statt
   flex:1), aber bewusst NICHT eine der vier Bereichs-Akzentfarben
   (Familie/Stil/Status/Art -- Heute/Bereiche/Neu/Suche tragen sie schon,
   siehe oben): Konto ist kein Inhaltsbereich, sondern Kontoverwaltung.
   Die neutralen Kachel-Toene (dieselben, die der schwebende Rundknopf
   oben schon nutzte) halten das auseinander, ohne eine fuenfte
   Akzentfarbe zu erfinden -- der Avatar/Anfangsbuchstabe traegt die
   eigentliche Wiedererkennung, nicht die Leistenflaeche. */
/* Spezifitaets-Fund (F15 Punkt 2, PLAN-feinschliff.md): ".leisten-
   eintrag--konto" ist EIN Klassen-Selektor (Spezifitaet 0,1,0), aber
   ".bereichsleiste-zeile > details" (oben, fuer Bereiche/Neu) ist
   Klasse+Element (0,1,1) und gewann deshalb gegen die feste Breite
   hier -- Konto (ein <details>) schrumpfte dadurch wie ein flex:1-
   Element auf ~54px statt der gewollten 60px, seitlich UNGLEICH
   ausgerichtet und den Bereiche/Neu-Feldern zusaetzlich Platz
   wegnehmend (Timms Befund: Avatar nicht mittig, Leiste zu eng).
   Selektor hier auf gleiche Spezifitaet (0,2,1) angehoben, damit die
   feste Breite tatsaechlich greift. */
/* Vom rechten Rand geloest (F17 Punkt 4, Abstand nachgezogen auf Timms
   Sichtung): der Knopf klebte an der Bildschirmkante. Der Abstand steht
   am Feld, nicht am Kreis -- so bleibt die Tippflaeche vollstaendig
   innerhalb der Leiste.

   MASS: der Kreis ist im geoeffneten Zustand 70,4px breit (44px x 1,6)
   und sitzt mittig in einem 48px-Feld -- er ragt also (70,4-48)/2 =
   11,2px ueber jede Feldkante hinaus. Mit den vorherigen 0,5rem (8px)
   stand seine rechte Kante 3,2px NEBEN dem Bildschirm. 1rem (16px)
   laesst ihm 4,8px Luft, auch voll aufgeklappt. Wer den Kreis weiter
   vergroessert, muss diesen Wert mitziehen. */
.bereichsleiste-zeile > details.leisten-eintrag--konto {
  position: relative;
  margin-right: var(--abstand-5);
}
.leisten-eintrag--konto > summary {
  display: flex;
  align-items: center;
  justify-content: center;
  /* 48px (F15 dritte Fassung, PLAN-feinschliff.md): die EINZIGE feste
     Breite der Leiste -- die fuenf Beschriftungsfelder teilen sich den
     Rest zu gleichen Teilen (oben). 48px traegt den aufgesetzten
     Rundknopf (44,8px im Grundzustand, siehe unten) und bleibt ueber
     der 44px-Mindesttippflaeche. Wachsen darf der Knopf darueber
     hinaus per transform: eine Transformation ragt ueber ihre Box
     hinaus, ohne die Box selbst zu verbreitern. */
  width: 48px;
  min-height: 52px;
  padding-bottom: env(safe-area-inset-bottom, 0px);
  cursor: pointer;
  list-style: none;
}
/* Flaeche im offenen Zustand ENTFERNT (F17 Punkt 4, Timms Befund
   "andersfarbiger Platzhalter in Ursprungsgroesse"): das war sie --
   ein 48x52-Rechteck in --kachel-bg, das hinter dem herausgewachsenen
   Kreis stehen blieb und wie ein zweites, nicht mitgewachsenes Element
   aussah. Die Leiste ist seit F17 Punkt 2 ohnehin durchgehend
   transparent, der offene Zustand zeigt sich am gewachsenen Kreis. */
.leisten-eintrag--konto > summary::-webkit-details-marker { display: none; }
/* Kontrast des Anfangsbuchstabens: dieselbe Paarung wie ueberall bei
   "Text auf aktiver Kachel" (pruefe_kontraste.py), keine neue Farbe. */
.leisten-eintrag--konto-avatar {
  display: flex;
  align-items: center;
  justify-content: center;
  /* Gegen das "oval langgezogen" (F17 Punkt 4): der Avatar ist ein
     Flex-Element im summary, und dessen Innenabstand unten traegt
     env(safe-area-inset-bottom) -- auf dem iPhone rund 34px. Der
     Inhaltsbereich des 52px hohen Feldes schrumpft dadurch auf ~18px,
     und ein Flex-Element ohne Mindestmasse gibt in dieser Richtung
     nach: aus dem Kreis wird eine Ellipse. Auf dem Schreibtisch ist
     env() null, deshalb war davon in den Abnahme-Bildern nichts zu
     sehen. flex: 0 0 auto plus gleiche Mindest- wie Festmasse und
     aspect-ratio halten das Element unter allen Umstaenden quadratisch
     -- und damit border-radius: 50% kreisrund. */
  flex: 0 0 auto;
  box-sizing: border-box;
  width: 44px;
  height: 44px;
  min-width: 44px;
  min-height: 44px;
  aspect-ratio: 1;
  border-radius: 50%;
  background: var(--kachel-aktiv-bg);
  color: var(--kachel-aktiv-fg);
  font-weight: 600;
  overflow: hidden;
  /* AUFGESETZTER KNOPF (F15 dritte Fassung, PLAN-feinschliff.md,
     Timms Bild): im Grundzustand sitzt der Kreis mittig AUF der oberen
     Abschlusslinie der Leiste -- halb darueber, halb darunter, wie ein
     aufgesetzter Knopf. Beim OEFFNEN waechst er von dort weiter
     hinaus. Reine Transformation, kein width/height-Sprung: das
     Element bleibt 32px, scale+translateY tragen die Wirkung, ohne die
     48px-Breite seiner Box zu sprengen.

     RECHENWEG (die Reihenfolge in transform ist kein Zufall): bei
     "scale(S) translateY(Y)" wirkt das Verschieben IM SKALIERTEN
     Koordinatensystem -- in der fertigen Matrix steht Y*S, nicht Y.
     Der Avatar ist in einer 52px hohen Flaeche zentriert, seine Mitte
     liegt also 26px unter deren Oberkante. Die Abschlusslinie selbst
     ist der border-top der .bereichsleiste und liegt noch eine halbe
     Linienbreite darueber. Die wird MITGERECHNET statt fest
     eingesetzt: --rahmen-fein ist 1px in den meisten Designs, aber 2px
     in Notebook -- mit fest 0,5px sass der Kreis dort um genau einen
     Pixel daneben (nachgemessen). calc() haelt beide Faelle richtig:
       Grundzustand  scale(1,4): (-26px - halbe Linie) / 1,4  -> Kreis 44,8px,
                     Mitte mitten auf der Linie, 22,4px ragen darueber.
       Offen         scale(1,9): (-38px - halbe Linie) / 1,9  -> Kreis 60,8px,
                     Mitte 12px UEBER der Linie, waechst also von der
                     Grundposition weiter hinaus.
     position+z-index noetig, damit das Herausragen ueber die Leiste
     (z-index 20) sichtbar bleibt -- Leiste/Vorfahren tragen kein
     overflow:hidden (geprueft), sonst waere es wirkungslos. */
  position: relative;
  z-index: 21;
  transform: scale(1.25) translateY(calc((-26px - var(--rahmen-fein) * 0.5) / 1.25));
  transition: transform 0.2s ease;
}
img.leisten-eintrag--konto-avatar { object-fit: cover; }
.leisten-eintrag--konto[open] > summary .leisten-eintrag--konto-avatar {
  transform: scale(1.6) translateY(calc((-38px - var(--rahmen-fein) * 0.5) / 1.6));
}
@media (prefers-reduced-motion: reduce) {
  /* Die Groessenstufe selbst bleibt (sie zeigt "Menue offen"), nur
     der Uebergang dahin entfaellt -- gleiches Muster wie .titel-klebt. */
  .leisten-eintrag--konto-avatar {
    transition: none;
  }
}

/* Glocke (PLAN-glocke.md G1 Punkt 1): schlichter Leisten-Eintrag,
   einfacher Link statt details/summary -- nur ein Icon, kein
   Aufklapp-Inhalt. Seit F15 dritter Fassung KEINE eigene Breite mehr
   (vorher fest 44px): sie gehoert zu den fuenf gleich grossen Feldern
   und teilt deren flex-Anteil (siehe .bereichsleiste-zeile oben) --
   Timms Vorgabe "alle Leisten-Buttons exakt gleich gross" nennt die
   Glocke ausdruecklich mit. Der gleichmaessige Anteil liegt ueber der
   44px-Mindesttippflaeche (nachgemessen, siehe Fertigmeldung).
   glocke-punkt ist kein rein farbiges Signal (Regel "Farbe nie
   einziges Signal"): er existiert oder nicht, UND aria-label
   unterscheidet zusaetzlich per Text ("...ungelesene Ereignisse").
   Kontrast des Punkts auf der Leistenflaeche in pruefe_kontraste.py
   gemessen (PAARE "Glocke: Ungelesen-Punkt"). */
.leisten-eintrag--glocke {
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
  min-height: 52px;
  color: var(--fg);
}
.glocke-punkt {
  position: absolute;
  top: 10px;
  /* An der MITTE ausgerichtet, nicht am rechten Feldrand (F15 dritte
     Fassung): seit die Glocke ihre feste 44px-Breite gegen den
     gleichmaessigen flex-Anteil getauscht hat, ist das Feld breiter
     als das 22px-Symbol darin -- ein fester right-Abstand haette den
     Punkt vom Symbol abgeloest in der Feldecke stehen lassen. 50% ist
     die Symbolmitte, +6px setzt den Punkt auf dessen obere rechte
     Ecke (Symbol 22px breit, halbe Breite 11px, halber Punkt 5px). */
  left: calc(50% + 6px);
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--loeschen-knopf-bg);
  border: var(--rahmen-fein) solid var(--bereichsleiste-bg);
}

/* .konto-menue-inhalt (Dropdown-Flaeche, gemeinsam mit der schwebenden
   Variante oben): positionierungsneutral -- haengt nur vom jeweiligen
   Elternelement ab (bottom/right relativ zu dessen eigener Box), deshalb
   OHNE Aenderung fuer beide Varianten nutzbar. Seit F4 aktiv unter
   .leisten-eintrag--konto (position: relative, siehe oben) verankert;
   unter der schwebenden .konto-menue (position: fixed) taete sie
   dasselbe, bliebe die alte Variante wieder in Gebrauch. */
.konto-menue-inhalt {
  position: absolute;
  bottom: calc(100% + 0.5rem);
  right: 0;
  min-width: 220px;
  background: var(--kopf-bg);
  border: var(--rahmen-fein) solid var(--rand);
  border-radius: var(--radius-flaeche);
  box-shadow: 0 12px 28px rgba(0, 0, 0, 0.25);
  padding: 0.4rem;
  display: flex;
  flex-direction: column;
}
/* Abmelden abgesetzt (F17 Punkt 6): als einziger Punkt verlaesst er
   den angemeldeten Zustand -- Abstand plus feine Linie halten ihn von
   den Zielen darueber getrennt, damit er nicht versehentlich als
   naechster Menuepunkt mitgetippt wird. */
.konto-menue-abmelden {
  margin-top: var(--abstand-3);
  padding-top: var(--abstand-3);
  border-top: var(--rahmen-fein) solid var(--rand);
}
.konto-menue-inhalt a,
.konto-menue-inhalt button {
  display: block;
  width: 100%;
  min-height: 44px;
  padding: 0 0.6rem;
  display: flex;
  align-items: center;
  color: var(--fg);
  text-decoration: none;
  background: none;
  border: none;
  border-radius: var(--radius-klein);
  text-align: left;
  font: inherit;
  cursor: pointer;
}
.konto-menue-inhalt a:hover,
.konto-menue-inhalt button:hover {
  background: var(--kachel-bg);
}

/* Aus dem Fluss von <details> geloest (position: absolute gegen das
   bereits position: fixed gesetzte .bereichsleiste) statt normales
   Flex-Kind: als Kind von <details>, das wiederum flex:1 neben dem
   fest breiten .such-link teilt (siehe oben), erbte das Raster sonst
   dessen eingeschraenkte Breite -- das 3-Spalten-Raster wurde neben
   "Suche" abgeschnitten. So spannt es die volle Leistenbreite auf,
   waehrend die Bereiche/Suche-Zeile darueber unveraendert bleibt.
   Eigener Hintergrund noetig, weil .bereichsleiste dadurch nicht mehr
   automatisch dahinter mitwaechst (position: absolute traegt nicht
   zur Boxhoehe des Elternelements bei). bottom (nicht top!) wiederholt
   den bereits dokumentierten 52px-Wert der zugeklappten Zeile (siehe
   body weiter oben), plus derselbe Sicherheitsabstand fuers iPhone --
   .bereichsleiste sitzt selbst am unteren Bildschirmrand, das Raster
   muss also nach OBEN aufklappen, sonst rendert es unterhalb des
   sichtbaren Bereichs (genau dieser Fehler ist beim ersten Versuch
   mit top: passiert, im Browser bemerkt statt unbemerkt geblieben). */
.bereichsraster {
  position: absolute;
  left: 0;
  right: 0;
  bottom: calc(52px + env(safe-area-inset-bottom, 0px));
  background: var(--bereich-aktiv-bg, var(--bereichsleiste-bg));
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--abstand-3);
  max-height: 50vh;
  overflow-y: auto;
  /* Oben fehlte jedes Padding -- die erste Kachelreihe stiess direkt
     an die Aufklapp-Kante (Auftrag "Designaspekte pruefen"). 0.75rem
     wie an den Seiten/unten, gleiche Konsistenzregel wie ueberall
     sonst in diesem Raster. */
  padding: 0.75rem 0.75rem calc(0.75rem + env(safe-area-inset-bottom, 0px));
}
.bereichskachel {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--abstand-1);
  min-height: 56px;
  padding: var(--abstand-3);
  border-radius: var(--radius-flaeche);
  /* --bereich-aktiv-bg (dieselbe Custom Property wie .kopf/.kopfzeile/
     .bereichsleiste): abgeblasster Ton statt des kraeftigen Titelfeld-
     Tons (Nachtrag "Designaspekte pruefen") -- ruhiger neben den
     ebenfalls kraeftigen Kacheln der jeweiligen Listenseite. Die
     gerade aktive Kachel bekommt dabei denselben Ton wie die
     Panel-Flaeche dahinter und faellt optisch mit ihr zusammen, statt
     als eigener Button hervorzustechen -- gewollt (Timms eigene
     Beobachtung): sie liest sich dadurch eher als "du bist schon
     hier" statt als anklickbarer Vorschlag. Der Textlabel bleibt in
     jeder Kachel klar lesbar, Farbe ist ohnehin nicht das einzige
     Signal (wie ueberall sonst in diesem Projekt). */
  background: var(--bereich-aktiv-bg, var(--kachel-bg));
  /* Feiner Rahmen seit 2026-08-04 (Timms Befund: die Bereichs-Knoepfe
     wirkten randlos neben den uebrigen Feldern). Systematik seither:
     MENUE-/LISTENZEILEN (Bereichskacheln, Design-Liste) und
     Eingabefelder tragen den feinen Rahmen; Filter-/Aktions-PILLEN
     bleiben bewusst randlos gefuellt; Hauptknoepfe kraeftig gefuellt;
     Outline-Nebenknoepfe nur Rahmen. Gerade im Dunkelmodus lag der
     Flaechenkontrast Kachel-zu-Leiste sonst bei nur 1,13:1. */
  border: var(--rahmen-fein) solid var(--rand);
  color: inherit;
  text-decoration: none;
  text-align: center;
  font-size: var(--schriftgrad-neben);
}
/* Farbe je Bereich (Auftrag "Designaspekte pruefen"): dieselben neun
   abgeblassten Toene wie .kopf/.kopfzeile/.bereichsleiste
   (--bereich-*-bg, siehe Klassen in rahmen.html) -- die Kachel selbst
   wird zur Vorschau der Farbe, die hinter dem jeweiligen Bereich
   wartet. */
.bereich-anzahl {
  font-size: var(--schriftgrad-klein);
  /* --gedaempft war gegen die neutrale --kachel-bg gerechnet (3,1:1
     hell/5,52:1 dunkel); gegen die neun abgeblassten Bereichstoene
     nachgemessen: 13,25-16,04:1 hell / 9,76-13,67:1 dunkel -- weit
     ueber WCAG AA, sogar staerker als vorher (--gedaempft waere hier
     ohnehin zu blass gewesen). Trotzdem bei --fg geblieben (nicht
     zurueck zu --gedaempft): der Groessenunterschied (0.75rem vs. die
     groessere Bereichsbeschriftung) bleibt das alleinige Signal fuer
     "Nebentext", eine dritte Farbe zusaetzlich zu Bereichston und
     --fg haette keinen Zweck mehr. */
  color: var(--fg);
}
/* Aktiver Bereich hervorgehoben (Nachtrag "Designaspekte pruefen"):
   seit die Kachel-Farbe fuer den gerade aktiven Bereich mit der
   Panel-Flaeche verschmilzt (siehe .bereichskachel oben), war das der
   einzige verbliebene Unterschied zu den anderen acht -- jetzt zusaetzlich
   fett. aria-current="page" statt einer eigenen Klasse: korrektes
   ARIA fuer "aktuelle Seite in der Navigation" (Screenreader kuendigen
   das an) UND gleichzeitig der CSS-Haken, zwei Fliegen mit einer
   Klappe statt einer rein dekorativen Klasse. */
.bereichskachel[aria-current="page"] .bereich-name {
  font-weight: 700;
}

/* Vokabelpflege (Auftrag "Vokabelpflege bauen"): eigene Zeile UNTER dem
   Neun-Kacheln-Raster, keine zehnte Kachel -- die Neun-Bereiche-Struktur
   soll klar bleiben (gleiche Begruendung wie schon bei der bewusst
   fehlenden eigenen "Workshops"-Kachel). Reine Text-Zeile, ueber die
   volle Breite, optisch klar als "etwas anderes als ein Bereich"
   erkennbar. */
.vokabulare-link {
  grid-column: 1 / -1;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  margin-top: 0.25rem;
  padding-top: 0.6rem;
  border-top: var(--rahmen-fein) solid var(--rand);
  color: var(--gedaempft);
  font-size: var(--schriftgrad-neben);
  text-decoration: none;
}

/* Werkzeug-Zone (F11 Punkt 3, PLAN-feinschliff.md, PRAEZISIERT nach
   Timms erster Sichtung "noch nicht deutlich genug"): Lerncenter+Tools
   sind keine Datensatz-Bereiche -- eigene Flaeche mit Gruppentitel UND
   eigenem Kachel-Stil, damit der Unterschied zu den neun Bereichs-
   Kacheln auch ohne Text-Lesen ins Auge faellt. Farbe kommt per
   color-mix aus der AKTIVEN Palette (gleiche Ableitung wie die vier
   Leisten-Toene, stil.css .leisten-eintrag--*), kein neuer Farbwert je
   Design -- gemischt auf --bereich-aktiv-bg (dem Grund des gerade
   aufgeklappten Bereichsrasters, faellt ohne aktiven Bereich auf
   --bereichsleiste-bg zurueck), nicht auf --bereichsleiste-bg direkt,
   weil die Zone innerhalb des Rasters liegt. 16% statt der 22% der
   Leiste: eine Kachel-FLAECHE braucht weniger Saettigung als eine
   duenne Leisten-Zeile, sonst wirkt sie neben den echten
   Bereichs-Kacheln zu kraeftig. Beide Kombinationen (mit und ohne
   aktiven Bereich) in pruefe_kontraste.py gemessen, bestehen WCAG AA. */
.werkzeug-gruppe {
  grid-column: 1 / -1;
  margin-top: 0.25rem;
  padding: 0.6rem 0.75rem;
  border-radius: var(--radius-flaeche);
  background: color-mix(in srgb, var(--akzent-familie-bg) 16%, var(--bereich-aktiv-bg, var(--bereichsleiste-bg)));
  border: var(--rahmen-fein) solid var(--rand);
}
.werkzeug-gruppe-titel {
  margin: 0 0 0.5rem;
  font-size: var(--schriftgrad-klein);
  font-weight: 600;
  color: var(--gedaempft);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.werkzeug-kacheln {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--abstand-3);
}
.werkzeug-kachel {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--abstand-1);
  min-height: 56px;
  padding: var(--abstand-3);
  border-radius: var(--radius-flaeche);
  background: color-mix(in srgb, var(--akzent-familie-bg) 16%, var(--bereich-aktiv-bg, var(--bereichsleiste-bg)));
  border: var(--rahmen-fein) solid var(--rand);
  color: inherit;
  text-decoration: none;
  text-align: center;
  font-size: var(--schriftgrad-neben);
}
/* Aktive Seite: volles Akzentpaar statt des Mischtons, gleiches Muster
   wie .bereichskachel[aria-current="page"] -- bereits gemessenes Paar
   (Filterkachel familie in pruefe_kontraste.py), keine neue Kombination. */
.werkzeug-kachel[aria-current="page"] {
  background: var(--akzent-familie-bg);
  color: var(--akzent-familie-fg);
  font-weight: 700;
}

/* Abmelden (PLAN-anmeldung.md E2): teilt sich die Zeile mit "Design
   waehlen" statt einer eigenen volle-Breite-Zeile -- .vokabulare-link
   bleibt die gemeinsame Optik, hier nur zu zweit nebeneinander statt
   allein; das <form>/<button> braucht dafuer eigene Reset-Regeln
   (Formularelemente erben Farbe/Schrift sonst nicht). */
.vokabulare-link-zeile {
  grid-column: 1 / -1;
  display: flex;
  gap: var(--abstand-3);
}
.vokabulare-link-zeile .vokabulare-link {
  flex: 1;
  grid-column: auto;
}
.vokabulare-link-zeile form { flex: 1; }
.vokabulare-link-zeile button.vokabulare-link {
  width: 100%;
  border: none;
  border-top: var(--rahmen-fein) solid var(--rand);
  background: none;
  font-family: inherit;
  cursor: pointer;
}

input[type="search"] {
  width: 100%;
  /* 16px verhindert, dass iOS beim Antippen ungefragt hineinzoomt */
  font-size: var(--schriftgrad-basis);
  padding: 0.6rem 0.8rem;
  border-radius: var(--radius-flaeche);
  border: var(--rahmen-fein) solid var(--rand);
  background: var(--bg);
  color: var(--fg);
  margin-bottom: 0.5rem;
}

.kachelzeile {
  display: flex;
  gap: var(--abstand-3);
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  padding-bottom: 0.5rem;
  scrollbar-width: none;
}
.kachelzeile::-webkit-scrollbar { display: none; }
/* Umbruch-Variante fuer Einstellungs-Seiten (z.B. /design): dort
   sollen alle Optionen auf einen Blick sichtbar sein, waehrend die
   Filterzeilen der Listen bewusst scrollen (2026-08-04). */
.kachelzeile--umbrechend {
  flex-wrap: wrap;
  overflow-x: visible;
}

/* Bildausschnitt-Raster (F3, PLAN-feinschliff.md): neun 44px-Kacheln,
   3x3 statt der sonst ueblichen scrollenden Reihe -- die raeumliche
   Anordnung IST hier die Bedeutung (oben links = oben links im Bild),
   eine Reihe wuerde das zerreissen. Jede Kachel zeigt einen kleinen
   Punkt an GENAU der Stelle, die sie auswaehlt (left/top in % vom
   Template gesetzt, dieselben Werte wie ihr Radio-Wert) -- das erklaert
   sich selbst, ohne dass "Oben links" als Fliesstext neben neun engen
   Kacheln stehen muesste (die Beschriftung bleibt trotzdem da, als
   aria-label auf dem Label selbst statt sichtbarem Text). */
.fokus-raster {
  display: grid;
  grid-template-columns: repeat(3, 44px);
  gap: var(--abstand-2);
  margin: 0.5rem 0;
}
.fokus-zelle {
  position: relative;
  width: 44px;
  height: 44px;
  border-radius: var(--radius-klein);
  border: var(--rahmen-fein) solid var(--rand);
  background: var(--kachel-bg);
  cursor: pointer;
  /* Punkte an 0%/100% sollen sichtbar die Kachelkante beruehren (das
     IST die Aussage: "ganz am Rand des Bildes"), nicht als Halbkreis
     darueber hinausragen. */
  overflow: hidden;
}
.fokus-zelle input {
  position: absolute;
  opacity: 0;
  width: 1px;
  height: 1px;
}
.fokus-zelle:has(input:checked) {
  background: var(--kachel-aktiv-bg);
  border-color: var(--kachel-aktiv-bg);
}
.fokus-zelle-punkt {
  position: absolute;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--gedaempft);
  transform: translate(-50%, -50%);
}
.fokus-zelle:has(input:checked) .fokus-zelle-punkt { background: var(--kachel-aktiv-fg); }
/* Nur MIT JavaScript gesetzt (profilbild_fokus.js) -- ohne JS ist ein
   Klick auf die Vorschau wirkungslos, ein Fadenkreuz-Zeiger waere dann
   ein leeres Versprechen. */
.profilbild-vorschau--klickbar { cursor: crosshair; }

/* Sichtbarer Fokus-Ring fuer Tastatur-Bedienung (2026-08-04):
   :focus-visible feuert nur bei Tastatur/Schaltersteuerung, nicht
   beim Antippen -- der Ring nutzt die Akzentfarbe des jeweiligen
   Designs und hat in allen sieben Paletten mindestens 3:1 gegen
   --bg (dieselben Werte wie die Glyphen-Paare in
   pruefe_kontraste.py). */
:focus-visible {
  outline: 3px solid var(--kachel-aktiv-bg);
  outline-offset: 2px;
}

/* Wer im System 'Bewegung reduzieren' gewaehlt hat, bekommt keine
   Uebergaenge -- die App nutzt sie ohnehin nur als Zugabe
   (Titel-Schrumpfen, Knopf-Hover). */
@media (prefers-reduced-motion: reduce) {
  * {
    transition: none !important;
    animation: none !important;
  }
}

/* Zwei Filtergruppen nebeneinander, solange sie nebeneinander passen.
   Nachgemessen bei 375 px (iPhone): Art und Sortierung brauchen
   zusammen 322 Pixel Kacheln bei 351 Pixel Formularbreite. Wird es
   enger -- laengere Beschriftung, dritte Kachel --, bricht die zweite
   Gruppe von selbst um, statt die Kacheln unter die 44-Pixel-Tippgroesse
   zu druecken. min-width: 0, damit die innere .kachelzeile bei Bedarf
   waagerecht scrollen kann statt die Gruppe aufzublaehen. */
.filtergruppen { display: flex; flex-wrap: wrap; gap: 0 var(--abstand-5); }
.filtergruppe { flex: 1 1 auto; min-width: 0; }
.filtergruppe .filter-titel { margin-top: 0.6rem; }

.kachel {
  flex: 0 0 auto;
  position: relative;
  display: inline-flex;
  align-items: center;
  min-height: 44px; /* Apples eigener Mindest-Tippbereich */
  padding: 0 0.9rem;
  border-radius: var(--radius-pille);
  background: var(--kachel-bg);
  white-space: nowrap;
  font-size: var(--schriftgrad-neben);
  cursor: pointer;
  user-select: none;
}
.kachel input {
  position: absolute;
  opacity: 0;
  width: 1px;
  height: 1px;
}
/* :has() statt einer vom Server gesetzten .aktiv-Klasse: die Kachel
   reagiert direkt auf den Haekchen-Zustand der (unsichtbaren)
   Checkbox -- auch beim Antippen, ohne dass app.js das Formular
   mit-austauschen muesste. Funktioniert genauso ohne JavaScript,
   weil der Server das checked-Attribut schon beim Laden setzt. */
.kachel:has(input:checked) {
  background: var(--kachel-aktiv-bg);
  color: var(--kachel-aktiv-fg);
}
/* Design-Wahl (/design): Submit-Kacheln statt Radios -- EIN Tipp
   schaltet um, auch ohne JavaScript (Timms Wunsch 2026-08-04, der
   Uebernehmen-Knopf entfiel). button.kachel braucht den Formular-
   Reset. .kachel--gewaehlt ist KEINE zweite Zustandsquelle wie beim
   Filterkachel-Vorfall: es gibt hier keine Checkbox, der Server
   rendert die Wahl direkt aus der Datenbank -- die Klasse ist die
   einzige Quelle. */
button.kachel {
  border: none;
  font: inherit;
  font-size: var(--schriftgrad-neben);
  /* Knoepfe erben anders als <label> KEINE Textfarbe -- ohne diese
     Zeile gilt die Browser-Systemfarbe buttontext, und die folgt der
     GERAETE-Einstellung statt der Design-Palette: iPhone im
     Dunkelmodus + helles Design = weisser Text auf heller Kachel
     (Timms Fund 2026-08-04, Klassik Hell). */
  color: inherit;
}
/* button.kachel.kachel--gewaehlt zusaetzlich zu .kachel--gewaehlt
   (Timm-Fund 2026-08-05): button.kachel (Element+Klasse, Spezifitaet
   0,1,1) setzt oben color:inherit -- gegen das reine .kachel--gewaehlt
   (0,1,0) gewinnt das, die Flaeche faerbte sich also korrekt um, der
   Text blieb aber in --fg statt --kachel-aktiv-fg stehen. Faellt in
   Klassik kaum auf (--fg zufaellig noch lesbar auf --kachel-aktiv-bg),
   bricht aber sichtbar bei jedem Design/eigenen Design, dessen --fg
   NICHT zu --kachel-aktiv-bg passt -- betraf jede .kachel--gewaehlt-
   Stelle im Projekt (Uebungsstatus/Merkmale auf move.html, Zustaende
   auf quelle.html, Design-Wahl auf /design), nicht nur die
   Design-Seite. pruefe_kontraste.py haette es nie gefunden: das
   Skript rechnet gegen die deklarierten Variablenpaare, nicht gegen
   das tatsaechlich kaskadierte Rendering. */
.kachel--gewaehlt,
button.kachel.kachel--gewaehlt {
  background: var(--kachel-aktiv-bg);
  color: var(--kachel-aktiv-fg);
}
/* Die Design-Wahl als senkrechte Liste (Timms Wunsch 2026-08-04):
   je Design eine volle Zeile -- links der Name, rechts Farbpunkte
   aus der Design-Datei selbst (app.py liest bg/Akzent/Titelton aus
   designs/*.css, die Datei bleibt die einzige Quelle) plus die
   Stimmung. Die Punkte sind reine Zugabe (aria-hidden), die
   Stimmung steht als Text daneben. */
.design-liste {
  display: flex;
  flex-direction: column;
  gap: var(--abstand-4);
}
/* Je Zeile eigene Waehlen-form (PLAN-eigene-designs.md E1 -- Formulare
   duerfen sich nicht schachteln, darum nicht mehr EIN Formular mit
   vielen Submit-Knoepfen) plus optionale Zweitaktion darunter
   (Kopieren bei Datei-Designs, Bearbeiten/Umbenennen/Loeschen bei
   Eigenbauten) -- kleiner Abstand dazwischen. */
/* Zeile statt Stapel (Timm 2026-08-04: die Kopieren-Aufklapper unter
   den Designs waren als volle Breite viel zu gross): die Waehlen-
   Kachel nimmt den Platz, Aktionen (Kopieren bzw. Bearbeiten/
   Umbenennen/Loeschen) sitzen kompakt RECHTS in derselben Zeile.
   flex-wrap laesst sie auf schmalen Bildschirmen darunter rutschen;
   ein GEOEFFNETER Aufklapper nimmt bewusst die volle Breite unter
   der Kachel ein (flex-basis: 100%), damit das Namensfeld Platz hat. */
.design-zeile {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--abstand-2);
}
.design-zeile > form:first-child { flex: 1 1 16rem; min-width: 0; }
.design-zeile > details[open],
.design-zeile > .vokabel-zeilen-aktionen:has(details[open]) { flex-basis: 100%; }
.design-liste .design-wahl {
  width: 100%;
  justify-content: space-between;
  gap: var(--abstand-3);
  white-space: normal;
  text-align: left;
  border-radius: var(--radius-flaeche);
  border: var(--rahmen-fein) solid var(--rand);
}
.design-stimmung {
  display: inline-flex;
  align-items: center;
  gap: var(--abstand-1);
  font-size: var(--schriftgrad-klein);
  color: var(--gedaempft);
  flex: 0 0 auto;
}
.kachel--gewaehlt .design-stimmung { color: inherit; }
.design-farbpunkt {
  display: inline-block;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  border: var(--rahmen-fein) solid var(--rand);
}

/* Kernfarben-Ableitung (PLAN-eigene-designs.md E3): eigener Aufklapper
   unter der Liste, kein Teil von .design-liste -- deshalb der eigene
   Abstand nach oben. */
.design-ableiten-aufklapper { margin-top: var(--abstand-4); }

/* Farbfelder-Editor (PLAN-eigene-designs.md E2): je Variable ein
   kleines Feld, gruppiert nach denselben Bloecken wie stil.css
   (baue_farbgruppen() in app.py). --{{ name }} als Monospace-Label,
   damit sichtbar bleibt, welche stil.css-Variable gerade bearbeitet
   wird -- der Editor ist ein Formular, keine gestaltete Vorschau. */
.design-farbfelder {
  display: flex;
  flex-wrap: wrap;
  gap: var(--abstand-4);
  margin-bottom: var(--abstand-4);
}
.design-farbfeld {
  display: flex;
  flex-direction: column;
  gap: var(--abstand-1);
  font-size: var(--schriftgrad-klein);
  color: var(--gedaempft);
}
.design-farbfeld-name { font-family: monospace; }
.design-farbfeld input[type="color"] {
  width: 56px;
  height: 44px;
  padding: 0;
  border: var(--rahmen-fein) solid var(--rand);
  border-radius: var(--radius-klein);
  background: none;
}
.design-farbfeld input[type="text"] {
  min-height: 44px;
  padding: 0.4rem 0.5rem;
  border: var(--rahmen-fein) solid var(--rand);
  border-radius: var(--radius-flaeche);
  font-family: monospace;
  font-size: var(--schriftgrad-klein);
  background: var(--bg);
  color: var(--fg);
}

/* Kontrastampel (kontrast_ampel.js): eine Zeile je PAARE-Eintrag aus
   pruefe_kontraste.py, Gruen/Warnung MIT Zahlen -- warnt, blockiert
   nicht (Timms Sammlung). Reine Zugabe, bleibt ohne JavaScript leer;
   #kontrast-ampel-hinweis (statischer Text) sagt das auch so. */
#kontrast-ampel {
  display: flex;
  flex-direction: column;
  gap: var(--abstand-1);
  margin-bottom: var(--abstand-4);
}
.kontrast-zeile {
  display: flex;
  justify-content: space-between;
  gap: var(--abstand-3);
  padding: 0.4rem 0.6rem;
  border-radius: var(--radius-klein);
  font-size: var(--schriftgrad-klein);
  background: var(--kachel-bg);
}
.kontrast-zeile--warnung { background: var(--loeschen-bg); }
.kontrast-zeile--gruen { color: var(--gedaempft); }
.kontrast-zeile--unbekannt { color: var(--gedaempft); font-style: italic; }

/* Je Filterzeile ein eigener, gedaempfter Akzent auf der aktiven
   Kachel -- Zusatzsignal, nicht das einzige (siehe Textlabel
   .filter-titel darueber). */
.kachelzeile--familie .kachel:has(input:checked) {
  background: var(--akzent-familie-bg); color: var(--akzent-familie-fg);
}
.kachelzeile--stil .kachel:has(input:checked) {
  background: var(--akzent-stil-bg); color: var(--akzent-stil-fg);
}
.kachelzeile--status .kachel:has(input:checked) {
  background: var(--akzent-status-bg); color: var(--akzent-status-fg);
}
.kachelzeile--art .kachel:has(input:checked) {
  background: var(--akzent-art-bg); color: var(--akzent-art-fg);
}
.kachelzeile--signatur .kachel:has(input:checked) {
  background: var(--signatur); color: var(--akzent-signatur-fg);
}

/* Punkt 6, Nachtrag: zeigt die aktive Sortierrichtung an der Kachel an,
   die sonst nur ueber die Adresszeile sichtbar waere. */
.richtung-pfeil {
  margin-left: 0.3rem;
  font-weight: 400;
}

/* Klassischer visuell-versteckt-Zuschnitt: bleibt fuer Screenreader
   lesbar, ohne im Layout Platz zu beanspruchen. */
.nur-hoerbar {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* Filter/Sortierung zugeklappt als Ausgangszustand (wie .abschnitte auf
   Detailseiten und die Bereiche-Leiste unten -- dasselbe Muster, kein
   neues Bedienkonzept): sechs Filterzeilen stapelten sich sonst vor der
   ersten Trefferzeile. Funktioniert ohne JavaScript (natives <details>);
   app.js ersetzt bei einer Aenderung nur #treffer, das Formular bleibt
   unangetastet -- ein geoeffneter Zustand bleibt beim Filtern erhalten,
   nur ein frisches Laden der Seite klappt wieder zu. */
.filter-aufklapper { margin-bottom: 0.5rem; }
.filter-aufklapper summary {
  display: flex;
  align-items: center;
  min-height: 44px;
  font-weight: 600;
  cursor: pointer;
  list-style: none;
}
.filter-aufklapper summary::-webkit-details-marker { display: none; }
.filter-aufklapper summary::after {
  content: "+";
  margin-left: auto;
  font-weight: 400;
  color: var(--gedaempft);
}
.filter-aufklapper[open] summary::after { content: "–"; }

/* Hoehenbegrenzung mit eigenem Scrollen (Auftrag "Feste Kopfbereiche
   absetzen und begrenzen", Teil 2): .kopf ist sticky und hat seit Teil
   1 einen sichtbaren eigenen Untergrund -- ohne Grenze wuchs er bei
   offenem Aufklapper (Titel, Suchfeld, fuenf Filterzeilen, Sortierung,
   Suchen-Knopf) auf 375x812 gemessen auf 691px, liess nur ~68px
   Trefferliste unterhalb der festen Bereiche-Leiste uebrig. Nur
   dieser Innenteil (zwischen <summary> und Suchen-Knopf) bekommt die
   Grenze, NICHT .filter-aufklapper selbst -- <summary> ("Filter &
   Sortierung", zum Zuklappen) und der Suchen-Knopf (Formular-
   Geschwister NACH </details>) bleiben dadurch immer ausserhalb des
   Scroll-Bereichs erreichbar, ganz ohne dass man dafuer hineinscrollen
   muesste.
   280px gewaehlt (nicht vh-relativ, damit die Zahl auf jedem Geraet
   gleich bleibt): bei geoeffnetem Aufklapper sinkt .kopf damit von
   691px auf rechnerisch ~450px (Titel+Suchfeld+summary+Suchknopf+
   Paddings ~213px gemessen, + 280px hier + Scroll-Rand). Auf 375x812
   bleiben so unterhalb von .kopf und oberhalb der 52px-Bereiche-Leiste
   noch rund 310px fuer die Trefferliste -- mehrere Zeilen sichtbar,
   nicht nur eine. */
/* Seit 2026-08-04 ueberlagert der geoeffnete Filterbereich die
   Trefferliste als Panel, statt sie nach unten zu verdraengen --
   Timms Korb-2-Befund: beim Waehlen der Filter soll man die sich
   ergebenden Treffer sehen. Absolut unter dem <summary> verankert
   (.filter-aufklapper ist der Bezug), eigener Untergrund + Rahmen +
   Schatten, damit es als Ebene lesbar ist; maximal ~45% der
   Bildhoehe, damit darunter immer Treffer sichtbar bleiben. Der
   Suchen-Knopf (Geschwister nach dem details) liegt unter dem Panel
   -- mit JavaScript filtert ohnehin jeder Tipp sofort, ohne
   JavaScript schliesst man das Panel ueber das Minus im summary und
   der Knopf liegt wieder frei. Kein Abdunkeln der Liste: sie zu
   sehen ist ja gerade der Zweck. */
.filter-aufklapper { position: relative; }
.filter-aufklapper-inhalt {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  z-index: 11;
  background: var(--kopf-bg);
  border: var(--rahmen-fein) solid var(--rand);
  border-radius: var(--radius-flaeche);
  box-shadow: 0 12px 28px rgba(0, 0, 0, 0.25);
  padding: 0 var(--abstand-3) var(--abstand-3);
  max-height: min(45vh, 420px);
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}
/* Jahres-Filter (PLAN-auswertungen.md A6, Punkt 3): schmal wie
   .auswertungen-zeitraum input[type="number"] (dieselbe Sorte Feld,
   ein Jahr braucht keine volle Zeilenbreite). */
.filter-aufklapper-inhalt input[type="number"] {
  width: 6rem;
  min-height: 44px;
  padding: 0 0.6rem;
  border: var(--rahmen-fein) solid var(--rand);
  border-radius: var(--radius-flaeche);
  background: var(--bg);
  color: var(--fg);
  font-family: inherit;
  font-size: var(--schriftgrad-basis);
}

.filter-titel {
  font-size: var(--schriftgrad-klein);
  font-weight: 600;
  color: var(--gedaempft);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin: 0.9rem 0 0.35rem;
}
.filter-titel:first-of-type { margin-top: 0.5rem; }

.suchknopf {
  min-height: 44px;
  width: 100%;
  border: none;
  border-radius: var(--radius-flaeche);
  background: var(--kachel-aktiv-bg);
  color: var(--kachel-aktiv-fg);
  font-size: var(--schriftgrad-basis);
  margin-top: 0.3rem;
}

/* "Heute geübt"/"Gemeinsam geübt" (Timm-Befund 2026-08-05): teilten
   sich bisher .suchknopf mit ueber siebzig anderen Speichern-/Suchen-/
   Anlegen-Knoepfen im ganzen Projekt -- auf move.html/uebungseinheit.
   html, wo diese Knoepfe die haeufigste, wichtigste Handlung sind,
   gingen sie darin unter. Eigene Farbe statt der generischen
   --kachel-aktiv-bg: --akzent-stil-bg/-fg, derselbe Gruenton wie die
   "Kann ich"-Erfolgsmarkierung (kein neuer Farbwert, dieselbe
   Erfolgs-Bedeutung) -- bereits in pruefe_kontraste.py gemessen
   ("Filterkachel stil"). font-weight zusaetzlich zur Farbe, damit
   Farbsehschwaeche nicht die einzige Unterscheidung ist (der
   Haekchen-Kommentar an den Knoepfen selbst traegt das dritte
   Signal). */
.geuebt-knopf {
  min-height: 44px;
  width: 100%;
  border: none;
  border-radius: var(--radius-flaeche);
  background: var(--akzent-stil-bg);
  color: var(--akzent-stil-fg);
  font-size: var(--schriftgrad-basis);
  font-weight: 600;
  margin-top: 0.3rem;
}

/* [hidden] muss staerker sein als jede eigene display-Regel.
   Der Browser bringt zwar "[hidden] { display: none }" mit, das ist
   aber eine Vorgabe-Regel -- und JEDE eigene Regel schlaegt sie. Wer
   also .ziehgriff auf display: inline-flex setzt, macht ein
   hidden-Element wieder sichtbar.
   Genau das war passiert: ohne JavaScript stand der Ziehgriff der
   Choreo-Schritte sichtbar da, ohne etwas zu tun -- das Gegenteil
   dessen, was er sollte (er ist Zugabe, die Hoch/Runter-Knoepfe sind
   der Weg). Am 2026-08-03 im Browser nachgemessen, nicht vermutet.
   Ein !important, das hier richtig ist: "versteckt" darf sich nicht
   ueberstimmen lassen. */
[hidden] { display: none !important; }

/* Blaettern: voriger Eintrag links, Stand in der Mitte, naechster
   rechts -- die Anordnung sagt schon, was passiert, ohne dass man die
   Pfeile lesen muss. Am Anfang und Ende der Liste bleibt die Seite
   leer (.blaetter-leer haelt den Platz), damit der Stand in der Mitte
   nicht springt.
   Die Namen duerfen umbrechen und werden NICHT abgeschnitten -- lange
   Figurennamen sind in dieser Datenbank die Regel, und "Advanced
   BALBOA & BAL-SWING: Volume 2 …" als "Advanced BAL…" waere keine
   Auskunft (OBERFLAECHE.md).
   Kontrast: --gedaempft auf --bg fuer Stand und Pfeile (hell 3,5:1,
   dunkel 6,6:1 -- begleitende Angaben, wie .eintrag-neben), die Namen
   in --fg (hell 18,9:1, dunkel 16,1:1). */
.blaettern {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: var(--abstand-3);
  padding: var(--abstand-4);
  margin-top: 1rem;
  border-top: var(--rahmen-fein) solid var(--rand);
}
.blaetter-knopf {
  display: inline-flex;
  align-items: center;
  gap: var(--abstand-3);
  min-height: 44px;
  color: var(--fg);
  text-decoration: none;
}
.blaetter-nachher { justify-content: flex-end; text-align: right; }
.blaetter-pfeil { color: var(--gedaempft); flex: 0 0 auto; }
.blaetter-name { font-size: var(--schriftgrad-kompakt); }
.blaetter-stand {
  color: var(--gedaempft);
  font-size: var(--schriftgrad-klein);
  white-space: nowrap;
  text-align: center;
}

main { padding: var(--abstand-4); }

.anzahl { color: var(--gedaempft); font-size: var(--schriftgrad-neben); margin: 0 0 0.5rem; }

.trefferliste { list-style: none; margin: 0; padding: 0; }
.trefferliste li { border-bottom: var(--rahmen-fein) solid var(--rand); }

.treffer {
  display: block;
  padding: 0.75rem 0.25rem;
  min-height: 44px;
  color: inherit;
  text-decoration: none;
}
.treffer:active { background: var(--kachel-bg); }

.name {
  display: block;
  overflow-wrap: anywhere; /* lange Namen brechen um, statt zu ueberlaufen */
  word-break: break-word;
  font-size: var(--schriftgrad-basis);
  line-height: 1.35;
}

/* Regel fuer Sekundaerinfo in einer Listenzeile (Konsistenz-Durchsicht
   nach Punkt 6): .marken/.marke fuer MEHRERE gleichzeitige Werte
   (Quellen: Typ + Jahr, Technik: mehrere Kategorien, Uebungseinheiten:
   Art + Anzahl Moves). .eintrag-neben (unten) fuer EINEN einzelnen Wert
   (Notizen: nur das Jahr, Personen: ein zusammenhaengender Satz zur
   Figurenzahl) -- ein Chip fuer einen einzelnen Wert waere unnoetiges
   Gewicht. Beide bewusst nebeneinander, nicht vereinheitlichen. */
.marken {
  display: flex;
  flex-wrap: wrap;
  gap: var(--abstand-2);
  margin-top: 0.35rem;
}

.marke {
  background: var(--marke-bg);
  border-radius: var(--radius-klein);
  padding: 0.12rem 0.5rem;
  font-size: var(--schriftgrad-klein);
  overflow-wrap: anywhere;
}

/* Technik-Liste: bezeichnung ist ein Merksatz, kein kurzer Titel
   (Schnitt 56, bis zu 218 Zeichen) -- auf drei Zeilen abschneiden,
   statt die Liste durch einzelne sehr lange Eintraege zu sprengen.
   Nur hier, .name selbst bleibt fuer alle anderen Listen unangetastet. */
.name--merksatz {
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.leer { color: var(--gedaempft); padding: 1rem 0.25rem; }


/* ---------------------------------------------------------------
   Move-Ansicht
   --------------------------------------------------------------- */

/* Auftrag "Vier Punkte", Punkt 4: deutlicher als reiner Fliesstext
   (vorher color: inherit, kein Hintergrund) -- aber bewusst kein
   gefuellter Block wie .suchknopf: auf einer Detailseite ist Lesen die
   Haupthandlung, nicht Zurueckgehen, gleiche Abwaegung wie beim
   Kommentar an .rueckgaengig-knopf oben. Farbe kommt aus der
   bestehenden --kachel-aktiv-bg-Blaufamilie (keine neue Farbe im
   System), hier aber als Textfarbe auf einem ruhigen Kachel-Chip statt
   als volle Fuellung -- dadurch erkennbar mit den aktiven
   Kacheln/Knoepfen verwandt, ohne deren Gewicht zu haben.
   Kontrast --kachel-aktiv-bg (Text) gegen --kachel-bg (dieser Chip):
     Hell 4,74:1, Dunkel 4,70:1 -- beide ueber WCAG AA (4,5:1). */
.zurueck {
  display: inline-flex;
  align-items: center;
  gap: var(--abstand-2);
  min-height: 44px;
  padding: 0 0.7rem;
  border-radius: var(--radius-pille);
  background: var(--kachel-bg);
  color: var(--kachel-aktiv-bg);
  font-weight: 600;
  text-decoration: none;
  font-size: var(--schriftgrad-kompakt);
}
/* Steht der Zurueck-Knopf OHNE .kopfzeile-Rahmen (Unterseiten wie
   /design, Formulare, Verknuepfen-Fluesse), bekam er bisher keinen
   Seitenrand und stiess an die Bildschirmkante (Timms iPhone-Befund
   2026-08-04). Gleicher Einzug wie .inhalt; in der .kopfzeile sorgt
   deren eigenes Padding dafuer, dort greift die Regel nicht. */
:not(.kopfzeile) > .zurueck {
  margin: var(--abstand-2) 0 0 var(--abstand-4);
}

/* Homepage/Instagram/Facebook/Spotify als Icon- statt Textkachel
   (Auftrag "Logo-Buttons statt Textlinks") -- dieselbe Farbpaarung wie
   .zurueck (--kachel-aktiv-bg auf --kachel-bg, dort bereits
   nachgemessen: 4,74:1 hell / 4,70:1 dunkel, ueber WCAG AA), rund
   statt Pille. 44px = Apples Mindest-Tippbereich, wie ueberall sonst
   in diesem Projekt. Das Icon selbst ist aria-hidden, die
   Beschriftung steht als aria-label am Link.
   margin-bottom: die ersetzte .kachelzeile hatte padding-bottom:
   0.5rem (fuer den Scrollbar-Verstecken-Trick dort, siehe Kommentar
   an .kachelzeile) -- das ging beim Ersetzen verloren, dadurch stiess
   die Icon-Reihe direkt an den naechsten Eintrag, wenn kein Text
   dazwischenlag (z.B. Workshop ohne Notizen-Feld, direkt gefolgt vom
   Video). 0.75rem statt der alten 0.5rem, gleicher Wert wie sonst
   nach dem Titelfeld (.titel-klebt + *). */
/* Kopf einer Track- oder Playlistseite: Cover links, Angaben rechts.
   Das Cover ist hier gross (Timms Wunsch) und ZUGLEICH der Weg zu
   Spotify -- ein zusaetzliches grosses Bild weiter unten war damit
   doppelt und ist entfallen. 120px statt beliebig: gross genug zum
   Erkennen, klein genug, dass Titel und Angaben ueber der Falz
   bleiben. Auf schmalen Geraeten bricht die Zeile um.
   Kontrast Interpretenzeile: --fg auf --bg, hell 18,9:1, dunkel
   16,1:1 (dieselben Werte wie ueberall fuer --fg). */
.musik-kopf { display: flex; gap: var(--abstand-5); align-items: flex-start; flex-wrap: wrap; }
.musik-cover {
  flex: 0 0 auto;
  display: block;
  width: 120px;
  height: 120px;
  border-radius: var(--radius-flaeche);
  overflow: hidden;
  border: var(--rahmen-fein) solid var(--rand);
}
.musik-cover img { width: 100%; height: 100%; object-fit: cover; display: block; }
.musik-angaben { flex: 1 1 12rem; min-width: 0; }
.musik-kuenstler { font-weight: 600; margin: 0 0 0.25rem; }
/* Die oeffentliche Spotify-Trackliste: eigene Nummerierung, damit
   sichtbar bleibt, dass es eine Reihenfolge ist -- und keine
   Entfernen-Knoepfe, weil hier nichts zu entfernen ist: es sind
   fremde Daten, keine eigenen Datensaetze. */
/* Hoerprobe: im Ruhezustand ein gewoehnlicher .mini-knopf, waehrend
   des Abspielens gefuellt. Der Text wechselt dabei ebenfalls auf
   "■ Stopp" (hoerprobe.js) -- die Faerbung allein waere sonst das
   einzige Signal. Kontrast: --kachel-aktiv-fg auf --kachel-aktiv-bg,
   dieselbe Paarung wie bei den aktiven Filterkacheln, dort bereits
   geprueft. */
.hoerprobe { display: inline-flex; align-items: center; justify-content: center; }
.hoerprobe.laeuft {
  background: var(--kachel-aktiv-bg);
  color: var(--kachel-aktiv-fg);
  border-color: var(--kachel-aktiv-bg);
}
/* Im Kopf der Trackseite steht die Hoerprobe allein, nicht in einer
   Knopfreihe -- dort soll sie nicht ueber die ganze Breite laufen. */
.musik-angaben .hoerprobe { width: auto; padding: 0 0.9rem; margin-top: 0.5rem; }

/* Mitklopf-Zaehler. Der Klopfknopf ist absichtlich gross und hoch --
   man trifft ihn im Takt, ohne hinzusehen, und 44px reichten dafuer
   nicht. Die Zahl darin ist die Rueckmeldung; die Schlagzahl darunter
   sagt zusaetzlich in Worten, was passiert (aria-live meldet die Zahl
   auch vorlesend). */
.bpm-kasten { margin-top: 0.5rem; }
.bpm-klopf {
  min-height: 96px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--abstand-1);
  /* Kein Textmarkieren beim schnellen Mehrfachtippen, und kein
     Doppeltipp-Zoom auf iOS -- beides wuerde das Klopfen stoeren. */
  user-select: none;
  touch-action: manipulation;
}
.bpm-wert { font-size: var(--schriftgrad-anzeige); font-weight: 700; line-height: 1; }
.bpm-einheit { font-size: var(--schriftgrad-klein); letter-spacing: 0.08em; }
.bpm-schlaege { margin: 0.35rem 0 0; text-align: center; }

/* Der Hol-Kasten ueber den Anlegen-Formularen: sichtbar abgesetzt,
   weil er etwas anderes tut als das Formular darunter -- er speichert
   nichts, er fuellt nur aus. --kachel-bg und --rand sind bestehende,
   bereits gepruefte Werte. */
.spotify-holen {
  background: var(--kachel-bg);
  border: var(--rahmen-fein) solid var(--rand);
  border-radius: var(--radius-flaeche);
  padding: var(--abstand-4);
  margin-bottom: 1rem;
}
.spotify-holen .feld-label { margin-top: 0; }

.spotify-liste { counter-reset: spotify; }
.spotify-liste li { counter-increment: spotify; }
.spotify-liste li .name::before {
  content: counter(spotify) ". ";
  color: var(--gedaempft);
}

/* Musik einer Choreografie: Stueck und/oder Playlist, je mit dem
   Spotify-Knopf unmittelbar daneben. Zwei getrennte Ziele -- der Name
   fuehrt in die App (Tempo, BPM, Notizen), das Logo direkt zu Spotify
   --, deshalb zwei Flaechen statt eines Knopfes, der raet, was gemeint
   war. Umbruch erlaubt: bei "Titel – Interpret" wird die Kachel lang,
   und Namen werden hier so wenig abgeschnitten wie ueberall sonst. */
.musikzeile { display: flex; flex-wrap: wrap; gap: var(--abstand-3); margin-bottom: 0.75rem; }
.musik-eintrag { display: inline-flex; align-items: center; gap: var(--abstand-2); }

/* "Suche loeschen" -- erscheint nur, solange eine Suche laeuft. Ruhiger
   als der Suchknopf daneben (kein gefuellter Hintergrund): das Suchen
   ist die Handlung, das Beenden nur der Ausgang. Volle Breite und
   44px wie jeder .linkknopf, damit er sich mit dem Daumen trifft. */
.suche-loeschen { margin-top: 0.5rem; }

.kontakt-icons { display: flex; gap: var(--abstand-3); margin-bottom: 0.75rem; }
.kontakt-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: var(--kachel-bg);
  color: var(--kachel-aktiv-bg);
  text-decoration: none;
}
/* Dieselbe Flaeche mit Cover statt Logo (hole_spotify_cover.py). Eckig
   statt rund, weil ein Plattencover quadratisch ist und ein
   angeschnittener Kreis davon nur Mitte zeigt; der Rahmen haelt es
   auch auf hellem Bildinhalt vom Hintergrund getrennt. Gleiche 44px,
   damit die Reihe nicht springt, je nachdem ob ein Cover da ist. */
.kontakt-icon--cover {
  border-radius: var(--radius-klein);
  overflow: hidden;
  background: var(--kachel-bg);
  border: var(--rahmen-fein) solid var(--rand);
}
.kontakt-icon--cover img { width: 100%; height: 100%; object-fit: cover; display: block; }

.move-titel {
  font-size: var(--schriftgrad-zwischentitel);
  line-height: 1.3;
  margin: 0.25rem 0 0.75rem;
  padding: 0 0.75rem;
  overflow-wrap: anywhere;
  word-break: break-word;
}

.video-bereich { padding: 0 0.75rem; }

/* Textinhalt oberhalb der Abschnitte -- Personen-, Quellen- und
   Personenuebersicht-Seite haben kein Video, brauchen aber dieselbe
   seitliche Luft. */
.inhalt { padding: 0 0.75rem; }
.inhalt .kachelzeile { padding-left: 0; }

/* Anmeldeseite (PLAN-anmeldung.md E2): eigenes, schmales Grundgeruest
   ohne rahmen.html (siehe Kommentar in anmelden.html) -- etwas Luft
   oben/zentriert auf breiten Bildschirmen, auf schmalen einfach die
   volle Breite wie jedes andere Formular. */
.anmelden-rahmen {
  max-width: 400px;
  margin: 3rem auto;
  padding: 0 0.75rem;
}
/* Wortmarke auf der Anmeldeseite (D1b, IDEEN-dancevault.md, Timms
   Zeichen-Entscheidung -- loest das eingebettete Zeichen ab): "dance"
   in der Textfarbe, "vault" im Marken-Gold. Das dv-Monogramm bleibt
   das Symbol fuer Startbildschirm und Browser-Tab; ausgeschrieben
   gehoert die Marke auf die eine Seite, die man vor dem Anmelden
   sieht. Kein eigener Schriftschnitt: dieselbe Systemschrift wie
   ueberall, nur groesser, fett und eng gestellt. Die Anmeldeseite
   bleibt sonst schlicht, sie ist kein Werbeplatz. */
.anmelden-marke {
  margin: 0 0 var(--abstand-6);
  font-size: var(--schriftgrad-gross);
  font-weight: 700;
  letter-spacing: -0.01em;
  line-height: 1.1;
}
.marke-dance { color: var(--fg); }
.marke-vault { color: var(--marke-gold); }
.inhalt p { line-height: 1.5; }
.fortschritt-bereich { margin-bottom: 1rem; }

/* Bewusst zurueckhaltender als .suchknopf: das hier ist die Korrektur
   eines Fehlgriffs, nicht die Haupthandlung -- erscheint nur direkt
   nach dem Eintragen (siehe rueckgaengig_id in app.py), kein
   dauerhafter Loeschknopf. */
.rueckgaengig-knopf {
  min-height: 44px;
  width: 100%;
  margin-top: 0.5rem;
  border: var(--rahmen-fein) solid var(--rand);
  border-radius: var(--radius-flaeche);
  background: transparent;
  color: var(--gedaempft);
  font-size: var(--schriftgrad-kompakt);
}

/* Zwei kleine Aktionen je Zeile in .eintragsliste (Auftrag "Uebungs-
   einheiten und Playlists befuellbar machen"): erreicht-Umschalter und
   Entfernen, beide reine <form>-Knoepfe wie .rueckgaengig-knopf, nur
   nebeneinander statt untereinander. Kein neuer Farbton -- dieselben
   Tokens (--rand/--gedaempft), schon gegen Hell/Dunkel geprueft. */
.verknuepfung-aktionen { display: flex; gap: var(--abstand-3); margin-top: 0.5rem; }
.verknuepfung-aktionen form { flex: 1; }
/* Seit die Choreo-Schritte in EINEM Formular stehen (die Reihenfolge
   wird als Ganzes geschickt), sind die Knoepfe direkte Kinder und
   nicht mehr in je ein eigenes form gewickelt -- sie brauchen die
   Breitenverteilung deshalb selbst. */
.verknuepfung-aktionen > button { flex: 1; }
.verknuepfung-aktionen > button:disabled { opacity: 0.4; }
/* Sichern-Link (Auftrag "Medien sichern und in R2 loeschen") kann
   direktes Kind neben einem form-Knopf stehen (z.B. neben "Als Cover
   verwenden") -- ohne diese Regel bekaeme nur das form dieselbe
   Breitenverteilung wie die Buttons oben, der Link selbst nicht. */
.verknuepfung-aktionen > a { flex: 1; }

/* Choreo-Schritte umsortieren.
   Der Griff erscheint erst, wenn schritte_sortieren.js laeuft (im HTML
   steht er auf hidden) -- ohne Skript bleiben die Hoch/Runter-Knoepfe
   der einzige und vollstaendige Weg.
   Kontrast Griff: --fg auf --bg, hell 18,9:1, dunkel 16,1:1.
   Kontrast Schrittnummer: --gedaempft auf --bg, hell 3,5:1, dunkel
   6,6:1 -- die Nummer wiederholt nur die sichtbare Reihenfolge und
   traegt keine eigene Aussage, der Figurenname daneben steht in --fg. */
/* Die Schrittfolge ist beim Ueben der Teil, den man sucht -- sie
   bekommt einen eigenen Rahmen und eine eigene Flaeche, damit sie sich
   vom uebrigen Seiteninhalt abhebt (Timms Wunsch). --kachel-bg und
   --rand sind bestehende, bereits gepruefte Werte; es kommt kein
   neuer Farbton dazu. Der linke Balken ist ein zweites, von der Farbe
   unabhaengiges Signal. */
.schritt-abschnitt {
  border: var(--rahmen-fein) solid var(--rand);
  border-left: 4px solid var(--fg);
  border-radius: var(--radius-flaeche);
  background: var(--kachel-bg);
  padding: 0.25rem 0.75rem;
  margin: 0.75rem 0;
}
.schritt-abschnitt > summary { font-weight: 600; }
.schrittliste li {
  border-bottom: var(--rahmen-fein) solid var(--rand);
  padding-bottom: 0.5rem;
}
.schrittliste li:last-child { border-bottom: none; }

/* touch-action: none, NICHT pan-y -- mit pan-y beansprucht der Browser
   die senkrechte Geste fuer sich und scrollt, statt den Schritt
   mitzunehmen; genau daran ist das Ziehen zuerst gescheitert. Steht
   nur auf dem Griff: die Liste selbst muss weiter scrollbar bleiben. */
.ziehgriff {
  color: var(--fg);
  cursor: grab;
  touch-action: none;
  /* 44px, sonst trifft ihn niemand mit dem Daumen. */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  min-height: 44px;
  margin-right: 0.25rem;
  font-size: var(--schriftgrad-zwischentitel);
  line-height: 1;
}
.ziehgriff:active { cursor: grabbing; }
.schritt-nummer { color: var(--gedaempft); }
/* Die gezogene Zeile: Flaeche UND Umriss, nicht nur eine andere Farbe
   (OBERFLAECHE.md). --kachel-bg ist eine bestehende, bereits gepruefte
   Flaeche, hier kommt kein neuer Farbwert dazu. */
.schrittliste li.wird-gezogen {
  background: var(--kachel-bg);
  outline: 2px solid var(--fg);
  border-radius: var(--radius-flaeche);
}

/* Vokabelpflege (Auftrag "Vokabelpflege bauen"): Umbenennen/Entfernen-
   Mini-Formulare je Zeile in .eintragsliste -- gestapelt statt
   nebeneinander wie .verknuepfung-aktionen, weil hier ein echtes
   Eingabe-/Auswahlfeld dabei ist, nicht nur ein Knopf. */
.vokabel-zeilen-form { margin-top: 0.5rem; }
.vokabel-zeilen-form select {
  width: 100%;
  min-height: 44px;
  font-size: var(--schriftgrad-basis);
  padding: 0.5rem 0.6rem;
  border-radius: var(--radius-flaeche);
  border: var(--rahmen-fein) solid var(--rand);
  background: var(--bg);
  color: var(--fg);
  font-family: inherit;
}
.mini-knopf {
  /* display:flex + Zentrierung standardmaessig (Timm-Fund 2026-08-05):
     vorher trugen nur <summary>-Aufklapper diese Regeln (uebers
     spezifischere .vokabel-zeilen-aktionen summary/
     .vokabel-beschriftung-aufklapper summary weiter unten) -- ein
     .mini-knopf auf einem einfachen <a> (z.B. "Bearbeiten" auf
     /design) blieb dagegen ohne display:flex ein normales
     Inline-Element, das width/min-height ignoriert und den Text
     unzentriert zeigt: neben einem zentrierten <summary>-Knopf in
     derselben Zeile wirkte das inkonsistent und schlecht getroffen.
     text-decoration:none aus demselben Grund -- ein <a> ist sonst
     unterstrichen, ein <button>/<summary> nie, macht optisch
     denselben "Knopf" je nach Element unterschiedlich. */
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-height: 44px;
  border: var(--rahmen-fein) solid var(--rand);
  border-radius: var(--radius-flaeche);
  background: transparent;
  color: var(--gedaempft);
  font-size: var(--schriftgrad-klein);
  font-family: inherit;
  text-decoration: none;
}

/* .mini-knopf wirkt unveraendert auch auf <summary> (width/min-height/
   border/border-radius/Farben) -- hier nur der native Aufklapp-Pfeil
   entfernt und Klickflaeche/Zentrierung ergaenzt (gleiches Muster wie
   .abschnitte summary). Vokabelpflege-Ausbau Teil 1
   (PLAN-vokabelpflege-ausbau.md): zwei Aufklapper (Umbenennen/
   Entfernen) statt zweier immer offener Formulare -- Ruhezustand
   zeigt nur Wert + Nutzungszahl + die beiden Knoepfe. Ohne JavaScript
   voll bedienbar, <details> braucht keins. */
.vokabel-zeilen-aktionen {
  display: flex;
  gap: var(--abstand-2);
  margin-top: 0.5rem;
}
.vokabel-zeilen-aktionen > details { flex: 1; }
.vokabel-zeilen-aktionen summary,
.vokabel-beschriftung-aufklapper summary {
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  list-style: none;
}
.vokabel-zeilen-aktionen summary::-webkit-details-marker,
.vokabel-beschriftung-aufklapper summary::-webkit-details-marker { display: none; }
.vokabel-zeilen-aktionen > details[open] summary,
.vokabel-beschriftung-aufklapper[open] summary { margin-bottom: 0.5rem; }

/* Entfernen bekommt die Warnstufe der Loeschen-Bestaetigungsseiten:
   der Aufklapp-Knopf im Stil von .loeschen-knopf (roter Rahmen, siehe
   stil.css ~1445), die Flaeche beim Aufklappen in --loeschen-bg, der
   tatsaechlich loeschende Knopf im Stil von .loeschen-endgueltig-knopf
   (gefuellt rot, ~1464) -- alle drei Variablenpaare sind bereits Teil
   der Kontrastpruefung (pruefe_kontraste.py), keine neue Kombination. */
.vokabel-entfernen-aufklapper[open] {
  background: var(--loeschen-bg);
  border-radius: var(--radius-flaeche);
  padding: 0.6rem;
}

/* Zwei Stammfelder nebeneinander (heute: Beginndatum + Dauer im
   Quellen-Formular, Timms Wunsch 2026-08-04). flex:1 je Teil -- ist
   der zweite per bedingte_felder.js versteckt (Nicht-Workshop), nimmt
   der erste die volle Breite, ohne eigene Regel. */
.feld-doppel { display: flex; gap: var(--abstand-3); }
.feld-doppel > div { flex: 1; min-width: 0; }

/* Sterne + Wieder-besuchen-Chip in EINER Zeile (Timms Wunsch
   2026-08-04, PLAN-teilnahme-zeile.md V2) -- der Chip ist ein
   normales .kachel-Ein-Tipp-Formular, nur eben neben statt unter
   den Sternen; bei schmalen Bildschirmen bricht die Zeile um. */
.sterne-zeile {
  display: flex;
  align-items: center;
  gap: var(--abstand-3);
  flex-wrap: wrap;
}
.sterne-zeile .daumen-icon { flex: 0 0 auto; }
.daumen-symbol--runter { transform: rotate(180deg); }
/* Der Wieder-besuchen-Chip zeigt NUR das Piktogramm (Timm 2026-08-04:
   mit Text brach die Sterne-Zeile um) -- bewusste, dokumentierte
   Ausnahme von "Zustand steht im Text": Daumen hoch/runter und
   Fragezeichen sind selbsterklaerend, der volle Klartext bleibt als
   aria-label/title an genau diesem einen Knopf. */
.wieder-chip { min-width: 44px; justify-content: center; }

/* "÷ N" neben einem Kostenbetrag (PLAN-kostenblock.md, Teiler je
   Posten): schmales Zahlenfeld, das ÷ davor traegt die Bedeutung
   sichtbar, das aria-label spricht sie aus. */
.kosten-teiler {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  color: var(--gedaempft);
}
.kosten-teiler input { width: 3.5rem; }

/* Kosten-Chip mit aufklappbarer Rechnung (PLAN-kostenblock.md):
   zugeklappt sieht der Chip aus wie jede .marke; offen steht die
   Rechnung als kleine Liste darunter. details ist inline-block,
   damit der Chip in der marken-Zeile bleibt. */
.kosten-chip { display: inline-block; }
.kosten-chip summary {
  cursor: pointer;
  list-style: none;
  display: inline-flex;
  align-items: center;
}
.kosten-chip summary::-webkit-details-marker { display: none; }
.kosten-rechnung {
  list-style: none;
  margin: 0.35rem 0 0;
  padding: 0.5rem 0.6rem;
  border: var(--rahmen-fein) solid var(--rand);
  border-radius: var(--radius-flaeche);
  background: var(--kachel-bg);
  font-size: var(--schriftgrad-neben);
}
.kosten-rechnung li + li { margin-top: 0.2rem; }
.kosten-rechnung li:last-child { font-weight: 600; }

/* "Meine Abweichung" (K1, PLAN-kostenblock.md Nachtrag 2026-08-05):
   dieselbe 16px/44px-Regel wie jedes andere Eingabefeld (stil.css
   ~3040), hier eigens ausgeschrieben, weil der Steckbrief (anders als
   ein Bearbeiten-Formular) nicht in .bearbeiten-formular steckt. */
.kosten-abweichung-aufklapper input[type="number"] {
  width: 100%;
  min-height: 44px;
  font-size: var(--schriftgrad-basis);
  padding: 0.5rem 0.6rem;
  border-radius: var(--radius-flaeche);
  border: var(--rahmen-fein) solid var(--rand);
  background: var(--bg);
  color: var(--fg);
  font-family: inherit;
}

/* Schnellnotiz im Move-Steckbrief (Timm, 2026-08-04): zugeklappt nur
   ein .mini-knopf; offen ein kleines Formular. summary-Muster wie
   .vokabel-zeilen-aktionen (kein nativer Pfeil, Klickflaeche). */
.schnellnotiz summary {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  list-style: none;
}
.schnellnotiz summary::-webkit-details-marker { display: none; }
.schnellnotiz[open] summary { margin-bottom: 0.5rem; }
.schnellnotiz textarea {
  width: 100%;
  font: inherit;
  font-size: var(--schriftgrad-basis);
  padding: 0.5rem 0.6rem;
  border-radius: var(--radius-flaeche);
  border: var(--rahmen-fein) solid var(--rand);
  background: var(--bg);
  color: var(--fg);
  margin-bottom: 0.5rem;
}

.vokabel-zuordnung-form { margin-top: 0.35rem; }
.vokabel-zuordnung-form select {
  width: 100%;
  min-height: 44px;
  font-size: var(--schriftgrad-basis);
  padding: 0.5rem 0.6rem;
  border-radius: var(--radius-flaeche);
  border: var(--rahmen-fein) solid var(--rand);
  background: var(--bg);
  color: var(--fg);
  font-family: inherit;
}

/* Kein festes width/height auf video/img: die intrinsische Groesse der
   Datei bleibt die Obergrenze, max-width zieht nur zusammen, nie
   auseinander -- so werden die 480x360-Altvideos nicht ueber ihre
   native Groesse hinaus hochskaliert, waehrend die 1080p-R2-Videos
   ganz normal auf Bildschirmbreite schrumpfen. */
.video-bereich video,
.video-bereich img {
  max-width: 100%;
  height: auto;
  display: block;
  margin: 0 auto;
  border-radius: var(--radius-flaeche);
  background: #000;
}

/* Vorschaubild einer Ressource (hole_youtube_daten.py) -- gleiches
   Prinzip wie .video-bereich img, aber ausserhalb davon (Ressourcen
   haben keinen Videoplayer). Kein fester Rahmen/Hintergrund noetig,
   YouTubes hqdefault.jpg fuellt die Breite bereits komplett.

   Antippen spielt ab (video_einbetten.js ersetzt den Knopf-Inhalt
   durch ein iframe, Auftrag "YouTube entdoppeln") -- deshalb ein
   <button>, kein <a>: es ist eine Handlung auf der Seite, kein
   Sprung nach draussen wie beim YouTube-Link daneben. */
.ressource-vorschau {
  display: block;
  margin-bottom: 0.6rem;
}
.vorschau-abspielen-knopf {
  display: block;
  position: relative;
  width: 100%;
  padding: 0;
  border: none;
  background: none;
  cursor: pointer;
}
.vorschau-abspielen-knopf img {
  max-width: 100%;
  height: auto;
  display: block;
  border-radius: var(--radius-flaeche);
}
/* Halbtransparenter Kreis + Dreieck ueber dem Standbild -- dasselbe
   Muster, das YouTube selbst auf seinen Vorschaubildern zeigt.
   Kontrast laesst sich gegen ein beliebiges Foto nicht fest messen
   (anders als Text/Symbol auf einer eigenen Flaeche); der dunkle
   Kreis mit 70% Deckkraft schafft auf jedem bisherigen Vorschaubild
   sichtbaren Abstand zum Bildinhalt. Der aria-label am Knopf traegt
   die eigentliche Beschriftung, das Dreieck ist aria-hidden. */
.vorschau-play-symbol {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 56px;
  height: 56px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.7);
  color: #fff;
  font-size: var(--schriftgrad-zwischentitel);
}
/* Nach dem Antippen (video_einbetten.js: replaceChildren) steht ein
   iframe direkt im .ressource-vorschau-Container -- gleiche
   16:9-Regel wie .video-einbettung iframe. */
.ressource-vorschau iframe {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  border: none;
  border-radius: var(--radius-flaeche);
}

.linkknopf {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-height: 44px;
  margin-top: 0.6rem;
  margin-bottom: 0.6rem;
  padding: 0 1rem;
  /* Feiner Rahmen seit 2026-08-04 (Timms Rahmen-Frage, zweite Runde):
     die Verknuepfen-/Aktionsknoepfe ("+ Person hinzufuegen", Sichern
     usw.) sind bedienbare Zeilen, keine Filter-Pillen -- nach der
     Rahmen-Systematik gehoeren sie zur umrandeten Familie wie
     Bereichskacheln und Eingabefelder. */
  border: var(--rahmen-fein) solid var(--rand);
  border-radius: var(--radius-flaeche);
  background: var(--kachel-bg);
  color: inherit;
  text-decoration: none;
  font: inherit;
  font-size: var(--schriftgrad-kompakt);
  text-align: center;
  cursor: pointer;
}

/* Stufe 1 des Loeschens (PLAN-feinschliff.md F1, Timms Design-Befund
   2026-08-05: "sieht aus wie der YouTube-Knopf"): bis 2026-08-05 trug
   JEDE Stufe-1-Stelle einen kraeftigen roten Rahmen
   (--rahmen-stark/--loeschen-knopf-bg) -- das Warnsignal stand damit
   auf ZWEI Stufen gleichzeitig, obwohl nur die Endgueltig-Stufe
   (.loeschen-endgueltig-knopf, unten) tatsaechlich etwas loescht.
   Jetzt still: derselbe duenne Rahmen (--rahmen-fein in --rand) und
   dieselbe gedaempfte Textfarbe wie jeder andere .mini-knopf/
   .linkknopf -- das Wort "Loeschen" bleibt Warnung genug, bevor die
   rote Flaeche der Endgueltig-Stufe kommt. KEINE eigene Geometrie
   mehr (kein padding/min-height hier): dadurch erbt jede Stelle exakt
   das Feld ihrer eigenen Basisklasse (.mini-knopf/.linkknopf/
   .videokachel/.linkknopf--neben) OHNE Umweg ueber eine zweite,
   dickere Rahmenbreite -- der "Text grenzt an den Rahmen"-Fall bei
   den Dokumenten kam genau von den 2px statt 1px Rahmen, nicht von
   einer eigenen Padding-Regel. gedaempft-auf-bg ist Teil von
   pruefe_kontraste.py (Klassik hell 4,54:1, Klassik dunkel 6,58:1 --
   beide ueber der 4,5:1-Schwelle fuer Text, hell knapp; nachgerechnet
   mit derselben WCAG-Formel wie pruefe_kontraste.py, siehe --gedaempft
   in :root oben) -- keine neue Kombination, die neu gemessen werden
   muesste. */
.loeschen-knopf {
  border: var(--rahmen-fein) solid var(--rand);
  color: var(--gedaempft);
  background: none;
}

/* Der tatsaechlich loeschende Knopf auf der Bestaetigungsseite: erst
   hier eine gefuellte Warnflaeche. #cc0000/#ffffff hell gemessen
   5,89:1 (Text) -- im Dunkelmodus wird dieselbe Farbe zu schwach
   (weisser Text nur 4,13:1, Flaeche gegen --loeschen-bg/--kachel-bg
   dunkel nur 2,78/2,67:1, beides unter der jeweiligen Schwelle).
   Deshalb wie --kachel-aktiv-bg/-fg ein eigenes, helleres Rot MIT
   dunklem Text im Dunkelmodus, nicht dieselbe Farbe mit umgekehrter
   Textfarbe: #e53e3e/#111111 dunkel gemessen 4,58:1 (Text), 3,96:1
   gegen --loeschen-bg dunkel, 3,81:1 gegen --kachel-bg dunkel --
   alle drei ueber der jeweiligen Schwelle. */
.loeschen-endgueltig-knopf {
  background: var(--loeschen-knopf-bg);
  color: var(--loeschen-knopf-fg);
  border: none;
}

.videozeile {
  display: flex;
  gap: var(--abstand-3);
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  margin-top: 0.6rem;
  padding-bottom: 0.3rem;
  scrollbar-width: none;
}
.videozeile::-webkit-scrollbar { display: none; }

.videokachel {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  max-width: 220px;
  padding: 0 0.9rem;
  border-radius: var(--radius-pille);
  border: none;
  background: var(--kachel-bg);
  color: inherit;
  text-decoration: none;
  font-size: var(--schriftgrad-neben);
  font-family: inherit;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  cursor: pointer;
}
.videokachel.aktiv { background: var(--kachel-aktiv-bg); color: var(--kachel-aktiv-fg); }

/* Einbett-Knopf fuer YouTube-Videos (video_link_block(), _kontakt_
   icons.html): uebernimmt Form/Groesse von .linkknopf ODER .videokachel
   (zweite Klasse am selben Element, siehe Vorlage), bekommt hier nur
   die Akzentfarbe dazu -- dieselbe Familie wie .steuer-knopf.
   abspielen-knopf (dort steht die Kontrastmessung: 5,42:1 hell,
   5,64:1 dunkel), beides ist eine "hier abspielen"-Handlung. */
.video-einbetten-knopf {
  background: var(--kachel-aktiv-bg);
  color: var(--kachel-aktiv-fg);
}

/* Der YouTube-Link selbst (video_link_inhalt/video_link_block,
   _kontakt_icons.html): rot umrandet statt gefuellt, siehe
   --youtube-rot-Kommentar (:root) fuer die Kontrastmessung. Faerbt
   nur das Symbol, NICHT den Text (video_link_inhalt zeigt bei manchen
   Videos zusaetzlich "ab 8:58" -- der bleibt in --fg, weil Fliesstext
   die 4,5:1-Textschwelle braucht, die --youtube-rot nicht in beiden
   Farbschemata schafft). Signalisiert bewusst "verlaesst die App" --
   seit das Vorschaubild bei Ressourcen selbst abspielt (statt
   ebenfalls nach draussen zu fuehren), ist das der einzige Weg hier
   noch, der wirklich hinausfuehrt. */
.youtube-extern-knopf {
  border: var(--rahmen-stark) solid var(--youtube-rot);
}
.youtube-extern-knopf svg {
  color: var(--youtube-rot);
}

/* Eingebetteter YouTube-Player (video_einbetten.js): 16:9 wie jedes
   Video in .video-bereich, volle Breite. Eigener Block statt in die
   Pillen-Reihe eingefuegt -- eine .videozeile scrollt waagerecht,
   ein eingebetteter Player braucht aber die volle Breite, um nutzbar
   zu sein. */
.video-einbettung { margin-top: 0.6rem; }
.video-einbettung iframe {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  border: none;
  border-radius: var(--radius-flaeche);
}

/* "Weitere Dokumente" (Quelle): gleiches Scroll-Prinzip wie .videozeile,
   aber echte Bild-Kacheln statt Text-Pillen -- es gibt keinen Titel zum
   Anzeigen (Befund: keins der 53 Bilder hat einen). */
.dokumentenzeile {
  display: flex;
  gap: var(--abstand-3);
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  padding-bottom: 0.3rem;
  scrollbar-width: none;
}
.dokumentenzeile::-webkit-scrollbar { display: none; }

.dokument-kachel {
  flex: 0 0 auto;
  width: 96px;
  height: 96px;
  object-fit: cover;
  border-radius: var(--radius-flaeche);
  background: var(--kachel-bg);
}

/* Sichern-Knopf neben jeder Dokument-Kachel (Auftrag "Medien sichern
   und in R2 loeschen") -- eigene, kompakte Kachel statt Text unter dem
   Bild (kein Platz in der engen Zeile), 44px Mindest-Tippbereich trotz
   kleinerer optischer Groesse. align-self: center noetig, weil
   .dokumentenzeile (wie jede Flex-Reihe ohne eigene align-items-Regel)
   sonst auf die volle 96px-Hoehe der Bild-Kacheln daneben strecken
   wuerde. */
.dokument-sichern-knopf {
  flex: 0 0 auto;
  align-self: center;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: var(--radius-flaeche);
  background: var(--kachel-bg);
  color: inherit;
}

/* Ansichtsseite eines einzelnen Dokuments (Auftrag "Dokumente oeffnen
   ohne Rueckweg") -- volle Breite, keine feste Groesse wie die kleine
   Kachel: die intrinsische Groesse der Datei bleibt Obergrenze,
   gleiches Prinzip wie beim Videoplayer (.video-bereich img). */
.dokument-ansicht {
  display: block;
  max-width: 100%;
  height: auto;
  border-radius: var(--radius-flaeche);
  margin: 0 auto;
}

/* Cover-Bild einer Digitale-Medien-Quelle (F9 Punkt 2, verkleinert
   F14 Punkt 2, PLAN-feinschliff.md): war anfangs volle Breite bis 70vh
   Hoehe -- Timms Befund nach F10, "zu gross und einnehmend". Jetzt
   Vorschau-Charakter wie .musik-cover (120px, dieselbe Groesse) statt
   eines eigenen Massstabs -- gross macht das Bild die F2-Lightbox per
   Tipp, genau dafuer ist sie da. object-fit:contain bleibt (auch
   hochkantige Scans vollstaendig statt beschnitten). */
/* Abstand nach oben (F14-Nachbesserung, PLAN-feinschliff.md, Timms
   Befund): das Cover ist das erste Element im .video-bereich und stiess
   ohne eigenen Abstand direkt an den Schnellnotiz-Block darueber --
   nachgemessen 0px, zugeklappt an die Notiz-Zeile, aufgeklappt an den
   Speichern-Knopf. --abstand-5 ist dieselbe Stufe, die der Steckbrief
   sonst zwischen Bloecken nutzt (z.B. .fortschritt-bereich), kein
   eigenes Mass. Am umschliessenden Link statt am Bild selbst: der Link
   ist das Blockelement im Fluss, ein margin am Bild darin haette die
   Lightbox-Flaeche mitverschoben. */
.video-bereich > .bild-gross-aufklappbar:first-child { display: block; margin-top: var(--abstand-5); }
.video-bereich .quelle-cover-bild {
  /* Hoehere Spezifitaet als ".video-bereich img" (stil.css oben, height:
     auto) noetig -- sonst gewinnt die allgemeine Regel gegen die
     einzelne Klasse trotz spaeterer Reihenfolge (gefunden beim Bau von
     F14: das Cover blieb bei height:auto, also 40px hoch statt 120px,
     obwohl hier explizit height:120px stand). */
  display: block;
  width: 120px;
  height: 120px;
  object-fit: contain;
  border-radius: var(--radius-flaeche);
  background: var(--kachel-bg);
  border: var(--rahmen-fein) solid var(--rand);
}

/* video-wrapper: Rahmen fuer Frame-Stepping/Vollbild/Zoom+Verschieben
   (video_bedienung.js). Pinch-Zoom (Zwei-Finger-Geste) wurde ersatzlos
   entfernt -- auf iPhone UND Android liess sich das native Seiten-Zoom
   dabei nicht zuverlaessig unterdruecken. touch-action bleibt deshalb
   im Normalzustand unangetastet (= normales Zoomen/Scrollen ueberall,
   auch auf dem Video selbst). Erst WAEHREND gezoomt ist (Knopf-Zoom,
   siehe unten), verhindert .ist-gezoomt das Mitscrollen beim
   Ein-Finger-Verschieben -- touch-action wird am Beginn einer
   Beruehrung gelesen, die Klasse muss also schon VOR dem naechsten
   Touchstart gesetzt sein, nicht erst mitten in der Geste. */
.video-wrapper {
  position: relative;
}

/* video-rahmen: ENTHAELT NUR DAS VIDEO, nicht die Knopfzeilen -- die
   sind Geschwister davon, keine Kinder. Wichtig fuer overflow:hidden:
   transform:scale() auf dem Video (weiter unten) veraendert nur das
   optische Erscheinungsbild, NICHT die Layout-Groesse. Saesse das
   Video im selben Rahmen wie die Knoepfe, waere dessen Box automatisch
   so hoch wie Video+Knoepfe zusammen, und ein vergroessertes Video
   haette darin genug Platz, um trotz overflow:hidden ueber die
   Knopfzeilen zu malen -- genau das ist beim iPhone-Test passiert. Mit
   einem eigenen, nur-Video-Rahmen schneidet overflow:hidden exakt an
   der urspruenglichen Videogroesse ab, die Knoepfe bleiben unberuehrt,
   weil sie ausserhalb dieser Box liegen. */
.video-rahmen {
  position: relative;
  overflow: hidden;
}
.video-rahmen.ist-gezoomt {
  touch-action: none;
}

.video-rahmen video {
  /* Reihenfolge wichtig: translate() als AEUSSERE Funktion wirkt in
     Bildschirm-Pixeln, unabhaengig vom Zoomstand -- siehe
     video_bedienung.js. --spiegel als INNERSTE Funktion (nach scale)
     spiegelt nur die eigene Bilddarstellung, bevor Zoom/Verschieben
     darauf angewendet werden -- mit einem DOMMatrix-Test bestaetigt:
     ein Fingerdelta ergibt dieselbe Bildschirmverschiebung, ob
     gespiegelt oder nicht, die Wisch-Logik in video_bedienung.js
     musste dafuer nicht angepasst werden. */
  transform: translate(var(--pan-x, 0px), var(--pan-y, 0px)) scale(var(--zoom, 1)) scaleX(var(--spiegel, 1));
  transform-origin: center;
}

/* STAND (2026-08-02, Auftrag "Nativen Play-Knopf im Video wieder
   ausblenden"): Chrome/Android legt bei pausiertem Video einen
   grossen runden Play-Knopf MITTIG UEBER das Bild -- diese Regel
   blendet nur dieses Overlay aus.
   Vorgeschichte, zur Erklaerung, warum das hier nicht wieder blind
   dieselbe alte Annahme ist: Die Regel stand hier schon einmal, mit
   dem (damals falschen) Kommentar "der Knopf IN der Leiste bleibt
   unberuehrt" -- die eigene Bedienleiste (_video_steuerung.html)
   hatte zu dem Zeitpunkt aber gar keinen Knopf zum Abspielen/
   Pausieren, das Overlay war der einzige Weg ueberhaupt. Deshalb
   zwischenzeitlich ersatzlos entfernt (siehe Git-Historie). Seither
   gibt es den .abspielen-knopf unten in der Bedienleiste
   (video_bedienung.js) -- DAS ist jetzt die Steuerung, unabhaengig
   von jedem nativen Element. Auf Timms Android-Geraet bestaetigt,
   dass beide Knoepfe gleichzeitig sichtbar waren; das native Overlay
   ist mit dem eigenen Knopf entbehrlich und wird hier wieder
   ausgeblendet. NICHT zusaetzlich -start-playback-button ausblenden
   -- der stand beim ersten Versuch mit drin und war der eigentliche
   Auslöser des Problems (verhinderte den ALLERERSTEN Start, nicht nur
   das Overlay-Bild). Funktioniert die eigene Steuerung auf Android
   trotzdem nicht zuverlaessig (starten UND mitten im Video
   pausieren), diese Regel sofort wieder entfernen statt einschraenken
   -- ein sichtbarer Knopf zu viel schadet weniger als ein
   unabspielbares Video. */
.video-wrapper video::-webkit-media-controls-overlay-play-button {
  display: none !important;
}

.video-steuerung {
  display: flex;
  gap: var(--abstand-3);
  margin-top: 0.5rem;
  /* Zusaetzlich zum touch-action auf den einzelnen Knoepfen: ein Tipp,
     der knapp daneben in den Zwischenraum trifft (Fingerungenauigkeit),
     landet sonst auf diesem Container statt auf einem Knopf und ist
     dort nicht abgesichert -- beim Android-Test zoomte wiederholtes
     Antippen von "+" die ganze Seite mit, vermutlich genau deshalb. */
  touch-action: manipulation;
}

/* Bedienleiste unter dem Video: Abspielen- und Vollbild-Knopf bleiben
   AUSSERHALB des Aufklappers (eigene Zeile, siehe
   video_bedienung.js-Kommentar) -- sonst braeuchte man im Vollbild
   zwei Tipps, um es zu verlassen, und Abspielen waere die eine
   Grundfunktion, die eingeklappt startet. Gleiches Nebeneinander-
   Muster wie .bereichsleiste-zeile (Knopf + flex:1-Aufklapper). */
.video-steuerung-leiste {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: var(--abstand-3);
  margin-top: 0.5rem;
}
.video-steuerung-leiste > .abspielen-knopf { flex-shrink: 0; }
.video-steuerung-leiste > .vollbild-knopf { flex-shrink: 0; }

/* Aufklapper fuer die restlichen acht Knoepfe, zugeklappt als
   Ausgangszustand -- dasselbe details/summary-Muster wie
   .filter-aufklapper/.bereichsleiste, kein neues Bedienkonzept,
   funktioniert ohne JavaScript. Zustandsanzeige (.bedienung-status)
   braucht dagegen JavaScript (video_bedienung.js) -- Geschwindigkeit/
   Spiegeln/Schleife gehen nie an den Server, es gibt keinen
   serverseitigen Zustand, aus dem sich der Text bauen liesse (anders
   als .filter-aufklapper, dessen "offen bei aktivem Filter" rein
   serverseitig entschieden wird). Genau die Falle, die die
   Startseite schon einmal hatte: ein zugeklapptes Feld mit aktivem
   Inhalt sah aus wie ein leeres. */
/* Eigene volle Zeile, zugeklappt UND offen -- sonst quetschen sich
   Abspielen/Vollbild/Bedienung zu dritt in eine Zeile. Auf schmalen
   Bildschirmen (Android-Meldung) blieb dem Aufklapper dabei so wenig
   Breite, dass .bedienung-status (z.B. "· 0,75x") auf 0px Breite
   schrumpfte -- ohne eigene Zeile bleibt der Zustandshinweis
   unsichtbar, egal ob aktiv oder nicht, genau die Falle von oben.
   flex-wrap auf .video-steuerung-leiste sorgt dafuer, dass "100%"
   tatsaechlich in eine neue Zeile umbricht, statt nur die
   Breitenberechnung zu verzerren -- Abspielen/Vollbild ruecken dafuer
   zu zweit in die erste Zeile zusammen. */
.video-bedienung-aufklapper { flex: 1; flex-basis: 100%; min-width: 0; }
.video-bedienung-aufklapper summary {
  display: flex;
  align-items: center;
  gap: var(--abstand-2);
  min-height: 44px;
  padding: 0 0.8rem;
  border-radius: var(--radius-flaeche);
  background: var(--kachel-bg);
  font-size: var(--schriftgrad-neben);
  cursor: pointer;
  list-style: none;
  overflow: hidden;
  touch-action: manipulation;
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  user-select: none;
}
.video-bedienung-aufklapper summary::-webkit-details-marker { display: none; }
.video-bedienung-aufklapper summary::after {
  content: "+";
  margin-left: auto;
  flex-shrink: 0;
  font-weight: 400;
  color: var(--gedaempft);
}
.video-bedienung-aufklapper[open] summary::after { content: "–"; }
/* min-width:0 + Ellipsis: der Text hier ist Laufzeit-Zustand
   (Geschwindigkeit/Schleife/gespiegelt, siehe Kommentar oben), also
   unterschiedlich lang -- ohne das lief er auf schmalen Bildschirmen
   (Android-Test) ueber die Pillenform hinaus statt abzuschneiden, weil
   Flex-Kinder ohne min-width:0 nicht unter ihre Inhaltsbreite
   schrumpfen. "Bedienung" selbst bleibt immer vollstaendig lesbar,
   nur dieser Zusatz kuerzt bei Bedarf. */
.bedienung-status {
  color: var(--gedaempft);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
}

.steuer-knopf {
  flex: 1;
  min-height: 44px;
  border: none;
  border-radius: var(--radius-flaeche);
  background: var(--kachel-bg);
  color: inherit;
  font-size: var(--schriftgrad-neben);
  font-family: inherit;
  /* Fuers Gedrueckthalten (Spulen, siehe video_bedienung.js): auf dem
     Handy sonst ein Kontextmenue/eine Textauswahl-Blase statt (oder
     zusaetzlich zu) der eigenen Halten-Logik. touch-action:manipulation
     unterdrueckt ausserdem die Doppeltipp-Zoom-Verzoegerung. */
  touch-action: manipulation;
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  user-select: none;
}
.steuer-knopf:disabled { opacity: 0.5; }

/* Abspielen: der einzige der zehn Bedienleisten-Knoepfe mit eigener
   Farbe -- alle in kraeftigem Blau waeren in einer Reihe erschlagend
   und wuerden keinen davon als "die eine Grundfunktion" auszeichnen.
   Wiederverwendet dieselbe --kachel-aktiv-bg-Familie wie
   .videokachel.aktiv/.suchknopf, keine neue Farbe im System.
   Kontrast Text/Icon (--kachel-aktiv-fg) auf Knopf-Flaeche
   (--kachel-aktiv-bg): 5,42:1 hell, 5,64:1 dunkel -- ueber WCAG AA.
   Knopf-Flaeche selbst gegen --bg (Nicht-Text-Kontrast): 5,42:1 hell,
   5,60:1 dunkel -- ueber der 3:1-Mindestgrenze. Die uebrigen neun
   Knoepfe (Vollbild, Bild-Zurueck/-Vor, Zoom, Geschwindigkeit,
   Spiegeln, Schleife) bleiben neutral in --kachel-bg, siehe Auftrag
   "Videoknoepfe: Farbe". */
.steuer-knopf.abspielen-knopf {
  background: var(--kachel-aktiv-bg);
  color: var(--kachel-aktiv-fg);
}

/* "Grosses" Vollbild per CSS statt nativer Vollbild-API (siehe
   video_bedienung.js) -- volle Bildschirmgroesse, eigene Knoepfe
   bleiben sichtbar/bedienbar. */
.video-wrapper.vollbild {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: var(--abstand-3);
  padding: var(--abstand-4);
  background: #000;
}
.video-wrapper.vollbild video {
  max-height: 80vh;
  width: 100%;
}
.video-wrapper.vollbild .video-steuerung-leiste { flex-shrink: 0; }

/* Nebenaktionen unterm Player (Sichern, externer Link): eine Zeile,
   zurueckgenommene Gewichtung -- Rahmen statt Fuellung, gedaempfter
   Text (4,8:1 gegen --bg, ueber AA), kleinere Schrift. Die 44px
   Mindest-Tipphoehe erbt .linkknopf. Timms Befund 2026-08-04: die
   zwei vollbreiten Knoepfe nahmen Platz weg, ohne Teil der
   Videobedienung zu sein. */
.video-nebenaktionen {
  display: flex;
  gap: var(--abstand-3);
}
.video-nebenaktionen .linkknopf--neben {
  flex: 1 1 0;
  margin-top: 0.5rem;
  margin-bottom: 0;
  background: none;
  border: var(--rahmen-fein) solid var(--rand);
  color: var(--gedaempft);
  font-size: var(--schriftgrad-neben);
}

/* Bild-Lightbox (F2, PLAN-feinschliff.md, Zugabe zu bild_gross.js): nur
   die Zugabe-Flaeche selbst -- der Ohne-JS-Grundweg (Link auf
   /medium/{id}/ansehen) braucht kein eigenes CSS, die vorhandene Seite
   reicht. Gleiche Ebene wie .video-wrapper.vollbild (z-index 100, auch
   ein Vollbild-Overlay), aber ein durchscheinender Schleier statt
   solidem Schwarz -- das Bild soll wirken wie ueber die Seite gelegt,
   nicht wie ein eigener schwarzer Bildschirm (kein Player mit eigenen
   Bedienknoepfen darunter, die den Kontrast bräuchten). Der
   Mauszeiger-Hinweis (zoom-in) gilt fuer die Ausloeser IMMER, auch ohne
   JavaScript -- ein Klick fuehrt dort ohnehin zur vergroesserten
   Ansicht (Ansehen-Seite), die Erwartung stimmt so oder so. */
.bild-gross-aufklappbar { cursor: zoom-in; }
.bild-gross-overlay {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, 0.85);
  padding: var(--abstand-4);
  cursor: zoom-out;
}
.bild-gross-overlay img {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  cursor: zoom-out;
}
/* 44px Mindest-Tipphoehe (Apples eigener Wert, ueberall im Projekt so
   verwendet) fuer Tastatur/Screenreader -- ein Klick irgendwo auf den
   Schleier schliesst zwar auch (Plan-Vorgabe), aber ohne Maus/Touch
   braucht es einen fokussierbaren, benannten Knopf. */
.bild-gross-schliessen {
  position: absolute;
  top: var(--abstand-3);
  right: var(--abstand-3);
  width: 44px;
  height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  border: none;
  background: rgba(255, 255, 255, 0.15);
  color: #fff;
  font-size: 1.5rem;
  line-height: 1;
  cursor: pointer;
}

.abschnitte { margin-top: 0.5rem; }

.abschnitte details {
  border-bottom: var(--rahmen-fein) solid var(--rand);
  padding: 0 0.75rem;
}

.abschnitte summary {
  display: flex;
  align-items: center;
  min-height: 48px;
  font-size: var(--schriftgrad-basis);
  cursor: pointer;
  list-style: none;
}
/* NUR die direkten Abschnitts-Aufklapper werden fett (F9 Punkt 3,
   PLAN-feinschliff.md, Timms Sichtung "Loeschen-Text an Dokumenten
   ist fett"): dasselbe Erbe wie beim F1-Marker-Fund direkt unten --
   ohne das ">" traf font-weight:600 JEDE summary im Abschnitt, auch
   den verschachtelten .loeschen-knopf der Dokumente-Zeile, waehrend
   der video-loeschen-aufklapper (ausserhalb von .abschnitte) duenn
   blieb. Jetzt einheitlich duenn ausser an der Abschnitts-Ueberschrift
   selbst. */
.abschnitte > details > summary { font-weight: 600; }
.abschnitte summary::-webkit-details-marker { display: none; }
/* NUR die direkten Abschnitts-Aufklapper bekommen das Plus/Minus (F1,
   Timms Befund "das ominoese 'Loeschen--'"): ohne das ">" traf die
   Regel JEDE summary im Abschnitt, auch verschachtelte Aktions-
   Aufklapper wie .vokabel-entfernen-aufklapper -- ein "Loeschen–"
   direkt neben dem Wort war die sichtbare Folge. Aktions-Aufklapper
   bleiben jetzt markerfrei, ihre eigene Klasse (z.B. .mini-knopf)
   entscheidet ueber ihr Aussehen. */
.abschnitte > details > summary::after {
  content: "+";
  margin-left: auto;
  font-weight: 400;
  color: var(--gedaempft);
}
.abschnitte > details[open] > summary::after { content: "–"; }

.abschnitt-inhalt { padding: 0 0 1rem; font-size: var(--schriftgrad-kompakt); line-height: 1.5; }
.abschnitt-inhalt p { margin: 0 0 0.75rem; }

.eintragsliste { list-style: none; margin: 0; padding: 0; }
.eintragsliste li {
  padding: 0.6rem 0;
  border-top: var(--rahmen-fein) solid var(--rand);
}
.eintragsliste li:first-child { border-top: none; }
/* Ohne Unterstreichung (Timm 2026-08-04): die Zeilen-Links der
   Steckbrief-Beziehungen sollen aussehen wie die Trefferzeilen der
   Bereichslisten (.treffer, dort seit jeher text-decoration: none) --
   zwei Optiken fuer denselben "ganze Zeile ist ein Link"-Fall brachen
   die Logik. Gleiches gilt fuer Link-Chips (a.marke). */
.eintragsliste a { color: inherit; text-decoration: none; }
a.marke { color: inherit; text-decoration: none; }

/* Fuer EINEN einzelnen Wert -- bei mehreren gleichzeitigen Werten
   .marken/.marke nehmen (siehe Kommentar dort). */
.eintrag-neben { color: var(--gedaempft); font-size: var(--schriftgrad-neben); margin-top: 0.15rem; }

/* Zeile in .eintragsliste, die wie ein Link aussieht, aber ein Formular
   abschickt (Quelle aus der Trefferliste verknuepfen) statt zu einer
   Seite zu navigieren -- deshalb <button> statt <a>, mit zurueckgesetztem
   Aussehen, damit sie sich nicht von den Link-Zeilen (.eintragsliste a)
   unterscheidet. */
.eintrag-knopf {
  all: unset;
  display: block;
  width: 100%;
  cursor: pointer;
  color: inherit;
  font: inherit;
  text-align: left;
}


/* ---------------------------------------------------------------
   Avatare -- Foto oder Platzhalter mit Initialen. Beide gleich
   gross, damit eine Zeile ohne Foto nicht schief neben einer mit
   Foto steht (25 der 90 Personen haben keins).
   --------------------------------------------------------------- */

.avatar {
  flex: 0 0 auto;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  object-fit: cover;
}
.avatar-platzhalter {
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--kachel-bg);
  color: var(--gedaempft);
  font-size: var(--schriftgrad-neben);
  font-weight: 600;
}
.avatar-gross { width: 96px; height: 96px; }
.avatar-gross.avatar-platzhalter { font-size: 1.6rem; }

/* Etappe 3 (Suchlisten anreichern): Teacher-Fotos in der Quellen-
   Trefferzeile -- deutlich kleiner als der normale Avatar, weil hier
   mehrere nebeneinander stehen und nur Zusatzinfo zur Zeile sind
   (die Zeile selbst, .treffer, bleibt das eigentliche Antippbare,
   44px hoch -- die kleinen Kreise sind nicht einzeln antippbar, siehe
   OBERFLAECHE.md "Alles Antippbare mindestens 44px": gilt nicht, weil
   nichts davon ein eigenes Ziel ist). Kein neuer Kontrast noetig --
   dieselben Tokens (--kachel-bg/--gedaempft) wie .avatar-platzhalter,
   schon gegen Hell/Dunkel geprueft. */
.avatar-klein { width: 28px; height: 28px; }
.avatar-klein.avatar-platzhalter { font-size: 0.6rem; }
.teacher-fotos { display: flex; flex-wrap: wrap; align-items: center; gap: var(--abstand-2); margin-top: 0.35rem; }

.person-zeile { display: flex; align-items: center; gap: var(--abstand-4); }
.person-text { min-width: 0; }

/* Sterne-Bewertung (PLAN-sterne.md, Block 1a). Eingabe: echte
   Radiobuttons (funktioniert ohne JavaScript), visuell versteckt wie
   .kachel input, dafuer das <label> als 44px-Tippflaeche mit dem
   Stern-Glyph. "Stern N fuellt auch alle davor" ist reines CSS, kein
   JS: Markup in UMGEKEHRTER Reihenfolge (5,4,3,2,1) +
   flex-direction: row-reverse zeigt sie visuell wieder 1..5 von
   links; :checked ~ label trifft dank der Umkehrung automatisch auch
   alle "niedrigeren" Sterne, weil die im (umgekehrten) DOM SPAETER
   stehen. Kein Hover-Vorschau-Effekt -- Zielgeraet ist ein iPhone,
   Hover gibt es dort nicht. */
.sterne-eingabe { display: flex; flex-direction: row-reverse; justify-content: flex-end; }
.sterne-eingabe input {
  position: absolute;
  opacity: 0;
  width: 1px;
  height: 1px;
}
.sterne-eingabe label {
  cursor: pointer;
  min-width: 44px;
  min-height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--schriftgrad-gross);
  line-height: 1;
  color: var(--gedaempft);
}
.sterne-eingabe input:checked ~ label { color: var(--stern-gefuellt); }
/* Voll/leer traegt seit 2026-08-03 (Symbol-Inventur) die FORM (★/☆),
   die Farbe ist nur noch Zugabe -- vorher war sie das einzige Signal,
   ein Verstoss gegen die eigene Regel aus OBERFLAECHE.md, zumal Gold
   und Grau aehnlich hell sind. Beide Glyphen stehen im Label,
   :checked blendet eine aus -- rein per CSS, kein JavaScript. */
.sterne-eingabe label .stern-glyphe-voll { display: none; }
.sterne-eingabe input:checked ~ label .stern-glyphe-voll { display: inline; }
.sterne-eingabe input:checked ~ label .stern-glyphe-leer { display: none; }

/* Reine Anzeige (Quelle-Detailseite, Quellen-Trefferzeile) -- kein
   Formular, deshalb einfache Spans statt Radiobuttons. role="img" +
   aria-label traegt den vollstaendigen Wert ("4 von 5 Sternen") als
   EIN Text; die einzelnen Glyphen sind aria-hidden, damit ein
   Screenreader nicht fuenfmal "Stern" liest. Voll/leer unterscheidet
   sich seit 2026-08-03 auch durch die Form (★/☆, in den Vorlagen),
   nicht mehr nur durch diese zwei Farben. */
.sterne-anzeige { font-size: var(--schriftgrad-betont); line-height: 1; }
/* Im Steckbrief stehen die Sterne als eigener Block ueber der
   Chip-Zeile -- vorher waren sie ein Inline-Span direkt nach dem
   Titelfeld, auf dem vertikale Abstaende nicht greifen (Timms
   iPhone-Befund 2026-08-04: "Sterne stossen ans Titelfeld"). */
.steckbrief .sterne-anzeige {
  display: block;
  margin: 0 0 var(--abstand-2);
}

/* Antippbare Sterne im Quellen-Steckbrief (PLAN-bearbeiten-
   konsistenz, Befund 2): fuenf Submit-Knoepfe statt reiner Anzeige,
   gleiche Optik und dieselben 44px wie die Sterne-EINGABE im
   Bearbeiten-Formular; voll/leer traegt die Form (Sterne-Regel). */
.sterne-antippbar div {
  display: flex;
}
.sterne-antippbar button {
  min-width: 44px;
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: none;
  background: none;
  cursor: pointer;
  font-size: var(--schriftgrad-gross);
  line-height: 1;
  padding: 0;
}
.sterne-antippbar .stern-voll { color: var(--stern-gefuellt); }
.sterne-antippbar .stern-leer { color: var(--gedaempft); }

/* Zustands-Schalter im Steckbrief (Bucketlist/Teilnahme): eigene,
   klar abgetrennte Zeile UNTER den Sternen und UEBER den
   Anzeige-Chips (Timms Wunsch nach schaerferer Trennung 2026-08-04).
   Interaktive Kacheln tragen hier den feinen Rahmen -- dieselbe
   Systematik wie Menuezeilen: was bedienbar ist, ist umrandet, die
   reinen Anzeige-Chips darunter nicht. */
.steckbrief-schalter {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--abstand-3);
  /* Unten eine volle Stufe Luft zu den Anzeige-Chips -- Timms
     iPhone-Befund 2026-08-04: die Chips klebten an der Zeile. */
  margin: var(--abstand-2) 0 var(--abstand-5);
}
.steckbrief-schalter form {
  margin: 0;
  display: inline-flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--abstand-2);
}
.steckbrief-schalter .kachel {
  border: var(--rahmen-fein) solid var(--rand);
  /* Kompakt (Timm, 2026-08-04: die Teilnahme-Zeile war zu
     raumgreifend): schmaleres Padding und kleinere Schrift, die
     44px Tipphoehe erbt die Kachel unveraendert. */
  padding: 0 0.6rem;
  font-size: var(--schriftgrad-klein);
}
/* Bucketlist setzt sich farblich von den uebrigen Schaltern ab
   (Timm 2026-08-04): Rahmen im Status-Akzent, gewaehlt die volle
   Status-Paarung -- beide Paare sind fuer jedes Design in
   pruefe_kontraste.py gemessen (Filterkachel status bzw. Glyphe
   gegen bg), keine neue Farbe im System. */
.kachel--bucketlist {
  border-color: var(--akzent-status-bg);
}
.kachel--bucketlist.kachel--gewaehlt {
  background: var(--akzent-status-bg);
  color: var(--akzent-status-fg);
}

/* Icon in einem Link-Chip (z.B. Homepage im Quellen-Steckbrief):
   auf Textgroesse gebracht, gleiche Grundlinie wie die Glyphen. */
.marke svg {
  width: 1em;
  height: 1em;
  vertical-align: -0.15em;
}
/* Label klein NEBEN den Kacheln statt als Ueberschrift darueber --
   eine Zeile statt zwei; das Daumen-Symbol davor ist Zugabe. */
.steckbrief-schalter-titel {
  display: inline-flex;
  align-items: center;
  gap: var(--abstand-1);
  font-size: var(--schriftgrad-klein);
  color: var(--gedaempft);
}
.steckbrief-schalter-optionen {
  display: inline-flex;
  align-items: center;
  gap: var(--abstand-2);
}

/* Kleiner Leeren-Knopf hinter den antippbaren Sternen: bewusst
   dezenter als die Sterne selbst, aber volle 44px Tippflaeche. */
.sterne-antippbar .sterne-leeren {
  font-size: var(--schriftgrad-betont);
  color: var(--gedaempft);
}

/* Auf einer GEWAEHLTEN Kachel erben Statussymbol, Herz und Fuss die
   Kachel-Textfarbe -- ihre eigenen Akzentfarben sind gegen
   --kachel-aktiv-bg nicht gemessen und dort nur Rauschen. */
.kachel--gewaehlt .status-symbol,
.kachel--gewaehlt .signatur-herz {
  color: inherit;
}
.sterne-anzeige .stern-voll { color: var(--stern-gefuellt); }
.sterne-anzeige .stern-leer { color: var(--gedaempft); }

.person-kopf { display: flex; gap: var(--abstand-5); align-items: flex-start; margin-bottom: 0.5rem; }
/* min-width: 0 gilt nach wie vor der Textspalte (langer Name muss
   umbrechen/schrumpfen duerfen) -- die Person-Foto-Spalte, fuer die
   sie zwischenzeitlich (Sichern-Knopf am Personenfoto) ebenfalls galt,
   ist wieder ein bare <img>, kein <div> mehr, siehe person.html. */
.person-kopf > div { min-width: 0; }

.typ-titel {
  font-weight: 700;
  font-size: var(--schriftgrad-basis);
  margin: 1.25rem 0 0.5rem;
}
.typ-titel:first-child { margin-top: 0; }

/* Suche ueber alle Bereiche (Punkt 8): ein .such-abschnitt je
   Bereich/Verknuepfung, durch Rand getrennt statt nur Abstand -- bei
   bis zu neun gleichzeitigen Abschnitten (Ein-Buchstabe-Suche) sonst
   schwer zu unterscheiden, wo einer endet und der naechste beginnt. */
.such-abschnitt {
  padding: 1rem 0;
  border-bottom: var(--rahmen-fein) solid var(--rand);
}
.such-abschnitt:first-child { padding-top: 0; }
.such-bereich-titel {
  font-weight: 700;
  font-size: var(--schriftgrad-betont);
  margin: 0 0 0.5rem;
}
/* Verknuepfte Treffer (Nachtrag): dezent vom Marke-Ton abgesetzt,
   damit auf den ersten Blick klar ist, dass hier etwas anderes
   gezeigt wird als ein direkter Treffer. */
.such-verknuepft { background: var(--marke-bg); border-radius: var(--radius-klein); padding: 1rem 0.75rem; border-bottom: none; }

/* Bewusst zurueckhaltend, nicht aufdringlich -- steht am Fuss der
   Startseite, faellt nur auf, wenn man hinschaut oder wenn sie alt
   genug ist, um die Farbe zu wechseln (sicherung_alt). */
.fuss { padding: 1.5rem 0.75rem 2rem; text-align: center; }
.sicherung-hinweis { color: var(--gedaempft); font-size: var(--schriftgrad-klein); }
.sicherung-alt { color: var(--akzent-status-bg); font-size: var(--schriftgrad-klein); font-weight: 600; }
.warteschlangen-link { color: inherit; font-size: var(--schriftgrad-neben); }
.hinweis-erledigt {
  margin: 0 0.75rem 1rem;
  padding: var(--abstand-4);
  border-radius: var(--radius-flaeche);
  background: var(--marke-bg);
  font-size: var(--schriftgrad-kompakt);
  text-align: center;
}


/* ---------------------------------------------------------------
   Move bearbeiten (Schritt 2)
   --------------------------------------------------------------- */

/* Kopfzeile (Auftrag "Navigationsbuttons"): Zurueck-Chip und
   Bearbeiten-Knopf in einer Zeile, Bearbeiten ganz rechts -- nimmt
   dadurch neben der Titelzeile keinen Platz mehr weg (vorher beide in
   .titelzeile neben dem <h1>, Bearbeiten musste sich die Zeile mit dem
   oft langen Namen teilen). */
/* Sticky wie .kopf auf den Listenseiten (Auftrag "Feste Kopfbereiche
   absetzen und begrenzen", Teil 3) -- position: sticky statt fixed,
   dieselbe Technik, die dort schon funktioniert, ohne Ausgleichs-
   Padding am body (bleibt im normalen Dokumentfluss). z-index: 10,
   dieselbe Ebene wie .kopf -- Bereichsleiste (20) bleibt darueber,
   Vollbild-Player (100, position: fixed; inset: 0) deckt beide
   vollstaendig ab. Gleicher Untergrund/Rand/Padding wie .kopf, damit
   beide festen Kopf-Zonen wie eine Sache aussehen, nicht wie zwei. */
.kopfzeile {
  position: sticky;
  top: 0;
  z-index: 10;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--abstand-4);
  /* Bisher kam die Hoehe immer indirekt vom Kind (.zurueck/
     .bearbeiten-knopf, je min-height: 44px) -- auf Seiten OHNE
     Zurueck-Knopf (PLAN-profil.md-Nachbarschaft: Vokabulare/
     Mitglieder, Timm 2026-08-05) bliebe die Zeile sonst niedriger
     als die in --kopfzeile-hoehe angenommenen 44px, und der darunter
     sticky .titel-klebt saesse zu hoch/ueberlappend. */
  min-height: 44px;
  padding: max(env(safe-area-inset-top, 0px), 0.75rem) 0.75rem 0.5rem;
  background: var(--bereich-aktiv-bg, var(--kopf-bg));
  border-bottom: var(--rahmen-fein) solid var(--rand);
}

/* Auftrag "Titel klebt unter der Navigationszeile": .titel-waechter
   ist ein 0px hohes Marker-Element VOR dem Titel im Dokument (siehe
   Templates), beobachtet von titel_klebt.js per IntersectionObserver.
   Entscheidend ist die Reihenfolge: der Waechter steht VOR dem Titel,
   das Schrumpfen des Titels verschiebt also nur Inhalt NACH dem
   Waechter, nie ihn selbst. Wuerde der Waechter stattdessen NACH dem
   Titel stehen, wuerde ihn das Schrumpfen zurueck in den sichtbaren
   Bereich schieben -- der Beobachter meldet "nicht mehr geklebt", der
   Titel waechst wieder, schiebt den Waechter erneut hinaus, und so
   weiter: eine Endlosschleife genau an der Umschaltgrenze. Mit dieser
   Reihenfolge kann das strukturell nicht auftreten, kein Entprellen
   noetig. margin:0 auf .titel-klebt (statt .move-titels eigenem
   margin-top), damit keine Rand-Verschmelzung eine Luecke zwischen
   Waechter-Unterkante und Titel-Oberkante oeffnet. */
.titel-waechter {
  height: 0;
}

/* position: sticky direkt unter der ebenfalls sticky .kopfzeile
   (top: --kopfzeile-hoehe, siehe deren Definition weiter oben --
   rein rechnerisch, kein JS noetig, damit das Kleben selbst auch ganz
   ohne JavaScript funktioniert). z-index: 10, dieselbe Ebene wie
   .kopf/.kopfzeile -- Vollbild-Player (100) deckt weiterhin beides ab.
   Vertikaler Abstand als PADDING statt margin (anders als die
   .move-titel-Basisregel): nur so gehoert der Abstand zur eigenen
   Hintergrundflaeche und wird von der Bereichsfarbe mit eingefaerbt --
   mit margin bliebe darueber/darunter ein Streifen in --bg stehen. */
.titel-klebt {
  position: sticky;
  top: var(--kopfzeile-hoehe);
  z-index: 10;
  margin: 0;
  /* Kein margin-bottom hier drin: das wuerde noch zur farbigen Flaeche
     gehoeren. Der Abstand zum folgenden Inhalt steht bewusst AUSSEN
     als eigene Regel weiter unten (.titel-klebt + *) -- sonst stiesse
     z.B. das runde Personen-Foto direkt an die Titelkante (Auftrag
     "Designaspekte pruefen", gedrungene Wirkung bemerkt). margin-top
     bleibt 0: der Waechter (.titel-waechter) davor braucht die exakte
     Anschlusskante, siehe dessen Kommentar. */
  /* Symmetrisch seit 2026-08-04: vorher 0.25/0.75 -- der Text sass
     dadurch sichtbar oberhalb der Mitte der farbigen Flaeche (Timm
     auf dem iPhone aufgefallen). Gesamthoehe unveraendert 1rem. */
  padding-top: 0.5rem;
  padding-bottom: 0.5rem;
  transition: font-size 0.15s ease, line-height 0.15s ease;
}
/* Titel OHNE Kopfzeile darueber (Vokabulare/Mitglieder, Timm
   2026-08-05, zweite Runde): das leere .kopfzeile-Band davor sah nach
   fehlendem Inhalt aus -- der Titel steht jetzt selbst ganz oben und
   klebt bei top: 0 statt unter der Kopfzeile. padding-top uebernimmt
   die safe-area-Behandlung, die sonst die Kopfzeile leistet (iPhone-
   Kerbe), mit dem Basis-0.5rem als Untergrenze. */
.titel-klebt--oben {
  top: 0;
  padding-top: max(env(safe-area-inset-top, 0px), 0.5rem);
}
/* Abstand NACH dem Titelfeld, fuer jede Detailseite gleich -- vorher
   0, dadurch stiess der jeweils erste Inhalt (z.B. das runde Foto auf
   der Personenseite) direkt an die farbige Kante. */
.titel-klebt + * {
  margin-top: 0.75rem;
}
.titel-klebt.ist-geschrumpft {
  font-size: var(--schriftgrad-basis);
  line-height: 1.25;
}
@media (prefers-reduced-motion: reduce) {
  /* Erste Verwendung von prefers-reduced-motion im Projekt: die
     Groessenaenderung selbst bleibt (sie transportiert Information --
     "jetzt klebt der Titel"), nur der Uebergang dahin entfaellt. */
  .titel-klebt {
    transition: none;
  }
}

/* Auftrag "Titelfeld je Bereich einfaerben": eine Klasse je Bereich,
   wie .kachelzeile--familie/--stil/--status/--art es vormacht -- die
   Bereichszuordnung selbst steht in jedem Template genau einmal
   ({% set bereich = "..." %}), nicht zehnfach als Farbwert verstreut. */
.titel-bereich--moves { background: var(--titel-moves-bg); }
.titel-bereich--personen { background: var(--titel-personen-bg); }
.titel-bereich--quellen { background: var(--titel-quellen-bg); }
.titel-bereich--uebungseinheiten { background: var(--titel-uebungseinheiten-bg); }
.titel-bereich--technik { background: var(--titel-technik-bg); }
.titel-bereich--ressourcen { background: var(--titel-ressourcen-bg); }
.titel-bereich--notizen { background: var(--titel-notizen-bg); }
.titel-bereich--musik { background: var(--titel-musik-bg); }
.titel-bereich--choreografien { background: var(--titel-choreografien-bg); }

/* Setzt nur die Custom Property --bereich-aktiv-bg (siehe .kopf weiter
   oben) -- eine Klasse pro Bereich, wiederverwendbar fuer .kopf,
   .kopfzeile UND .bereichsleiste/.bereichsraster gleichzeitig, egal
   auf welchem der drei Elemente sie steht. */
.bereich-farbe--moves { --bereich-aktiv-bg: var(--bereich-moves-bg); }
.bereich-farbe--personen { --bereich-aktiv-bg: var(--bereich-personen-bg); }
.bereich-farbe--quellen { --bereich-aktiv-bg: var(--bereich-quellen-bg); }
.bereich-farbe--uebungseinheiten { --bereich-aktiv-bg: var(--bereich-uebungseinheiten-bg); }
.bereich-farbe--technik { --bereich-aktiv-bg: var(--bereich-technik-bg); }
.bereich-farbe--ressourcen { --bereich-aktiv-bg: var(--bereich-ressourcen-bg); }
.bereich-farbe--notizen { --bereich-aktiv-bg: var(--bereich-notizen-bg); }
.bereich-farbe--musik { --bereich-aktiv-bg: var(--bereich-musik-bg); }
.bereich-farbe--choreografien { --bereich-aktiv-bg: var(--bereich-choreografien-bg); }

/* Signature-Kennzeichnung (eigener Platz statt im Uebungsstatus-Block,
   siehe Konsistenz-Runde): Herz-Glyphe statt reiner Farbe, damit die
   Bedeutung nicht von Farbsehen abhaengt. Gleiche Stelle in Titelzeile,
   Trefferliste UND als eigene Kachel im Bearbeiten-Formular. */
.signatur-herz { color: var(--signatur); }

/* Fuss- und Lupen-Symbol (fuss_icon()/lupe_icon()): die SVGs brauchen
   eine explizite Groesse, anders als ♥/★/✓/●/○/◐, die als Text mit dem
   umgebenden Schriftgrad mitskalieren. 1em/1em plus ein Versatz nach
   unten setzt sie auf dieselbe Grundlinie wie die Textzeichen daneben
   -- kein eigenes color, sie erben die Textfarbe wie alle anderen
   Symbole in der Zeile. (Die Lupe ersetzt seit 2026-08-03 das
   🔍-Emoji, das letzte im Vokabular -- Begruendung bei lupe_icon()
   in _kontakt_icons.html.) */
.fuss-symbol,
.lupe-symbol,
.daumen-symbol {
  width: 1em;
  height: 1em;
  vertical-align: -0.15em;
}

/* Uebungsstatus-Symbole (Auftrag "Ampelfarben"): Fortschrittsfarben
   fuer die drei aktiven Zustaende, ein neutraler Grauton fuer den
   Ausstieg -- bewusst KEINE Rot-Gelb-Gruen-Ampel. "Zurückgestellt"
   ist absichtlich neutral benannt (nicht "Will ich nicht"); ihn rot
   einzufaerben naehme das zurueck. Alle vier Variablen bestehen
   schon (--akzent-*, --gedaempft), keine neue Farbe.
   Kontrast gegen --bg, beide Farbschemata, > 3:1-Schwelle fuer
   grafische Zeichen (03.08.2026 gemessen, siehe richte_uebungsstatus_
   symbole_ein.py fuer die Einzelwerte):
     status-symbol--vormerken      7,09:1 hell / 7,90:1 dunkel
     status-symbol--uebe           5,42:1 hell / 5,60:1 dunkel
     status-symbol--kann           4,54:1 hell / 7,72:1 dunkel
     status-symbol--zurueckgestellt 4,54:1 hell / 6,58:1 dunkel
       (hell seit --gedaempft #767676 am 2026-08-03; vorher 3,54)
   Farbe ist Zugabe, nicht das Signal -- ◇ ◐ ✓ ○ unterscheiden sich
   schon durch die Form, auch ohne Farbsehen. */
.status-symbol--vormerken { color: var(--akzent-status-bg); }
.status-symbol--uebe { color: var(--akzent-familie-bg); }
.status-symbol--kann { color: var(--akzent-stil-bg); }
.status-symbol--zurueckgestellt { color: var(--gedaempft); }
.kachel--signatur:has(input:checked) { color: var(--signatur); }
/* Angeglichen an .zurueck, seinen Nachbarn in derselben .kopfzeile,
   und an die untere Navigation (Timm-Befund 2026-08-05): vorher
   color: inherit + font-weight 400 (Browser-Standard) + kleinerer
   Schriftgrad -- neben dem fetten, farbigen .zurueck wirkte
   "Bearbeiten" dadurch wie ein anderes, schwaecheres Element, obwohl
   beide dieselbe Handlungsebene sind (ein Knopf oben in der
   Kopfzeile). font-weight: 600 ist die durchgehende Knopf-Regel im
   Projekt (.such-link, .bereichsleiste summary, .zurueck) --
   .bearbeiten-knopf war die einzige Ausnahme. Farbe/Groesse jetzt
   identisch zu .zurueck (--kachel-aktiv-bg auf --kachel-bg, dort
   bereits gemessen: 4,74:1 hell / 4,70:1 dunkel, ueber WCAG AA) --
   dieselben zwei Design-Variablen wie ueberall, passt sich also
   automatisch jeder Palette/jedem eigenen Design an. */
.bearbeiten-knopf {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  min-height: 44px; /* Apples eigener Mindest-Tippbereich, wie .kachel */
  margin-right: 0.75rem; /* gleicher Randabstand wie vorher durch .titelzeile-Padding */
  padding: 0 0.8rem;
  border-radius: var(--radius-pille);
  background: var(--kachel-bg);
  color: var(--kachel-aktiv-bg);
  font-weight: 600;
  text-decoration: none;
  font-size: var(--schriftgrad-kompakt);
}

.bearbeiten-formular { padding-bottom: 2rem; }

.feld-label {
  display: block;
  font-size: var(--schriftgrad-klein);
  font-weight: 600;
  color: var(--gedaempft);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin: 1rem 0 0.35rem;
}
.feld-label:first-of-type { margin-top: 0; }

/* date/number/select standen bis 2026-08-03 NICHT in dieser Liste --
   die Achsenfelder vom Typ 'datum'/'zahl'/'geld' und das
   Auswahlfeld in choreografie_bearbeiten.html trugen deshalb die
   Browser-Vorgabe: kleinere Schrift (iOS zoomt beim Antippen hinein,
   genau was die 16px verhindern sollen) und weniger als 44px Hoehe.
   Aufgefallen beim Einbau von "Gehört zu"; hier mitkorrigiert statt
   fuer das neue Feld eine zweite Regel danebenzustellen. email/
   password kamen 2026-08-04 mit der Anmeldeseite dazu (PLAN-anmeldung.md
   E2) -- gleicher Fehlertyp, gleich mitkorrigiert. url/file kamen
   2026-08-05 mit medium_neu.html dazu (PLAN-video-upload.md V1b,
   Punkt 4, Timms Fund "viele unterschiedliche Größen") -- derselbe
   wiederkehrende Fehlertyp: ein neuer input-Typ, dieselbe fehlende
   Zeile. Diese Liste ist die einzige Stelle, die ein neuer Typ
   braucht, kein Duplikat je Formular. */
.bearbeiten-formular input[type="text"],
.bearbeiten-formular input[type="date"],
.bearbeiten-formular input[type="number"],
.bearbeiten-formular input[type="email"],
.bearbeiten-formular input[type="password"],
.bearbeiten-formular input[type="url"],
.bearbeiten-formular input[type="file"],
.bearbeiten-formular select,
.bearbeiten-formular textarea {
  width: 100%;
  min-height: 44px;
  font-size: var(--schriftgrad-basis); /* verhindert iOS-Zoom beim Antippen */
  padding: 0.6rem 0.8rem;
  border-radius: var(--radius-flaeche);
  border: var(--rahmen-fein) solid var(--rand);
  background: var(--bg);
  color: var(--fg);
  font-family: inherit;
}
.bearbeiten-formular textarea { resize: vertical; }

/* Gruppierte Achsen im Bearbeiten-Formular (Achsen-Gruppierung,
   2026-08): jede feld_definition.gruppe erscheint als eigener,
   abgegrenzter Block statt lose zwischen den uebrigen Achsen zu
   stehen -- generisch fuer jede Gruppe, nicht nur Kosten. Nur
   bestehende Farb-Tokens (--rand/--gedaempft), keine neue Farbe, kein
   neuer Kontrast-Nachweis noetig. */
.achsen-gruppe {
  margin-top: 1rem;
  padding: 0.8rem;
  border: var(--rahmen-fein) solid var(--rand);
  border-radius: var(--radius-flaeche);
}
.achsen-gruppe .filter-titel:first-child { margin-top: 0; }

/* Berechnete Ergebniszeilen am Ende einer Gruppe (Auftrag: "keine
   Achsen, haengen als Ergebniszeilen unten an den Block an") -- eine
   Trennlinie vor dem ganzen Summen-Block, nicht vor jeder einzelnen
   Zeile. Gilt gleichermassen in der Ansicht (innerhalb des
   <details>-Abschnitts einer Gruppe) und im Bearbeiten-Formular
   (innerhalb .achsen-gruppe). */
.achsen-gruppe-summen {
  margin-top: 0.5rem;
  padding-top: 0.5rem;
  border-top: var(--rahmen-fein) solid var(--rand);
}
.achsen-gruppe-summe {
  display: flex;
  justify-content: space-between;
  gap: var(--abstand-3);
  font-weight: 600;
}
.achsen-gruppe-summe + .achsen-gruppe-summe { margin-top: 0.15rem; }

/* Ansicht: beide Summen in EINER Zeile statt gestapelt (Auftrag "Die
   beiden Summen in eine Zeile") -- eigene Klasse, damit das
   Bearbeiten-Formular (.achsen-gruppe-summe oben) unveraendert
   gestapelt bleibt. flex-wrap statt nowrap auf der ganzen Zeile: bei
   375px passen beide Beschriftung/Wert-Paare oft nicht nebeneinander,
   die Zeile bricht dann sauber um (OBERFLAECHE.md, nie kuerzen) --
   .summe-paar selbst bleibt nowrap, damit "Gesamtkosten 587,54 €"
   nicht mitten im Paar umbricht. */
.achsen-gruppe-summenzeile {
  margin-top: 0.5rem;
  padding-top: 0.5rem;
  border-top: var(--rahmen-fein) solid var(--rand);
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--abstand-3);
  font-weight: 600;
}
.summe-paar { display: inline-flex; gap: var(--abstand-2); white-space: nowrap; }
.summe-trenner { color: var(--gedaempft); font-weight: 400; }

/* Sichtbares "€" am Geldfeld (Auftrag "Waehrungsachse wieder
   entfernen", Punkt 3) -- Ersatz fuer die entfernte waehrung-Achse,
   zeigt beim Eintippen, welche Waehrung erwartet wird. --gedaempft
   ist bereits gegen --bg geprueft (siehe .eintrag-neben). */
/* flex (nicht inline-flex) mit voller Zeilenbreite: seit dem
   "÷ N"-Teiler (PLAN-kostenblock.md) stehen drei Teile in der Zeile
   (Betrag, Euro-Zeichen, Teiler) -- als inline-flex mit width:auto
   ragte die Gruppe auf dem iPhone ueber den Rahmen hinaus (Timms
   Fund 2026-08-04). Jetzt schrumpft der BETRAG (flex:1 + min-width),
   der Teiler bleibt fest, nichts steht ueber. */
.geld-eingabe { display: flex; align-items: center; gap: var(--abstand-3); max-width: 100%; }
/* Ausnahme von der width:100%-Regel oben: volle Breite wuerde das
   Euro-Zeichen und den Teiler hinausdruecken. Schriftgroesse und
   Hoehe gelten weiter. */
.geld-eingabe input[type="number"] { width: auto; flex: 1 1 auto; min-width: 0; }
.geld-eingabe .kosten-teiler { flex: 0 0 auto; }
/* Der Teiler bleibt ein schmales Feld -- die Formular-Basisregeln
   wuerden ihn sonst auf Betragsbreite ziehen (hier gezielt
   spezifischer ueberschrieben statt per Reihenfolge zu hoffen). */
.geld-eingabe .kosten-teiler input[type="number"] { width: 3.5rem; flex: 0 0 auto; }
.geld-eingabe span { color: var(--gedaempft); font-size: var(--schriftgrad-basis); }

.vorschlag-box {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--abstand-4);
  margin-top: 0.75rem;
  padding: 0.6rem 0.8rem;
  border-radius: var(--radius-flaeche);
  background: var(--marke-bg);
  font-size: var(--schriftgrad-neben);
}
.vorschlag-box p { margin: 0; }
.uebernehmen-knopf {
  flex: 0 0 auto;
  min-height: 44px; /* Apples eigener Mindest-Tippbereich, wie .kachel */
  padding: 0 0.8rem;
  border: none;
  border-radius: var(--radius-pille);
  background: var(--kachel-aktiv-bg);
  color: var(--kachel-aktiv-fg);
  font-size: var(--schriftgrad-neben);
  font-family: inherit;
}

/* rollen-liste: senkrechte Variante von .kachel fuer Optionen mit
   einem ganzen Satz Erklaerung -- .kachel selbst ist fuer kurze,
   einzeilige Chips gebaut (white-space:nowrap, Pillenform), das
   passt bei "Hat die Figur erfunden oder ihr den Namen gegeben"
   nicht mehr. Gleiches :has(input:checked)-Muster wie ueberall
   sonst, kein JavaScript fuer die Markierung noetig. */
.rollen-liste {
  display: flex;
  flex-direction: column;
  gap: var(--abstand-3);
  margin-top: 0.5rem;
}
.rollen-option {
  display: flex;
  align-items: flex-start;
  gap: var(--abstand-4);
  min-height: 44px;
  padding: 0.65rem 0.9rem;
  border-radius: var(--radius-flaeche);
  background: var(--kachel-bg);
  cursor: pointer;
}
.rollen-option input {
  margin-top: 0.2rem;
  flex-shrink: 0;
  width: 20px;
  height: 20px;
}
.rollen-option:has(input:checked) {
  background: var(--kachel-aktiv-bg);
  color: var(--kachel-aktiv-fg);
}
.rollen-option:has(input:checked) .eintrag-neben { color: inherit; opacity: 0.85; }

/* aehnlich-warnung: dieselbe Sprache wie .vorschlag-box (auffaellig,
   aber kein Fehler-Rot -- es ist eine Nachfrage, kein Problem), nur
   mit Platz fuer eine ganze Trefferliste statt eines einzelnen
   Uebernehmen-Knopfs. */
.aehnlich-warnung {
  margin: 0.75rem 0;
  padding: 0.6rem 0.8rem;
  border-radius: var(--radius-flaeche);
  background: var(--marke-bg);
}
.aehnlich-warnung > p:first-child { margin-top: 0; font-size: var(--schriftgrad-neben); }

/* ---------------------------------------------------------------
   Auswertungen (PLAN-auswertungen.md A1ff.): Bausteine fuer alle
   Bloecke -- Balken als CSS-Breiten, Torten als SVG (siehe
   web/diagramme.py), beides ohne JavaScript. Farben ausschliesslich
   ueber --diagramm-1..6 (oben in :root definiert) bzw. bestehende
   Tokens, siehe Entscheidung 3/4 im Plan.
   --------------------------------------------------------------- */

/* Zeitraum-Formular (Entscheidung 7, ?von_jahr=&bis_jahr=): zwei
   Auswahllisten + Knopf in einer Zeile, faellt auf schmalen Schirmen
   um (flex-wrap). Zahlenfelder wurden zu <select> (A7 Punkt 2) --
   .bearbeiten-formular auf dem Formular selbst liefert die 16px/44px-
   Regel dafuer (stil.css ~3040), hier nur noch das Zeilen-Layout und
   der Abstand zum Kopf (A7 Punkt 2: "wie zwischen den Abschnitten",
   selber Wert wie .abschnitt-inhalt .auswertung-block + .auswertung-
   block weiter unten). */
.auswertungen-zeitraum {
  display: flex;
  align-items: flex-end;
  gap: var(--abstand-3);
  flex-wrap: wrap;
  margin-top: var(--abstand-6);
  margin-bottom: 1rem;
}
.auswertungen-zeitraum label {
  display: flex;
  flex-direction: column;
  gap: var(--abstand-1);
  font-size: var(--schriftgrad-klein);
  color: var(--gedaempft);
}
.auswertungen-zeitraum select { width: auto; min-width: 7rem; }

/* Block-Kopf: Titel links, Ausblenden-Knopf rechts -- .mini-knopf
   ist sonst immer volle Breite (die uebliche Zeilen-Aktion), hier
   ausdruecklich schmal neben dem Titel. */
.auswertung-block-kopf {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--abstand-3);
  margin-bottom: 0.5rem;
}
.auswertung-block-kopf h2 { margin: 0; }
.auswertung-block-kopf form { flex: 0 0 auto; }
/* Oberkategorien (PLAN-auswertungen.md A6, Punkt 1): mehrere Bloecke
   stehen jetzt als Geschwister in EINEM .abschnitt-inhalt (statt wie
   vorher als eigene .inhalt-Divs auf oberster Ebene) -- .inhalt faellt
   deshalb bewusst weg (sonst doppeltes Seitenpolster, .abschnitte
   details traegt das schon), stattdessen eine Trennlinie + Abstand
   zwischen aufeinanderfolgenden Bloecken, damit "kein Block mehr
   direkt an den Nachbarblock grenzt" (Timms Befund). Der erste Block
   je Abschnitt bleibt ohne Linie/oberen Abstand -- die summary
   darueber trennt schon genug. */
.abschnitt-inhalt .auswertung-block + .auswertung-block {
  margin-top: var(--abstand-6);
  padding-top: var(--abstand-6);
  border-top: var(--rahmen-fein) solid var(--rand);
}

/* Ausgeblendete Bloecke in ihrer Kategorie (A7 Punkt 9): eine
   einzeilige Zeile statt eines eigenen Sammelblocks unten -- gleiches
   Zeilen-Layout wie .auswertung-block-kopf (Titel links, Knopf
   rechts), gedaempfter Text macht den Ruhezustand ("nichts zu sehen
   hier") auf den ersten Blick von einem echten Block unterscheidbar. */
.auswertung-block--ausgeblendet {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--abstand-3);
}
.auswertung-block--ausgeblendet .name { color: var(--gedaempft); font-weight: 400; }
.auswertung-block--ausgeblendet form { flex: 0 0 auto; }
/* Wiederverwendbar ueberall, wo ein .mini-knopf NICHT die uebliche
   volle Zeilenbreite haben soll (Block-Kopf-Ausblenden-Knopf,
   Zeitraum-Anwenden-Knopf). */
.mini-knopf--auto { width: auto; padding: 0 0.8rem; }

/* Balken: Beschriftung links (Jahr/Monat/Posten), Leiste in der
   Mitte, Zahl rechts -- eine Zeile je Wert, .balken-fuellung als
   Breite in % vom Template gesetzt (style="width:..."). 1px
   --rand-Kontur an der Fuellung (Entscheidung 3), damit auch
   aehnliche Diagrammtoene gegen die Leiste UND gegeneinander (bei
   gestapelten Balken, A2) erkennbar bleiben. */
.balkenreihe {
  display: flex;
  flex-direction: column;
  gap: var(--abstand-2);
}
.balken-zeile {
  display: flex;
  align-items: center;
  gap: var(--abstand-3);
}
.balken-beschriftung {
  flex: 0 0 3.75rem;
  font-size: var(--schriftgrad-neben);
  color: var(--gedaempft);
  text-align: right;
}
.balken-leiste {
  flex: 1;
  min-width: 0;
  height: 1.1rem;
  background: var(--kachel-bg);
  border-radius: var(--radius-klein);
  overflow: hidden;
  /* Gestapelte Balken (A2): mehrere .balken-fuellung nebeneinander
     statt einer -- flex sorgt dafuer, dass jeder Posten genau seinen
     eigenen Breitenanteil bekommt, ohne dass die Reihenfolge im
     Markup etwas am Ergebnis aendert. */
  display: flex;
}
.balken-fuellung {
  display: block;
  height: 100%;
  border: var(--rahmen-fein) solid var(--rand);
  box-sizing: border-box;
}
.balken-zahl {
  flex: 0 0 auto;
  min-width: 1.75rem;
  font-weight: 600;
  font-size: var(--schriftgrad-neben);
  text-align: right;
}

/* Torte: SVG-Kreis (Segmente aus web/diagramme.py) plus Legende
   darunter -- die Legende traegt Zahl+Text (Entscheidung 4: nie Text
   auf der Flaeche selbst). Mehrere Torten nebeneinander (Multiuser,
   Entscheidung 8) ueber .torten-nebeneinander. */
.torte-svg {
  display: block;
  width: 100%;
  max-width: 180px;
  height: auto;
  margin: 0 auto;
}
.torte-svg path,
.torte-svg circle {
  stroke: var(--rand);
  stroke-width: 1;
}
.torte-legende {
  display: flex;
  flex-direction: column;
  gap: var(--abstand-2);
  margin-top: 0.75rem;
  list-style: none;
  padding: 0;
}
.torte-legende li a,
.torte-legende li span.torte-legende-zeile {
  display: flex;
  align-items: center;
  gap: var(--abstand-2);
  color: inherit;
  text-decoration: none;
}
.torte-farbpunkt {
  width: 0.9rem;
  height: 0.9rem;
  border-radius: 50%;
  border: var(--rahmen-fein) solid var(--rand);
  flex: 0 0 auto;
}
.torte-legende-text { flex: 1; }
.torte-legende-zahl { font-weight: 600; }

.torten-nebeneinander {
  display: flex;
  gap: var(--abstand-4);
  flex-wrap: wrap;
}
.torten-nebeneinander > div {
  flex: 1 1 140px;
  min-width: 140px;
}

/* Zeitleiste (A4, IDEEN 11, der Ninox-Ersatz): Jahres-Spalten
   nebeneinander, jede Spalte fuer sich senkrecht scrollend (max-height
   + overflow-y), die SPALTEN-REIHE horizontal scrollend im eigenen
   Container -- Entscheidung im Plan: "Spalten scrollen horizontal im
   eigenen Container, die Seite selbst nie". overflow-x auto + eigener
   Rand verhindert, dass die ganze Seite seitlich wandert. */
.zeitleiste-spalten {
  display: flex;
  /* A6, Punkt 5 (entzerren): abstand-6 statt abstand-4 -- Timms Befund
     "Kachelhaufen" kam auch von Spalten, die fast ineinander liefen. */
  gap: var(--abstand-6);
  overflow-x: auto;
  padding-bottom: 0.5rem;
  margin: 0 -0.25rem;
  padding-left: 0.25rem;
  padding-right: 0.25rem;
}
.zeitleiste-spalte {
  /* Mindest-Spaltenbreite angehoben (220px -> 240px A6, -> 280px A7
     Punkt 3, Timms Fund "die Kartengroesse erstickt die Teacher-Fotos"):
     die groesseren Avatare unten (.zeitleiste-karte .avatar-klein)
     brauchen mehr Platz in der Zeile, sonst wird sofort umgebrochen. */
  flex: 0 0 280px;
  display: flex;
  flex-direction: column;
  gap: var(--abstand-4);
  max-height: 32rem;
  overflow-y: auto;
  /* Die "echte senkrechte Achsenlinie" (A6, Punkt 5): eine durchgehende
     Randlinie links der ganzen Spalte, Karten UND Monats-Marken ruecken
     mit padding-left davon ab -- liest sich als eine Zeitachse, an der
     die Karten haengen, nicht als loser Stapel. */
  border-left: var(--rahmen-stark) solid var(--rand);
  padding-left: var(--abstand-3);
}
.zeitleiste-spalte-titel {
  position: sticky;
  top: 0;
  background: var(--bg);
  margin: 0;
  padding-bottom: 0.35rem;
  /* Seit A6 auch als <a> im Einsatz (Jahres-Spalten fuehren jetzt zum
     gefilterten /quellen-Ergebnis) -- ohne diese zwei Zeilen saehe der
     Linktitel anders aus als "Geplant"/"Ohne Datum" (bleiben <p>). */
  display: block;
  color: inherit;
  text-decoration: none;
}
/* Monats-Marke (A6, Punkt 5): kein eigener Balken, nur eine kleine,
   gedaempfte Beschriftung an der Achsenlinie -- sie MARKIERT einen
   Zeitpunkt, sie ist keine weitere Karte. */
.zeitleiste-monat-marke {
  margin: 0.2rem 0 0;
  font-size: var(--schriftgrad-klein);
  font-weight: 600;
  color: var(--gedaempft);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.zeitleiste-karte {
  display: block;
  /* Mehr Karten-Innenabstand (0.6/0.7rem -> 0.85/0.9rem, A6 Punkt 5). */
  padding: 0.85rem 0.9rem;
  min-height: 44px;
  border: var(--rahmen-fein) solid var(--rand);
  border-radius: var(--radius-flaeche);
  background: var(--kachel-bg);
  color: inherit;
  text-decoration: none;
}
.zeitleiste-karte .name { font-size: var(--schriftgrad-neben); }
/* Teacher-Miniaturfotos groesser (A7 Punkt 3, ECHTER Timm-Befund: "die
   Fotos sind schon da, die Kartengroesse erstickt sie") -- scoped auf
   die Zeitleiste-Karte, .avatar-klein bleibt ueberall sonst bei 28px
   (Lehrende-Liste, Steckbrief-Zeilen), keine globale Aenderung noetig. */
.zeitleiste-karte .avatar-klein { width: 40px; height: 40px; }
.zeitleiste-karte .avatar-klein.avatar-platzhalter { font-size: 0.85rem; }

/* Streudarstellung (A5, IDEEN 4, Block 'rating-kosten'): einfache
   SVG-Punkte, keine Achsenlinien (die Zahlen darunter/in der Liste
   tragen die eigentliche Information, Entscheidung 4 -- die Flaeche
   selbst zeigt nur die Verteilung). */
.streu-svg {
  display: block;
  width: 100%;
  max-width: 320px;
  height: auto;
  margin: 0 auto;
}
.streu-svg circle {
  fill: var(--diagramm-1);
  stroke: var(--rand);
  stroke-width: 1;
}

/* Uebungs-Kalender (A5, IDEEN 10): 12 Monatskarten nebeneinander
   (flex-wrap, kein horizontales Zwangs-Scrollen wie bei der Zeitleiste
   -- ein Monatsraster ist schmal genug, um umzubrechen). Jede Karte
   ein 7-spaltiges Wochenraster, leere Zellen (Tage ausserhalb des
   Monats) unsichtbar aber platzhaltend, damit die Wochentage
   spaltentreu bleiben. */
.monatsraster-monate {
  display: flex;
  flex-wrap: wrap;
  gap: var(--abstand-4);
}
.monat-karte { flex: 0 0 auto; }
.monat-titel { margin-bottom: 0.35rem; }
.monat-woche {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 2px;
  margin-bottom: 2px;
}
.monat-tag {
  width: 16px;
  height: 16px;
  border-radius: var(--radius-klein);
  background: var(--kachel-bg);
  border: var(--rahmen-fein) solid var(--rand);
  box-sizing: border-box;
}
.monat-tag--leer { background: none; border-color: transparent; }
.monat-tag--geuebt { background: var(--diagramm-2); }
.monat-tag--gemeinsam { background: var(--diagramm-1); }
/* Geplant (L1, PLAN-lerncenter.md): dritte Kategorie, bestehende
   Diagrammfarbe wiederverwendet (kein neues Farb-Literal). Nur
   gesetzt, wenn der Tag NICHT schon geuebt ist (app.py _monatsraster) --
   ein erfuellter Termin zeigt den geuebt-Zustand, nicht beides. */
.monat-tag--geplant { background: var(--diagramm-3); }

/* Kalender-Legende (A7 Punkt 8, PLAN-auswertungen.md): die Tage
   trugen bisher NUR Farbe -- gegen "Farbe nie einziges Signal"
   (OBERFLAECHE.md). Text neben jedem Muster macht den Unterschied
   auch ohne Farbwahrnehmung nachvollziehbar; erscheint nur bei mehr
   als einem Mitglied eine zweite Zeile (Gemeinsam geuebt). */
.monat-legende {
  display: flex;
  flex-wrap: wrap;
  gap: var(--abstand-4);
  list-style: none;
  margin: 0 0 var(--abstand-3);
  padding: 0;
  font-size: var(--schriftgrad-neben);
  color: var(--gedaempft);
}
.monat-legende li {
  display: flex;
  align-items: center;
  gap: var(--abstand-1);
}
.monat-legende .monat-tag { flex: 0 0 auto; }

/* Lernkarte (L2, PLAN-lerncenter.md): eine Karte je Seite, deshalb
   darf der Name gross stehen -- er IST die Vorderseite, nicht eine
   Zeile unter vielen. Flaeche und Kontur wie jede andere Kachel
   (--kachel-bg/--rand), kein eigenes Farbwerk. */
.lernkarte {
  background: var(--kachel-bg);
  border: var(--rahmen-fein) solid var(--rand);
  border-radius: var(--radius-flaeche);
  padding: var(--abstand-5);
  margin-bottom: var(--abstand-5);
}
.lernkarte-name {
  margin: 0 0 var(--abstand-2);
  font-size: var(--schriftgrad-zwischentitel);
  font-weight: 600;
}
.lernkarte-rueckseite { margin-top: var(--abstand-5); }
.lernkarte-beschreibung { white-space: pre-wrap; }
/* Beide Bewertungen gleich breit nebeneinander: keine der beiden
   Antworten ist die "richtige", also bekommt auch keine mehr
   Gewicht (gleiches Prinzip wie die Ja/Nein-Kachelzeilen sonst). */
.lernkarte-bewertung {
  display: flex;
  gap: var(--abstand-3);
  margin-top: var(--abstand-5);
}
.lernkarte-bewertung form { flex: 1 1 0; margin: 0; }
.lernkarte-bewertung .suchknopf { width: 100%; }

/* Reise (A5, IDEEN 12, Kuer): senkrechte Linie links (Rand-Farbe,
   dieselbe Kontur wie ueberall), Eintraege als normale .treffer-
   Zeilen daneben -- kein neues Zeilenmuster, nur der Linien-Akzent. */
.reise-zeitleiste {
  list-style: none;
  margin: 0;
  padding: 0;
  border-left: calc(var(--rahmen-fein) * 2) solid var(--rand);
}
.reise-eintrag { margin-left: -1px; padding-left: 0.9rem; }
.reise-eintrag a {
  display: block;
  padding: 0.5rem 0.25rem;
  min-height: 44px;
  color: inherit;
  text-decoration: none;
}
.reise-eintrag:not(:last-child) { border-bottom: var(--rahmen-fein) solid var(--rand); }

/* Ausgeblendete Bloecke: eingeklappt am Seitenende (Entscheidung 2),
   gleiches Zeilenmuster wie ueberall (.eintragsliste), nur mit einem
   Einblenden-Knopf statt eines Links. */
.ausgeblendete-bloecke summary {
  cursor: pointer;
  font-weight: 600;
  padding: 0.5rem 0;
}

/* Figuren-Trainer, Lauf-Buehne (PLAN-trainer.md T1): eigener dunkler
   Grund unabhaengig vom Design/Hell-Dunkel-Modus (wie das
   F2-Bild-Overlay, .bild-gross-overlay/-schliessen -- schwarz und
   weiss brauchen keine Kontrastpruefung, das ist der Extremfall).
   Die "5 Farbtoene je Figur" (Plan-Vorgabe) sind KEINE reinen
   Diagrammfarben, sondern per JS zu 30% in Schwarz gemischt
   (color-mix(in srgb, var(--diagramm-N) 30%, black), trainer_lauf.js)
   -- weisser Text bleibt so in allen sieben Designs weit ueber WCAG AA
   (nachgemessen: schlechtester Fall neon/akzent-familie-bg 10,2:1,
   staerkster moeglicher Diagrammton; kein Design faellt darunter). */
.trainer-buehne {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--abstand-4);
  padding: var(--abstand-4);
  color: #fff;
  text-align: center;
  background: #000;
}
.trainer-beenden-knopf {
  position: absolute;
  top: var(--abstand-3);
  right: var(--abstand-3);
  min-width: 44px;
  min-height: 44px;
  padding: 0 1rem;
  border-radius: var(--radius-flaeche);
  border: var(--rahmen-fein) solid rgba(255, 255, 255, 0.4);
  background: rgba(255, 255, 255, 0.15);
  color: #fff;
  font-family: inherit;
  font-size: var(--schriftgrad-kompakt);
}
.trainer-fortschritt {
  width: min(80vw, 420px);
  height: 10px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.2);
  overflow: hidden;
}
.trainer-fortschritt-fuellung {
  height: 100%;
  width: 100%;
  background: #fff;
  transition: width 0.1s linear;
}
.trainer-figur-name {
  margin: 0;
  font-size: clamp(2rem, 10vw, 4rem);
  font-weight: 700;
  line-height: 1.1;
  transition: font-size 0.2s ease, color 0.2s ease;
}
/* Vorwarnung (Plan-Vorgabe: "faerbt sich gelb UND wird groesser") --
   Farbe ist NICHT das einzige Signal, siehe OBERFLAECHE.md: Groesse
   UND der bereits laufende Fortschrittsbalken UND der Woodblock-Ton
   (trainer_lauf.js) sind die weiteren drei Merkmale. #ffd60a auf
   Schwarz gemessen 14,9:1 (WCAG), weit ueber jeder Schwelle -- fixer
   Wert unabhaengig vom Design, weil die Buehne selbst das auch ist. */
.trainer-figur-name--warnung {
  color: #ffd60a;
  font-size: clamp(2.4rem, 12vw, 4.8rem);
}
.trainer-start {
  max-width: 32rem;
  margin: 0 auto;
  text-align: center;
}
.trainer-wake-hinweis { margin-top: var(--abstand-3); }
