﻿/* ============================================================
   ToLiDo — App-level styles
   Application-wide CSS that complements the MudBlazor theme.
   Keep component-specific styling in the component; put only
   cross-cutting, app-wide rules here (accessibility helpers,
   focus styles, skip links, etc.).
   ============================================================ */

/* ------------------------------------------------------------
   Design-Token (TO-0039)
   Die eine Stelle für alle Werte, die MudBlazor nicht kennt. Was MudBlazor
   kennt (Primärfarbe, Flächen, Textfarben), steht in ToLiDoTheme.cs und ist
   hier über die --mud-palette-*-Variablen erreichbar; alles darüber hinaus
   steht hier.

   Regel: unterhalb der Token-Blöcke steht kein Farbwert mehr in einer
   Deklaration -- weder als Hex noch als var()-Fallback. Token-Blöcke sind
   dieser hier (helles Theme) und der Block :root[data-tulidu-theme="dark"]
   direkt darunter (TO-0042, gefüllt mit TO-0044). In Kommentaren darf ein Wert selbstverständlich
   genannt werden; erlaubt ist ausserdem rgba(var(--mud-palette-...-rgb), ...) --
   dort steht keine Farbe, sondern eine Deckkraft auf einer Farbe aus dem Theme.
   Seit TO-0043 hält ein Test in TuLiDu.WebApp.Tests diese Regel nach, statt sie
   nur zu behaupten. Vor TO-0039 standen 13 fest verdrahtete
   Farben in dieser Datei, darunter fünfmal #1976d2 -- eine Kopie der
   MudBlazor-Primärfarbe, die bei jeder Änderung des Themes stillschweigend
   falsch geworden wäre -- und sechs kopierte MudBlazor-Vorgabewerte als
   var()-Fallback, die denselben Fehler gemacht hätten.

   TO-0039 hat nur die Schicht eingeführt, mit exakt den bisherigen Werten. TO-0042
   hat die drei --tulidu-due-*-Werte auf gerechnete, AA-feste Töne gehoben. Mit
   TO-0043 trägt auch das Theme eigene Farben (ToLiDoTheme.cs) -- die Token hier
   verweisen deshalb überall dorthin, wo MudBlazor die Rolle schon kennt, und
   führen nur noch das, was es dort nicht gibt: Manila, die Datenschrift, die
   Fälligkeitsleiter, die Kennzeichnungen, die Abstands- und Radienleiter.
   ------------------------------------------------------------ */
:root {
  /* Abstandsleiter, Grundeinheit 4px. Löst schrittweise die freie Mischung aus
     pa-3/pa-4/my-2/0.75rem/0.5rem quer durch die Komponenten ab. */
  --tulidu-space-1: 4px;
  --tulidu-space-2: 8px;
  --tulidu-space-3: 12px;
  --tulidu-space-4: 16px;
  --tulidu-space-5: 24px;
  --tulidu-space-6: 32px;
  --tulidu-space-7: 48px;

  /* Radien nach Rolle: Steuerelement, Karte, Chip. */
  --tulidu-radius-control: 4px;
  --tulidu-radius-card: 10px;
  --tulidu-radius-pill: 999px;

  /* Datenschrift (TO-0043): Datum, Zähler, Prozente, Versionsnummer. Die einzige
     Schriftrolle, die hier steht statt im Theme -- MudBlazor kennt keine Variante
     "Daten", also gibt es kein --mud-typography-*-family dafür. Die Liste muss zu
     ToLiDoTheme.DataFontFamily passen; ein Test prüft das (ToLiDoThemeTests). */
  --tulidu-font-data: 'IBM Plex Mono', Consolas, ui-monospace, monospace;

  /* Abgesenkte Fläche -- Statistikkacheln, Filterleisten, Vorschlagspillen: alles, was
     eine Stufe TIEFER liegt als die Karte darauf. Benannter Zugang zu MudBlazors
     BackgroundGray (= #F2F1EC seit TO-0043).

     Der Alias ist nicht Kosmetik: bis TO-0043 stand an sechzehn Stellen -- sieben hier,
     neun in Razor-Dateien -- die Variable in britischer Schreibweise, also
     background-grey. MudBlazor 9.9.0 schreibt sie aber mit "a" (nachgeprüft: in
     MudBlazor.min.css kommt "grey" kein einziges Mal vor). Die Deklarationen liefen
     damit ins Leere; wo ein Fallback danebenstand, griff der, wo keiner stand, blieb
     die Fläche durchsichtig. Ein Buchstabe, der sich nicht wiederholen soll. */
  --tulidu-surface-sunken: var(--mud-palette-background-gray);

  /* Insel-Flaeche eines Items -- der Ton, auf dem eine Zeile im Item-Baum und eine Zeile der
     flachen Listen (Home, "Mein Tag", Tag-Filter) steht. Gegenstueck zu --tulidu-item-boundary,
     das dieselbe Zeile nach unten begrenzt.

     Bis TO-0048 war das die abgesenkte Flaeche selbst. Mit den Registerlinien kam ein zweites
     leises Element in dieselbe Zelle, und die Summe wurde unruhig: Flaeche, Linie, Kante und
     Luecke bewarben sich um dieselbe Aufmerksamkeit. Der Ton liegt jetzt bei zwei Fuenfteln des
     Weges von Papier zur abgesenkten Flaeche -- die Insel bleibt erkennbar, traegt die
     Abgrenzung aber nicht mehr allein; das tun Kante und Luecke ohnehin besser.

     Eigener Wert und kein var() auf die Palette: MudBlazor kennt diese Zwischenstufe nicht.
     Kontrast ist dadurch nicht neu zu rechnen -- der Ton liegt zwischen zwei Gruenden, gegen
     die ToLiDoThemeContrastTests jede Textrolle ohnehin prueft (Papier und abgesenkte Flaeche),
     und damit auch sein Kontrast zwischen zwei geprueften Werten. */
  --tulidu-item-surface: #F7F7F4;

  /* Manila -- Etikettenfläche des Anhängers (TO-0043). Der einzige Farbwert des
     Entwurfs, den MudBlazor nicht kennt; Tinte darauf erreicht 13.7:1. */
  --tulidu-manila: #F0E9D8;

  /* Marke: Hervorhebung "Li" im Schriftzug (s. .tulidu-brand-accent). Seit TO-0043
     Klee statt des aufgehellten Grüns -- die Kopfleiste ist nicht mehr blau, und auf
     Papier kam #C8E6C9 nur auf 1.8:1. TO-0051 hat aus diesem Zwischenstand den Entscheid
     gemacht: die Hervorhebung bleibt farbig. Hier steht die ROLLE der Palette und kein Wert,
     deshalb folgt sie dem dunklen Theme von selbst (Nachtklee, 9.4:1) -- die Begründung
     steht bei .tulidu-brand-accent weiter unten. */
  --tulidu-brand-accent: var(--mud-palette-primary);

  /* Gepäckanhänger -- Listentyp-Etikett, Tag-Icon, Zähler-Kennzeichen. Seit TO-0043
     auf Manila mit Tinte darauf und einer Kante in Schnur; vorher ein eigener,
     wärmerer Braunton, der zu nichts sonst in der Oberfläche gehörte. */
  --tulidu-tag-text: var(--mud-palette-text-primary);
  --tulidu-tag-surface: var(--tulidu-manila);
  --tulidu-tag-edge: var(--mud-palette-lines-default);
  --tulidu-tag-hole-edge: var(--mud-palette-lines-inputs);
  --tulidu-tag-icon-active: var(--mud-palette-secondary);
  --tulidu-badge-surface: var(--mud-palette-secondary);
  --tulidu-badge-text: #FFFFFF;

  /* Fälligkeitsleiter, monoton Rot -> Orange -> Gelb (je näher das Datum, desto
     roter). TO-0042 hat die Werte gerechnet statt geschätzt: die bisherigen
     Material-Töne erreichten auf Papier 4.8:1 (#d32f2f), 3.0:1 (#ed6c02) und
     1.9:1 (#f9a825). Damit war ausgerechnet die Stufe unlesbar, die früh genug
     warnt, um noch etwas ändern zu können. Die Werte unten halten AA (4.5:1)
     auch als Fliesstext; die dunkle Entsprechung steht im Block darunter.
     Kontraste gegen Papier #FBFBF9 (TO-0043); auf dem heutigen weissen Grund
     liegen sie je rund 0.2 höher. */
  --tulidu-due-overdue: #B3261E;   /* 6.3:1 */
  --tulidu-due-urgent: #A24E00;    /* 5.6:1 */
  --tulidu-due-soon: #7A6200;      /* 5.7:1 */

  /* Vierte Stufe, nur im Fälligkeitsband (TO-0049): "später" — alles ab dem achten Tag.
     Bewusst kein Warnton, sondern ein zurückgenommenes Grüngrau: die Leiter oben wäre
     entwertet, wenn auch der übernächste Montag noch farbig riefe. Als bedeutungstragende
     Fläche muss der Ton trotzdem 3:1 halten; 4.5:1 gegen Papier #FBFBF9 hat er ohnehin. */
  --tulidu-due-later: #6E7773;     /* 4.5:1 */

  /* Freigabe-Kennzeichnung: grün = von mir geteilt, orange = mit mir geteilt. Die
     Unterscheidung bleibt, die Töne kommen seit TO-0043 aus der Palette. Beide sind
     Icon-Farben und mussten dafür ohnehin nachgezogen werden: das bisherige #f57c00
     erreichte auf Papier 2.6:1 und verfehlte damit die 3:1, die WCAG für
     bedeutungstragende Grafik verlangt. Jetzt 5.2:1 (Klee) und 5.6:1 (Warnton). */
  --tulidu-share-by-me: var(--mud-palette-primary);
  --tulidu-share-with-me: var(--mud-palette-warning);

  /* Loch-Motiv am Sektionskopf (TO-0047): der Ring um den gestanzten Punkt. „Gepinnte
     Listen" bekommt ihn in Klee (deckt sich mit dem Pin-Icon daneben), „Alle Listen" in
     Schnur — damit bleiben die beiden Sektionen unterscheidbar, ohne dass eine davon eine
     Farbfläche braucht. */
  --tulidu-section-punch: var(--mud-palette-lines-inputs);

  /* Statusflächen des Fortschrittsbalkens auf der Listenkarte (TO-0047). Sie führen dieselben
     Rollen, die ItemPresentationMud.StatusColor für die Status-Chips vergibt — die Zuordnung
     Status → Rolle steht dort und nur dort, hier steht Rolle → Fläche.

     „Offen" ist Schnur: der Rest, der noch vor einem liegt, ist keine Meldung, sondern der
     ungefüllte Teil des Balkens. „Ohne Status" liegt eine Stufe leiser, weil das Fehlen einer
     Aussage nicht so laut sein soll wie eine.

     Die Flächen sind bewusst NICHT auf 3:1 gerechnet: sie stehen nie allein, die Legende
     darunter nennt jede Zahl im Text, und der Balken selbst ist aria-hidden. Die Farbe
     illustriert hier, sie trägt nicht (REQ-08-002). */
  --tulidu-status-success: var(--mud-palette-success);
  --tulidu-status-info: var(--mud-palette-info);
  --tulidu-status-warning: var(--mud-palette-warning);
  --tulidu-status-error: var(--mud-palette-error);
  --tulidu-status-neutral: var(--mud-palette-lines-default);
  --tulidu-status-none: var(--mud-palette-divider);

  /* Registerlinie im Item-Baum (TO-0048): die senkrechte Haarlinie, die je Ebene die
     Verschachtelung zeigt. Schnur und damit leiser als die Kante zwischen zwei Eintraegen
     (--tulidu-item-boundary, Schnur dunkel): die Linie wiederholt sich in jeder Zeile und
     in jeder Ebene. Sie soll die Tiefe zeigen, nicht die Zeile zerschneiden. */
  --tulidu-tree-rail: var(--mud-palette-lines-default);

  /* Drag & Drop. Bewusst eine eigene Farbe, damit "hier wird eingefügt" nie mit
     den Freigabe-Kennzeichnungen verwechselt wird -- seit TO-0043 die Info-Farbe
     (Tiefe, #1C6675) statt des MudBlazor-Blaus, das mit der Palette verschwunden ist. */
  --tulidu-drop-indicator: var(--mud-palette-info);
  --tulidu-drop-into-surface: rgba(28, 102, 117, 0.08);

  /* Profilbild-Zuschnitt: Fläche hinter dem noch nicht geladenen Bild. Warm getönt,
     damit der Platzhalter nicht als einziger Grauwert auf Papier steht. */
  --tulidu-crop-frame: #E8E6E0;

  /* Der einzige Schatten, den ToLiDo selbst zeichnet: der Sprunglink, der beim Tabben
     über allem schwebt (s. .sr-only-focusable:focus). Er liegt wirklich über dem
     Inhalt, deshalb Schatten und nicht Haarlinie. Steht seit TO-0043 als Token hier,
     damit unterhalb der Token-Blöcke ausnahmslos kein Farbwert mehr vorkommt --
     ein Test in TuLiDu.WebApp.Tests prüft genau das. */
  --tulidu-shadow-overlay: 0 2px 8px rgba(0, 0, 0, 0.35);

  /* Erscheinungsbild (TO-0045, REQ-08-003) — die Grundstufen. Beide Einstellungen sind hier
     bewusst als Token notiert und nicht als Regel: die Stufen darunter überschreiben nur
     diese Werte, und jede Stelle, die einen davon verwendet, zieht damit automatisch mit.

     Schriftgrösse als FAKTOR auf der Grundschriftgrösse des Dokuments (s. die html-Regel
     weiter unten), nicht als Liste einzelner Grössen: Theme-Typografie und Stylesheet sind
     durchgehend in rem notiert, ein Faktor an der Wurzel zieht die ganze Skala mit und lässt
     ihre Verhältnisse unangetastet. */
  --tulidu-font-scale: 1;

  /* Dichte: Zeilenhöhe und Zeilenabstand im Item-Baum, Innenabstände der Karten, Abstand
     zwischen den Sektionen der Listenübersicht. Die Werte hier sind exakt die, die vor
     TO-0045 fest in den jeweiligen Regeln standen — „komfortabel" ist damit definitionsgemäss
     das bisherige Aussehen. */
  --tulidu-tree-row-min-height: 32px;
  --tulidu-tree-row-padding-y: 3px;
  --tulidu-tree-row-gap: 6px;
  --tulidu-card-padding: 16px;
  --tulidu-card-actions-padding: 8px;
  --tulidu-space-section: 4.5rem;
}

/* ------------------------------------------------------------
   Dunkles Theme: die Token, die nicht einfach mitziehen (TO-0042, TO-0044)
   MudBlazor schreibt im Dark Mode nur die --mud-palette-*-Variablen um und
   hinterlässt im DOM keinen Anker, an dem eigenes CSS erkennen könnte, welches
   Theme gerade gilt (nachgeprüft in publish_output: MudBlazor.min.css kennt nur
   die Hilfsklassen .mud-dark*, und MudBlazor.dll enthält keine Theme-Klasse).
   Der Anker muss also von ToLiDo kommen: TO-0044 setzt data-tulidu-theme am
   <html>-Element auf "light" oder "dark". Weil das Attribut an der Wurzel hängt,
   erben auch Dialoge und Popover die Werte -- die rendert MudBlazor ausserhalb
   des Layout-Baums, ein Anker weiter unten würde sie nicht erreichen.

   Seit TO-0044 wird das Attribut gesetzt: MainLayout ruft nach dem ersten Render
   tulido.setTheme("light"|"dark") auf (app.js), und derselbe Aufruf läuft bei
   jedem späteren Wechsel des Betriebssystems noch einmal.

   Hier steht NUR, was nicht von selbst mitzieht. Alles, was auf eine
   --mud-palette-*-Variable verweist -- der Anhänger-Rand, die
   Freigabe-Kennzeichnungen, die Drop-Farbe, der Markenakzent, die abgesenkte
   Fläche -- wechselt mit der Palette in ToLiDoTheme.cs und braucht hier keine
   zweite Zeile. Jede Zeile, die hier doch steht, ist eine Farbe, die MudBlazor
   nicht kennt.

   Bewusst NICHT über @media (prefers-color-scheme: dark): das würde die
   Fälligkeitsfarben schon heute umschalten, während der Rest der Anwendung hell
   bleibt. Und mit TO-0045 (Hell/Dunkel/System frei wählbar) käme man damit
   ohnehin nicht aus -- wer auf einem dunklen System "Hell" wählt, braucht die
   hellen Stufen.

   Die Kontrastwerte gelten gegen den dunklen Grund #101815 (NIGHT_GROUND in
   ToLiDoTheme.cs); auf der dortigen Flächenfarbe #18211E liegen sie je rund
   0.7 tiefer und bleiben damit deutlich über AA.
   ------------------------------------------------------------ */
:root[data-tulidu-theme="dark"] {
  /* Fälligkeitsleiter (TO-0042). --tulidu-due-overdue ist derselbe Ton wie die
     Fehlerfarbe der dunklen Palette; ein Test hält beide zusammen. */
  --tulidu-due-overdue: #FF8A7A;   /* 7.9:1 */
  --tulidu-due-urgent: #FFB067;    /* 10.0:1 */
  --tulidu-due-soon: #E8C46A;      /* 10.8:1 */

  /* "Später" im Fälligkeitsband (TO-0049). Der helle Ton #6E7773 erreicht auf dem dunklen
     Grund nur 3.9:1 und stünde neben den drei Leuchtstufen wie ausgeschaltet da; aufgehellt
     bleibt er zurückgenommen, ohne zu verschwinden. 5.9:1 gegen #101815. */
  --tulidu-due-later: #8A9791;     /* 5.9:1 */

  /* Insel-Flaeche eines Items (s. hellen Block). Dunkel liegt die abgesenkte Flaeche UNTER dem
     Grund statt darueber -- "heller" heisst hier also ebenfalls: naeher an den Grund. Derselbe
     Anteil wie hell, zwei Fuenftel des Weges. */
  --tulidu-item-surface: #0E1613;

  /* Manila (TO-0044): die Etikettenfläche des Anhängers. Der helle Ton #F0E9D8 ist
     im dunklen Theme eine Leuchtfläche -- der Anhänger würde die Zeile beherrschen,
     statt sie zu beschriften. Dunkel bleibt er warm und damit als Papier erkennbar. */
  --tulidu-manila: #2A2620;

  /* Die Etikettenschrift steht hell auf dieser Fläche, aber warm statt kühl: die
     Textfarbe der Palette (#E6EAE8) sähe auf Manila aus wie ein Fremdkörper.
     11.3:1 auf #2A2620. */
  --tulidu-tag-text: #E8DFC8;

  /* Zähler-Kennzeichen: die Fläche ist die Sekundärfarbe und damit im dunklen Theme
     hell (Etikettensand). Die Schrift darauf muss deshalb dunkel sein -- weiss käme
     auf 1.7:1. Der Wert ist der dunkle Grund, 9.7:1. */
  --tulidu-badge-text: #101815;

  /* Fläche hinter dem noch nicht geladenen Profilbild. Warm getönt wie hell, nur
     eine Spur über der Kartenfläche, damit der Platzhalter als Loch erkennbar ist. */
  --tulidu-crop-frame: #262421;

  /* Drop-Fläche: dieselbe Deckkraft-Idee wie hell, aber auf der dunklen Info-Farbe
     (#6BC6D8) und etwas kräftiger -- eine 8-Prozent-Aufhellung ist auf dunklem Grund
     kaum noch zu sehen. */
  --tulidu-drop-into-surface: rgba(107, 198, 216, 0.14);

  /* Der Sprunglink-Schatten. Schwarz auf schwarzem Grund trennt nichts mehr; im
     dunklen Theme muss der Schatten tiefer und weicher sein, um überhaupt zu wirken. */
  --tulidu-shadow-overlay: 0 2px 10px rgba(0, 0, 0, 0.65);
}

/* ------------------------------------------------------------
   Erscheinungsbild: die Stufen (TO-0045, REQ-08-003)

   Dieselbe Mechanik wie beim dunklen Theme darüber: MainLayout schreibt die gewählte
   Stufe als Attribut an das <html>-Element (tulido.setAppearance in app.js), und hier
   hängen die Token daran. An der Wurzel, damit auch Dialoge und Popover sie erben --
   die rendert MudBlazor ausserhalb des Layout-Baums.

   Die Grundstufen ("Normal", "Komfortabel") haben KEIN Attribut und keinen Block: sie
   stehen bereits im :root-Block oben. Ein Attribut data-tulidu-font-scale="normal" wäre
   eine zweite Schreibweise für denselben Zustand, und jede Regel müsste beide kennen.
   AppearancePresentation liefert für diese Stufen deshalb null, und app.js entfernt das
   Attribut dann, statt es zu setzen.
   ------------------------------------------------------------ */

/* Schriftgrösse. 1.125 und 1.25 statt runder Zahlen: das ist die Leiter, die bei 16px
   Grundgrösse auf 18px und 20px führt -- Werte, die der Browser ohne Zwischenschritt
   rastert. Ein Faktor 1.5 wäre die nächste sinnvolle Stufe, sprengt aber das Spaltenraster
   des Item-Baums, dessen Breiten in px stehen. */
:root[data-tulidu-font-scale="large"] {
  --tulidu-font-scale: 1.125;
}

:root[data-tulidu-font-scale="xlarge"] {
  --tulidu-font-scale: 1.25;
}

/* Dichte. Die Zeile im Baum verliert zwei Drittel ihres senkrechten Innenabstands und
   fast den ganzen Abstand zur Nachbarzeile; der "Insel"-Eindruck aus TO-0025 bleibt
   dadurch erhalten (die Zeilen laufen nicht ineinander), rückt aber zusammen. Die
   Mindesthöhe sinkt nur auf 26px und nicht weiter: darunter unterschreiten die
   Schaltflächen in der Aktionsspalte die 24×24 CSS-Pixel, die WCAG 2.2 (2.5.8) als
   Zielgrösse verlangt. */
:root[data-tulidu-density="compact"] {
  --tulidu-tree-row-min-height: 26px;
  --tulidu-tree-row-padding-y: 1px;
  --tulidu-tree-row-gap: 2px;
  --tulidu-card-padding: 10px;
  --tulidu-card-actions-padding: 4px;
  --tulidu-space-section: 2.5rem;
}

/* Die Grundschriftgrösse des Dokuments -- die eine Stelle, an der der Faktor wirkt.
   Prozent und nicht px: damit bleibt die im Browser eingestellte Schriftgrösse die
   Grundlage. Ein fester px-Wert würde sie überschreiben und ausgerechnet den Benutzern
   die Einstellung nehmen, für die REQ-08-003 gedacht ist. */
html {
  font-size: calc(100% * var(--tulidu-font-scale));
}

/* Dichte an den Karten. Die Regeln greifen auf MudBlazors eigene Klassen zu, weil die
   Innenabstände der Karte dort und nicht im Markup stehen; die Spezifität des
   Wurzel-Attributs reicht dafür aus. Wo eine Komponente einen Abstand als Inline-Style
   mitbringt (ListCard setzt padding-top/-bottom eigens), bleibt dieser stehen -- er ist
   dort Teil des Kartenaufbaus und nicht der Dichte. */
:root[data-tulidu-density="compact"] .mud-card-header,
:root[data-tulidu-density="compact"] .mud-card-content {
  padding: var(--tulidu-card-padding);
}

:root[data-tulidu-density="compact"] .mud-card-actions {
  padding: var(--tulidu-card-actions-padding);
}

/* ------------------------------------------------------------
   Schriften (TO-0040)
   Mit der Applikation ausgeliefert, kein Web-Dienst zur Laufzeit. Die Dateien
   liegen unter wwwroot/fonts/, ein Verzeichnis je Familie; das README dort nennt
   Herkunft, Lizenz und die benötigten Schnitte.

   Warum selbst ausliefern: sonst hängt der Seitenaufbau an der Erreichbarkeit
   eines Dritten, und bei jedem Aufruf geht die IP-Adresse der Benutzer dorthin.
   Für ein Werkzeug, in dem private Aufgabenlisten stehen, ist das kein
   Nebenaspekt — und eine spätere Content-Security-Policy muss keine fremde
   Domain freischalten.

   Je Schnitt zwei Regeln: latin-ext und latin. Der Browser holt nur, was der
   dargestellte Text tatsächlich braucht — eine Liste ohne osteuropäische
   Diakritik lädt die latin-ext-Datei gar nicht erst. Die unicode-range-Werte
   sind die von Google Fonts ausgelieferten, weil die Dateien genau diese
   Subsets sind. Liefert eine Familie kein latin-ext (s. README), wird die
   zugehörige Regel ersatzlos gelöscht.

   font-display: swap — Text ist sofort lesbar und wird nachträglich ersetzt.
   Für eine Aufgabenliste ist sichtbarer Text wichtiger als ein sprungfreier
   Seitenaufbau.

   WELCHE Familie wo verwendet wird, steht nicht hier, sondern in ToLiDoTheme.cs:
   Schriftfamilien kennt MudBlazor, also gehören sie ins Theme (Design.md, 3f).
   Hier stehen nur die Dateien. Archivo und IBM Plex Mono sind deshalb heute noch
   ungenutzt — sie kommen mit TO-0043 zum Zug, so wie die ungenutzten Token
   oberhalb.
   ------------------------------------------------------------ */

/* Archivo 600 — Überschriften und Etiketten (ab TO-0043). */
@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('fonts/archivo/archivo-600-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('fonts/archivo/archivo-600-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* Atkinson Hyperlegible 400/700 — Fliesstext. Vom Braille Institute für
   Menschen mit Seheinschränkung gezeichnet; der Entscheid, ob sie bleibt,
   fällt in TO-0041. */
@font-face {
  font-family: 'Atkinson Hyperlegible';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('fonts/atkinson/atkinson-400-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'Atkinson Hyperlegible';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('fonts/atkinson/atkinson-400-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Atkinson Hyperlegible';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('fonts/atkinson/atkinson-700-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'Atkinson Hyperlegible';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('fonts/atkinson/atkinson-700-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* IBM Plex Mono 400 — Daten: Datum, Zähler, Prozente (ab TO-0043). */
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('fonts/plex-mono/plex-mono-400-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('fonts/plex-mono/plex-mono-400-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* ------------------------------------------------------------
   Schaltflächen ohne Schaltflächen-Aussehen (TO-0065)
   Aktivatoren, die wie ein Icon oder wie ein Datum aussehen sollen, waren früher
   <span role="button"> mit eigenem Keydown-Handler. Das ist mit Screenreadern nicht
   verlässlich -- ein roher Tastendruck erreicht immer das fokussierte Element, auch
   wenn der virtuelle Cursor längst woanders steht, und so fing das Etikett-Icon in
   der Listendetail-Ansicht das Enter ab, das dem Stift daneben galt. Begründung
   ausführlich im Kopfkommentar von TagIcon.razor.

   Seither sind es echte <button>. Diese Klasse nimmt ihnen das Standardaussehen des
   Browsers, damit gegenüber dem früheren <span> nichts an Höhe, Rahmen oder Schrift
   dazukommt; die Komponentenklasse daneben gestaltet weiter allein.

   Die Regel steht bewusst VOR den Typografie-Rollen und allen Komponentenblöcken:
   font: inherit setzt auch die Familie, und .tulidu-due-row__date weiter unten muss
   seine Datenschrift dagegen durchsetzen können. Beide Selektoren haben dieselbe
   Spezifität -- dann entscheidet die Reihenfolge in dieser Datei.
   ------------------------------------------------------------ */
.tulidu-plain-button {
  appearance: none;
  background: none;
  border: 0;
  margin: 0;
  padding: 0;
  font: inherit;
  color: inherit;
  text-align: inherit;
}

/* ------------------------------------------------------------
   Typografie-Rollen (TO-0043)
   WELCHE Schrift wo gilt, entscheidet ToLiDoTheme.cs: MudBlazor schreibt die
   Familien als --mud-typography-<variante>-family in den Body, und zwar NACH
   dieser Datei -- ein :root-Block hier käme dagegen nicht an. Hier stehen nur
   die beiden Rollen, für die MudBlazor gar keine Variante kennt.
   ------------------------------------------------------------ */

/* Etikettenschrift: Sektionsköpfe, Anhänger-Beschriftung, alles, was benennt statt
   zu erzählen. Familie und Sperrung kommen aus der Overline-Variante des Themes,
   damit es die Schriftliste nicht ein zweites Mal gibt. */
.tulidu-label {
  font-family: var(--mud-typography-overline-family);
  font-size: var(--mud-typography-overline-size);
  font-weight: var(--mud-typography-overline-weight);
  letter-spacing: var(--mud-typography-overline-letterspacing);
  text-transform: uppercase;
}

/* Datenschrift: Datum, Zähler, Prozente, Versionsnummer. Der Grund ist funktional
   und nicht dekorativ -- erst tabular-nums richtet die Datumsspalte im Item-Baum
   tatsächlich aus, weil jede Ziffer dieselbe Breite bekommt.

   Die drei Selektoren sind nötig, weil die Klasse mal auf einem gewöhnlichen
   Element sitzt, mal auf einem MudText und mal auf einem Element, das einen
   MudText enthält. Alle drei haben dieselbe Spezifität wie MudBlazors
   .mud-typography-<variante> oder mehr, und app.css wird nach MudBlazor.min.css
   geladen (s. App.razor) -- deshalb gewinnen sie. */
.tulidu-data,
.tulidu-data.mud-typography,
.tulidu-data .mud-typography {
  font-family: var(--tulidu-font-data);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0;
}

/* Das Fälligkeitsdatum trägt seine Klasse schon (DueDateField.razor, seit TO-0042
   auch die Farbklasse) -- es hier mitzunehmen erspart eine Änderung an einer Datei,
   deren Doc-Kommentar erklärt, warum das Markup so und nicht anders aussieht. */
.tulidu-due-row__date,
.tulidu-due-row__date .mud-typography {
  font-family: var(--tulidu-font-data);
  font-variant-numeric: tabular-nums;
}

/* ------------------------------------------------------------
   Flächen und Kanten (TO-0043)
   Karten stehen auf Papier und werden durch eine Haarlinie in Schnur begrenzt,
   nicht durch einen Schatten. Schatten bleibt den Ebenen vorbehalten, die
   wirklich darüber liegen: Dialog, Menü, Popover, Drawer im Overlay-Modus.

   Warum das hier steht und nicht als Elevation="0" in fünfundzwanzig Razor-Dateien:
   der Schatten ist eine Eigenschaft der Gestaltung, nicht der einzelnen Ansicht.
   Eine Regel lässt sich zurücknehmen, fünfundzwanzig Änderungen nicht.

   Die :not()-Kette nennt die Ebenen, die ihren Schatten behalten. Sie greift auch
   dann richtig, wenn eine davon gar keine .mud-paper-Klasse trägt -- dann läuft die
   Ausnahme ins Leere, statt etwas kaputtzumachen.
   ------------------------------------------------------------ */
.mud-paper.mud-elevation-1:not(.mud-dialog):not(.mud-popover):not(.mud-drawer):not(.mud-appbar),
.mud-paper.mud-elevation-2:not(.mud-dialog):not(.mud-popover):not(.mud-drawer):not(.mud-appbar),
.mud-paper.mud-elevation-3:not(.mud-dialog):not(.mud-popover):not(.mud-drawer):not(.mud-appbar) {
  box-shadow: none;
  border: 1px solid var(--mud-palette-lines-default);
  border-radius: var(--tulidu-radius-card);
}

/* Kopfleiste: Tinte auf Papier (Palette, s. ToLiDoTheme.AppbarBackground) mit einer
   Schnur-Haarlinie als unterer Kante statt eines blauen Farbblocks mit Schatten. */
.tulidu-appbar {
  border-bottom: 1px solid var(--mud-palette-lines-default);
}

/* Drawer: dockt im Normalfall an den Inhalt an und ist dann keine darüberliegende
   Ebene -- also Kante statt Schatten. Im Overlay-Modus (.mud-drawer-temporary, auf
   schmalen Bildschirmen) liegt er wirklich über dem Inhalt und behält seinen. */
.mud-drawer:not(.mud-drawer-temporary) {
  box-shadow: none;
}

.mud-drawer.mud-drawer-pos-left:not(.mud-drawer-temporary) {
  border-right: 1px solid var(--mud-palette-lines-default);
}

/* Abgesenkte Fläche als Klasse -- ersetzt die Farb-Inline-Styles in Home, MyDay,
   TagFilter und TagMultiFilter (TO-0043, Vorschlag 5.4). Ein Inline-Style ist im
   Dark Mode nicht nachziehbar; ausserdem stand dort bis TO-0043 eine Variable, die
   es gar nicht gibt (s. --tulidu-surface-sunken im Token-Block). */
.tulidu-surface-sunken {
  background: var(--tulidu-surface-sunken);
}

/* ------------------------------------------------------------
   Accessibility helpers
   ------------------------------------------------------------ */

/* Visually hidden, but still announced by screen readers.
   Used for aria-live regions and off-screen labels. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* Like .sr-only, but becomes visible when focused — for skip links
   ("Zum Inhalt springen") that should appear once a keyboard user
   tabs to them. */
.sr-only-focusable:not(:focus):not(:focus-within) {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* ------------------------------------------------------------
   Branding
   ------------------------------------------------------------ */

/* App-Icon in der AppBar (MainLayout.razor), links neben dem
   "ToLiDo"-Schriftzug. Rein dekorativ (aria-hidden im Markup) —
   der Schriftzug daneben trägt den Namen für Screenreader. logo-icon.svg
   trägt einen Grün-Verlauf; der halbtransparente weisse Rand ist mit TO-0043
   entfallen. Er war eine Notmassnahme gegen den harten Kontrast zur blauen
   AppBar — die Kopfleiste steht jetzt in Tinte auf Papier, und auf hellem Grund
   schnürt ein weisser Rand das Zeichen nur ein. */
.tulidu-brand-logo {
  height: 32px;
  width: 32px;
  flex-shrink: 0;
}

/* Grün eingefärbtes "Li" im AppBar-Schriftzug (MainLayout.razor), als Echo des
   Icons/der externen Wortmarke (logo-full.png).

   Bis TO-0043 war das #C8E6C9 (Material Green 100) — ein eigens aufgehelltes Grün,
   gewählt gegen die blaue AppBar, wo es 4.46:1 erreichte. Auf Papier kommt derselbe
   Ton nur noch auf 1.8:1. Seit TO-0043 steht hier die Primärfarbe Klee: 5.2:1 auf
   Papier, im dunklen Theme Nachtklee mit 9.4:1.

   TO-0051 hat entschieden, dass es dabei bleibt. Zur Wahl stand, die Silbe stattdessen
   über das Schriftgewicht zu betonen (Archivo 700 gegen 500). Dagegen sprach zweierlei.
   Ausgeliefert ist nur Archivo 600 — der Weg kostete vier weitere Schriftdateien für eine
   Silbe und die Regel "ein Gewicht für alle Überschriften"; ohne sie rechnet der Browser
   sich einen Fettschnitt aus der 600 zusammen, und wie der aussieht, entscheidet dann er.
   Und sein Hauptargument, in beiden Themes gleich zu funktionieren, ist ohnehin erfüllt,
   seit der Token oben auf die Palettenrolle zeigt statt auf einen Festwert.

   Was der Farbweg nicht leistet: wer Rot-Grün nicht unterscheidet, sieht keine
   Hervorhebung. Er sieht einen ruhigen Schriftzug — keine fehlende Information. Genau
   deshalb ist das hier vertretbar und an einer Statusanzeige nicht.

   Nachgehalten von BrandMarkTests: der Token zeigt auf die Palettenrolle, das Markup
   trägt die Klasse, und die Regel setzt nur die Farbe. */
.tulidu-brand-accent {
  color: var(--tulidu-brand-accent);
}

/* Versionsnummer im Drawer-Fuss (MainLayout.razor), seit TO-0030 ein MudButton statt reinem
   Text -- oeffnet die Release Notes der laufenden Version. Bis TO-0050 stand sie in der
   Kopfleiste. Die Standard-MudButton-Optik (Grossbuchstaben, betonte Schriftstaerke) waere
   fuer ein nebensaechliches Detail zu auffaellig; die Ueberschreibung laesst sie weiterhin wie die bisherige
   Typo.caption aussehen, nur eben klickbar. */
.tulidu-version-button {
  text-transform: none;
  font-size: 0.75rem;
  font-weight: 400;
  min-width: 0;
  padding: 4px 8px;
}

/* Eingebettetes Release-Notes-Dokument im ReleaseNotesDialog (TO-0030). Feste Hoehe statt
   automatischer Anpassung an den Inhalt: ein iframe kennt die Hoehe seines fremden
   Dokuments nicht von sich aus, ohne dass das eingebettete Dokument aktiv mitspielt
   (postMessage o.ae.) -- das waere fuer ein manuell exportiertes, statisches HTML-Dokument
   unverhaeltnismaessig. Der Inhalt scrollt stattdessen innerhalb des iframes. */
.tulidu-release-notes-frame {
  width: 100%;
  height: 60vh;
  border: none;
}

/* Visible appearance while focused — fixed top-left chip above everything else,
   doesn't push surrounding layout since it's taken out of flow either way. */
.sr-only-focusable:focus,
.sr-only-focusable:focus-within {
  position: fixed;
  top: 0.5rem;
  left: 0.5rem;
  width: auto;
  height: auto;
  padding: 0.5rem 1rem;
  margin: 0;
  overflow: visible;
  clip: auto;
  white-space: normal;
  background: var(--mud-palette-primary);
  color: var(--mud-palette-primary-text);
  border-radius: 4px;
  z-index: 3000;
  text-decoration: none;
  font-weight: 500;
  box-shadow: var(--tulidu-shadow-overlay);
}

/* ------------------------------------------------------------
   Profilbild-Zuschnitt (REQ-02-009)
   Quadratischer, overflow:hidden-Container — der sichtbare
   Ausschnitt IST der spätere Zuschnitt. Bild wird per JS
   (tulido.imageCrop) positioniert/skaliert.
   ------------------------------------------------------------ */
.tulidu-crop-container {
  position: relative;
  width: 280px;
  height: 280px;
  max-width: 100%;
  overflow: hidden;
  border-radius: 50%;
  background: var(--tulidu-crop-frame);
  margin: 0 auto;
  cursor: grab;
  touch-action: none;
  user-select: none;
}

.tulidu-crop-container:active {
  cursor: grabbing;
}

.tulidu-crop-container img {
  position: absolute;
  transform-origin: center center;
  max-width: none;
  pointer-events: none;
  -webkit-user-drag: none;
}

/* ------------------------------------------------------------
   Hinweis-/Beschreibungstexte
   Erläuterungen unter Überschriften und zu Formularfeldern. Einheitlich
   dezent + kursiv. Auf MudText anwenden und das Color-Attribut dort weglassen.

   Seit TO-0043 der Sekundärtext der Palette (Graphit, 6.0:1 auf Papier) statt eines
   fest verdrahteten rgb(150,150,150). Das erreichte 2.6:1 und verfehlte damit AA für
   Fliesstext deutlich — ausgerechnet bei den Texten, die etwas erklären sollen
   (REQ-08-001). Dieselbe Korrektur wie bei den Fälligkeitsfarben in TO-0042: der Ton
   war leise gemeint und war unlesbar geworden.
   ------------------------------------------------------------ */
.tulidu-hint {
  color: var(--mud-palette-text-secondary);
  font-style: italic;
}

/* Greift auch, wenn die Klasse auf einem MudText-Wrapper sitzt, dessen
   eigentlicher Text im inneren .mud-typography-Element liegt. */
.tulidu-hint.mud-typography,
.tulidu-hint .mud-typography {
  color: var(--mud-palette-text-secondary);
  font-style: italic;
}

/* ------------------------------------------------------------
   Freigabe-Zeile im „Liste teilen"-Dialog (REQ-04-008): eine Zeile pro
   Person mit Namen/Entfernen-Button oben und den Berechtigungs-Checkboxen
   darunter, per Trennlinie von der nächsten Zeile abgesetzt.
   ------------------------------------------------------------ */
.tulidu-share-row {
  padding-bottom: 8px;
  border-bottom: 1px solid var(--mud-palette-lines-default);
}

.tulidu-share-row:last-of-type {
  border-bottom: none;
}

/* ------------------------------------------------------------
   Listentyp-„Gepäckanhänger" (Listen-Übersicht)
   Stellt die Listentyp-Bezeichnung (z.B. „Packliste") als kleinen
   Anhänger neben dem Titel dar: abgerundeter Körper, links zu einer
   Spitze zulaufend, mit einem runden „Loch" am spitzen Ende.
   Dezent (Outline-Optik, gedämpftes Grau) statt des bisherigen Rots.
   ------------------------------------------------------------ */
.tulidu-type-tag {
  position: relative;
  display: inline-flex;
  align-items: center;
  /* Mehr Platz links für Spitze + Loch, rechts normaler Innenabstand. */
  padding: 2px 10px 2px 22px;
  /* Etikettenschrift (TO-0043): Archivo aus der Overline-Variante des Themes, leicht
     gesperrt. Bewusst OHNE text-transform: uppercase, obwohl der Entwurf das für
     Etiketten vorsieht -- hier steht ein Eigenname ("Packliste", "Vorrat"), und
     Versalien nehmen einem Eigennamen die Wortform, an der man ihn erkennt. Die
     Sektionsköpfe, für die die Regel gedacht war, sind davon nicht betroffen und
     tragen sie seit TO-0047 auch. Der Anhänger bleibt damit das, was er hier ist:
     das Etikett am Listentyp. Die Listenkarte selbst als Anhänger zu zeichnen, war
     in TO-0047 vorgeschlagen und ist verworfen (s. Design.md, Abschnitt 3f). */
  font-family: var(--mud-typography-overline-family);
  font-size: 0.72rem;
  font-weight: 600;
  line-height: 1.4;
  letter-spacing: 0.04em;
  /* Warmer Sandton („Kofferzettel"): beiger Hintergrund + bräunliche Schrift.
     Die Form entsteht über clip-path; deshalb statt border ein Innen-Schatten als
     feine Kante (eine echte border würde an der schrägen Spitze abgeschnitten). */
  color: var(--tulidu-tag-text);
  background: var(--tulidu-tag-surface);
  box-shadow: inset 0 0 0 1px var(--tulidu-tag-edge);
  /* Rechts abgerundet, links zur Spitze zulaufend. */
  border-radius: 3px 11px 11px 3px;
  clip-path: polygon(
    11px 0,        /* obere Kante beginnt nach der Spitze            */
    100% 0,
    100% 100%,
    11px 100%,
    0 50%          /* linke Spitze (Anhänger-Form)                   */
  );
  white-space: nowrap;
  user-select: none;
  /* Leichtes Kippen — wirkt wie ein hängender Gepäckanhänger. */
  transform: rotate(2deg);
  transform-origin: left center;
}

/* Das „Loch" am spitzen Ende des Anhängers. */
.tulidu-type-tag::before {
  content: "";
  position: absolute;
  left: 8px;
  top: 50%;
  transform: translateY(-50%);
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--mud-palette-surface);
  box-shadow: 0 0 0 1px var(--tulidu-tag-hole-edge);
}

/* ------------------------------------------------------------
   Statusbalken und Legende der Listenkarte (TO-0047)

   Ersetzt bis zu sechs gefüllte Chips durch ein Element: ein Balken aus
   Statussegmenten, die Zahlen als Legende daneben. Die Breite eines Segments kommt
   aus flex-grow und damit direkt aus der Anzahl — kein Prozentwert, der gerundet
   werden müsste.

   Der Balken ist im Markup aria-hidden; die Legende darunter ist eine echte Liste
   und trägt dieselben Zahlen als Text. Deshalb dürfen die Flächen leiser sein als
   3:1: sie illustrieren, sie tragen nicht.
   ------------------------------------------------------------ */
.tulidu-status-bar {
  display: flex;
  gap: 2px;
  height: 8px;
  margin-bottom: var(--tulidu-space-2);
  border-radius: var(--tulidu-radius-pill);
  overflow: hidden;
  background: var(--mud-palette-divider);
}

.tulidu-status-bar__segment {
  display: block;
  height: 100%;
  /* Ein einzelner Eintrag unter zweihundert soll sichtbar bleiben. */
  min-width: 4px;
}

.tulidu-status-legend {
  display: flex;
  flex-wrap: wrap;
  gap: var(--tulidu-space-1) var(--tulidu-space-3);
  margin: 0;
  padding: 0;
  list-style: none;
  /* Zahlen: Datenschrift mit Tabellenziffern, wie überall sonst im Projekt. */
  font-family: var(--tulidu-font-data);
  font-variant-numeric: tabular-nums;
  font-size: 0.72rem;
  color: var(--mud-palette-text-secondary);
}

.tulidu-status-legend li {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.tulidu-status-legend__dot {
  flex: none;
  width: 8px;
  height: 8px;
  border-radius: 50%;
}

/* Rolle → Fläche. Welcher Status welche Rolle bekommt, steht in
   ItemPresentationMud.StatusColor und nur dort. */
.tulidu-status-fill--success {
  background: var(--tulidu-status-success);
}

.tulidu-status-fill--info {
  background: var(--tulidu-status-info);
}

.tulidu-status-fill--warning {
  background: var(--tulidu-status-warning);
}

.tulidu-status-fill--error {
  background: var(--tulidu-status-error);
}

.tulidu-status-fill--neutral {
  background: var(--tulidu-status-neutral);
}

.tulidu-status-fill--none {
  background: var(--tulidu-status-none);
}

/* ------------------------------------------------------------
   Status als Keyline (TO-0048)

   Bis hierher trug der Status einen gefuellten Chip in seiner Farbe. In der Baumzeile
   standen damit zwei Farbflaechen nebeneinander -- Status und Faelligkeit --, und die
   auffaelligere von beiden war die, die man nicht sucht: der Status ist meistens "Offen",
   die Faelligkeit ist das, was draengt. Der Chip wird deshalb zu einem Punkt plus Text in
   der Statusfarbe. Danach traegt die Zeile ein einziges dominierendes Farbsignal.

   Die Rolle kommt aus ItemPresentationMud.StatusKeylineClass und damit aus derselben
   Zuordnung wie die Chip-Farbe und die Balkenflaeche der Listenkarte (StatusColor) -- eine
   Wahrheit pro Element.

   Anders als beim Fortschrittsbalken der Listenkarte traegt die Farbe hier Text, nicht
   Flaeche, und muss deshalb Fliesstext-Kontrast halten. Alle vier Signalrollen sind in
   ToLiDoThemeContrastTests bereits als Textfarbe gegen alle drei Gruende geprueft (4.5:1),
   in beiden Paletten; "Offen" traegt die sekundaere Textfarbe und ist dort ebenso geprueft.
   Allein traegt die Farbe ohnehin nicht: der Statusname steht daneben (REQ-08-002).

   Der Baustein ist geteilt (StatusChip) -- die Keyline gilt damit auch fuer die flachen
   Ansichten (ItemSummaryRow auf Startseite und "Mein Tag"). Das ist Absicht: ein Status,
   der im Baum anders aussieht als auf der Startseite, waere genau die Doppelspurigkeit,
   gegen die der geteilte Baustein angelegt wurde.
   ------------------------------------------------------------ */
.tulidu-status-key {
  display: inline-flex;
  align-items: center;
  gap: var(--tulidu-space-1);
  min-width: 0;
}

/* Der Punkt erbt die Farbe seines Elternelements. So faerbt die Rollen-Klasse Punkt und
   Text in einem Schritt, und die beiden koennen nicht auseinanderlaufen. */
.tulidu-status-key__dot {
  flex: 0 0 auto;
  width: 8px;
  height: 8px;
  border-radius: var(--tulidu-radius-pill);
  background: currentColor;
}

.tulidu-status-key__text {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 0.8125rem;
}

/* Anfassbarkeit: Ohne die Chip-Flaeche fehlt der Hinweis, dass der Status per Klick
   aenderbar ist. Die Unterstreichung beim Ueberfahren ersetzt ihn, ohne die Zeilenhoehe
   anzutasten -- ein Rahmen oder eine Flaeche taete genau das. Der Fokusring der
   Tastaturbedienung sitzt unveraendert am Aktivator selbst. */
.tulidu-status-key--interactive:hover .tulidu-status-key__text {
  text-decoration: underline;
  text-underline-offset: 2px;
}

.tulidu-status-key--success {
  color: var(--mud-palette-success);
}

.tulidu-status-key--info {
  color: var(--mud-palette-info);
}

.tulidu-status-key--warning {
  color: var(--mud-palette-warning);
}

.tulidu-status-key--error {
  color: var(--mud-palette-error);
}

/* "Offen" und "kein Status": keine Meldung, deshalb keine Signalfarbe. */
.tulidu-status-key--neutral {
  color: var(--mud-palette-text-secondary);
}

/* ------------------------------------------------------------
   Sektionskopf „Gepinnte Listen" / „Alle Listen" (Listen-Übersicht)

   Seit TO-0047 eine ruhige Zeile statt der Panel-Header-Optik mit Akzentbalken und
   Farbwäsche. Drei Teile: das Loch-Motiv als Punkt am Anfang, das Etikett in
   Versalien, und die Haarlinie, die die Zeile nach rechts ausfüllt.

   Warum leiser als vorher: eine Sektion soll die Karten darunter abgrenzen, nicht
   mit ihnen um Aufmerksamkeit streiten. Eine eigene Fläche und ein eigener
   Farbbalken waren dafür zwei Mittel zu viel. Die Unterscheidung der beiden
   Sektionen bleibt — sie steckt jetzt im Ring des Punktes statt in einer Fläche.

   Ursprünglich war diese Zeile die Schnur, an der die Listenkarten als
   Gepäckanhänger hingen. Die Kartenform ist verworfen (s. Design.md, Abschnitt 3f);
   der ruhigere Kopf ist geblieben, die senkrechte Linie zur ersten Karte nicht —
   sie hätte nichts mehr, woran sie hängt.

   Versalien sind hier richtig und am Listentyp-Etikett nicht: „GEPINNTE LISTEN" ist
   eine Bezeichnung, „Packliste" ein Eigenname (s. den Kommentar an .tulidu-type-tag).
   ------------------------------------------------------------ */
.tulidu-section-header {
  display: flex;
  align-items: center;
  gap: var(--tulidu-space-2);
  margin-bottom: var(--tulidu-space-3);
}

/* Die Haarlinie, die die Zeile nach rechts ausfüllt. */
.tulidu-section-header::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--mud-palette-lines-default);
}

/* Das Loch-Motiv als Punkt vor dem Etikett. Ein eigenes Element und kein Pseudo:
   ::after trägt die Haarlinie, und ein Punkt, den man ein- und ausblenden können
   muss, gehört ohnehin ins Markup. */
.tulidu-section-header__punch {
  flex: none;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--mud-palette-background);
  box-shadow: 0 0 0 2px var(--tulidu-section-punch);
}

/* Etikett: Archivo aus der Overline-Variante des Themes, klein und gesperrt. 600 statt
   700, weil Archivo nur in diesem Schnitt ausgeliefert wird (s. TO-0043). */
.tulidu-section-header .mud-typography {
  font-family: var(--mud-typography-overline-family);
  font-weight: 600;
  font-size: 0.75rem;
  line-height: 1.4;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--mud-palette-text-secondary);
}

/* Das Icon zieht auf die Etikettengrösse mit — Size.Small wäre neben einer 0.75rem-Zeile
   das grösste Element im Kopf und damit lauter als der Text, den es begleitet. */
.tulidu-section-header .mud-icon-root {
  font-size: 1rem;
}

.tulidu-section-header--pinned {
  --tulidu-section-punch: var(--mud-palette-primary);
}

.tulidu-section-header--all {
  --tulidu-section-punch: var(--mud-palette-lines-inputs);
}

/* Abstand am Ende einer Sektion in der Listen-Uebersicht ("Gepinnte Listen", "Alle Listen"),
   bevor die naechste Sektion beginnt (statt MudBlazors mb-6 = 24px, das als Trennung zwischen
   mehreren Sektionen zu knapp wirkte). Bewusst als margin-bottom der jeweils VORANGEHENDEN
   Sektion statt margin-top der folgenden: so bringt eine spaeter eingefuegte weitere Sektion
   ihren Abstand zu beiden Nachbarn automatisch mit, statt dass an mehreren Stellen im Markup
   nachjustiert werden muss. */
.tulidu-section-gap {
  margin-bottom: var(--tulidu-space-section);
}

/* ------------------------------------------------------------
   Aktiver Eintrag im Drawer (TO-0047)

   MudBlazor legt unter den aktiven Eintrag eine Farbwäsche über die volle Breite.
   Der Entwurf markiert ihn stattdessen mit demselben Loch-Motiv wie den
   Sektionskopf: ein Punkt am linken Rand. Damit bleibt die Fläche der
   Hover-Rückmeldung vorbehalten — und die bedeutet dann auch wieder etwas, statt
   mit der Markierung des aktiven Eintrags um dieselbe Sprache zu streiten.

   Die Schriftfarbe des aktiven Eintrags bleibt unangetastet: sie kommt aus der
   Palette und ist die zweite, textliche Hälfte derselben Aussage — ohne sie hinge
   die Markierung an einem Punkt von sechs Pixeln allein.
   ------------------------------------------------------------ */
.mud-nav-link.active:not(.mud-nav-link-disabled),
.mud-navmenu .mud-nav-link.active:not(.mud-nav-link-disabled) {
  background-color: transparent;
}

.mud-nav-link {
  position: relative;
}

.mud-nav-link.active:not(.mud-nav-link-disabled)::before {
  content: "";
  position: absolute;
  left: 6px;
  top: 50%;
  width: 6px;
  height: 6px;
  margin-top: -3px;
  border-radius: 50%;
  background: var(--mud-palette-drawer-background);
  box-shadow: 0 0 0 2px var(--mud-palette-primary);
  pointer-events: none;
}

/* ------------------------------------------------------------
   Navigation im Drawer (TO-0050)

   Gegliedert wird in NavMenu.razor -- hier steht nur, was Layout ist: die Spalte,
   die den Konto-Block unten haelt, die Trennlinien zwischen den drei Absichten und
   der Abmelden-Knopf, der als einziger Eintrag ein <button> ist.
   ------------------------------------------------------------ */
.tulidu-navmenu {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  min-height: 0;
}

/* Nimmt den freien Platz und scrollt, wenn die Liste laenger wird als der Drawer.
   min-height: 0 ist noetig, damit ein Flex-Kind ueberhaupt kleiner werden darf als
   sein Inhalt -- ohne das schoebe eine lange Liste den Konto-Block aus dem Bild,
   statt selbst zu scrollen. */
.tulidu-navmenu__main {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
}

/* Einstellungen, Profil, Abmelden: bleiben unten und sind durch eine Schnur-Haarlinie
   abgesetzt -- dieselbe Kante wie an Kopfleiste und Drawer. */
.tulidu-navmenu__account {
  flex: 0 0 auto;
  padding-top: var(--tulidu-space-2);
  border-top: 1px solid var(--mud-palette-lines-default);
}

/* Trennlinien zwischen den Absichten. Hier steht nur der senkrechte Rhythmus: den
   seitlichen Einzug bis auf die Textkante der Eintraege bringt MudBlazors eigener
   DividerType.Middle mit (mud-divider-middle).

   Warum nicht einfach margin: 8px 16px -- ein MudDivider traegt in der Voreinstellung
   mud-divider-fullwidth mit width: 100%, und ein waagrechter Rand kommt bei
   border-box AUSSERHALB dieser Breite dazu. Die Linie war damit 32px breiter als der
   Drawer, was der Menuebereich seit TO-0050 als waagrechten Rollbalken zeigt: er ist
   seither ein Scroll-Container und verschweigt einen Ueberhang nicht mehr. */
.tulidu-nav-divider {
  margin-top: var(--tulidu-space-2);
  margin-bottom: var(--tulidu-space-2);
}

/* Abmelden. Account/Logout ist ein POST-Endpunkt mit Antiforgery-Token, der Eintrag
   deshalb ein <button> in einem <form> und kein Link (s. Kommentar in NavMenu.razor).
   Die Optik kommt aus derselben Klasse wie bei den Nachbarn -- .mud-nav-link steht im
   Markup. Hier stehen nur die Eigenschaften, die ein <button> von sich aus mitbringt
   und die dagegen anlaufen: Schrift erbt er nicht, Rahmen und Textausrichtung bringt
   er selbst mit. Zeilenhoehe, Polsterung und Farbe bleiben bewusst ungenannt -- die
   sollen aus .mud-nav-link kommen, damit dieser Eintrag sich mitbewegt, wenn sich
   seine Nachbarn aendern. */
.tulidu-nav-logout {
  font-family: inherit;
  font-size: inherit;
  border: none;
  text-align: start;
  cursor: pointer;
}

.tulidu-nav-logout-form {
  margin: 0;
}

/* Fuss des Drawers: traegt seit TO-0050 die Versionsangabe (MainLayout.razor).
   flex: 0 0 auto, damit er seine Hoehe behaelt, waehrend die Liste darueber scrollt.
   Die Polsterung von 8px stellt den Knopftext auf dieselbe Kante wie die Beschriftung
   der Eintraege darueber -- der Knopf bringt seinerseits 8px mit. */
.tulidu-drawer-footer {
  flex: 0 0 auto;
  display: flex;
  padding: var(--tulidu-space-2) var(--tulidu-space-2) var(--tulidu-space-3);
}

/* ------------------------------------------------------------
   Item tree (list detail page)

   Approach: every row defines the SAME column template, supplied
   once via the --tulidu-cols custom property on the container. The
   container itself is NOT a grid — each row (and the header) is its
   own independent grid that uses the identical track definition, so
   columns line up across all rows at any nesting depth.

   Why not subgrid / one shared `display: contents` grid: with a
   single shared grid the cells must be *direct* grid items, but
   MudBlazor components emit their own wrapper <div>s, which broke the
   cell-to-track mapping (columns drifted, most visibly on narrow
   screens). With per-row grids sharing one track definition every
   row is a real, self-contained element with guaranteed identical
   column widths — no dependency on subgrid support — and a row can
   render an optional second line locally without disturbing the grid.
   ------------------------------------------------------------ */

.tulidu-tree {
  /* Titel | Status | Priorität | Fällig | Aktionen (ohne Auswahl-Spalte).
     Defined once here and consumed by every row via var(--tulidu-cols).
     The selection column is added by --selectable below. */
  /* Aktionen-Spalte 84px: Platz für „Mein Tag"-Sonnen-Icon + Aktionsmenü (REQ-14-007). */
  --tulidu-cols: minmax(200px, 1fr) minmax(160px, 220px) 130px 120px 84px;
  /* Trennlinie zwischen zwei ITEMS (TO-0025) — bewusst separat von den übrigen, unverändert
     schwachen Innenlinien (Kopfzeile, Spalten-internes). Nutzt MudBlazors LinesInputs statt
     TableLines: gleiche Palette, aber standardmässig kräftiger (rgba(0,0,0,0.23) statt 0.12) und
     trotzdem theme-bewusst (folgt automatisch Light/Dark). Ein einziger Wert an einer Stelle,
     damit sich die Stärke später leicht nachjustieren lässt. */
  --tulidu-item-boundary: var(--mud-palette-lines-inputs);
  width: 100%;
  border-top: 1px solid var(--mud-palette-table-lines);
}

/* Batch-Modus: Auswahl-Spalte (40px) vorne einblenden. */
.tulidu-tree--selectable {
  --tulidu-cols: 40px minmax(200px, 1fr) minmax(160px, 220px) 130px 120px 84px;
}

/* Auf mittleren Bildschirmen (< 900px): Priorität + Fällig ausblenden → 3 Spalten (ohne Auswahl). */
@media (max-width: 899px) {
  .tulidu-tree {
    --tulidu-cols: minmax(160px, 1fr) minmax(140px, 200px) 84px;
  }
  .tulidu-tree--selectable {
    --tulidu-cols: 40px minmax(160px, 1fr) minmax(140px, 200px) 84px;
  }
}

/* Auf kleinen Bildschirmen (< 600px): auch Status ausblenden → 2 Spalten (ohne Auswahl). */
@media (max-width: 599px) {
  .tulidu-tree {
    --tulidu-cols: minmax(120px, 1fr) 84px;
  }
  .tulidu-tree--selectable {
    --tulidu-cols: 40px minmax(120px, 1fr) 84px;
  }
}

/* Vorlagenmodus (TO-0053): Status und Fällig werden in ItemTree/ItemRow gar nicht erst
   gerendert — der Status wird beim Anwenden zurückgesetzt, das Fälligkeitsdatum verworfen
   (REQ-15-002). Also entfallen auch ihre Spuren: Titel | Priorität | Aktionen.
   Bewusst weggelassen statt per display:none versteckt — ein leeres Raster mit
   Spaltenüberschriften über nichts wäre für Screenreader schlechter, nicht besser.
   Diese Regeln stehen NACH den obigen: gleiche Spezifität, die spätere gewinnt. */
.tulidu-tree--template {
  --tulidu-cols: minmax(200px, 1fr) 130px 84px;
}
.tulidu-tree--template.tulidu-tree--selectable {
  --tulidu-cols: 40px minmax(200px, 1fr) 130px 84px;
}

/* < 900px: Priorität ist --hide-md und fällt ebenfalls weg → Titel | Aktionen. */
@media (max-width: 899px) {
  .tulidu-tree--template {
    --tulidu-cols: minmax(160px, 1fr) 84px;
  }
  .tulidu-tree--template.tulidu-tree--selectable {
    --tulidu-cols: 40px minmax(160px, 1fr) 84px;
  }
}

/* < 600px: unverändert zwei Spalten, nur mit engerem Titel. */
@media (max-width: 599px) {
  .tulidu-tree--template {
    --tulidu-cols: minmax(120px, 1fr) 84px;
  }
  .tulidu-tree--template.tulidu-tree--selectable {
    --tulidu-cols: 40px minmax(120px, 1fr) 84px;
  }
}

/* Each row is an independent grid using the shared column template,
   so all rows align identically regardless of nesting depth.
   width:100% is required: a grid container otherwise shrinks to its
   content, leaving no free space for the 1fr title track to expand
   into — which made rows narrower than the list and broke alignment.

   background + margin-top (TO-0025): jedes Item bekommt einen sehr dezenten, EINHEITLICHEN
   Farbton (keine Abwechslung/Zebra — das erste Zwischenergebnis mit alternierender Bänderung
   wirkte gerade durch den Kontrast zwischen den Bändern zu auffällig) plus etwas Abstand zum
   vorherigen Item. Gilt für JEDE Zeile unabhängig von der Tiefe, nicht nur für Wurzel-Items —
   auch Einträge in Unterlisten sollen sich klar voneinander abheben. Zusammen ergibt Farbton +
   Lücke ein „Insel"-Gefühl je Item, ohne dass Nachbar-Items optisch ineinanderlaufen. */
/* align-items:stretch (statt center, TO-0036) laesst alle Zellen die volle Zeilenhoehe
   der Zeile einnehmen. Mit center sass jede Zelle nur so hoch wie ihr eigener Inhalt und
   wurde innerhalb der (durch die hoechste Zelle bestimmten) Zeilenspur zentriert - sobald
   eine Beschreibung die Titelzelle mehrzeilig machte, lag ihr eigener border-bottom (s.
   .tulidu-tree-cell) dadurch tiefer als der der kuerzeren Nachbarzellen, und die Trennlinie
   der Zeile riss sichtbar auseinander ("Versatz"). Betraf nur Zeilen ohne Schnellzugriffs-
   Leiste bzw. ohne sichtbares Zusatzband, weil dort deren eigener, zeilenbreiter
   border-bottom die einzelnen Zellgrenzen ueberdeckte (s. .tulidu-tree-row--has-quickactions
   unten). stretch behebt das an der Wurzel, exakt wie bereits bei .tulidu-tree-headrow
   weiter oben - jede Zelle bleibt dank ihres eigenen align-items:center (display:flex)
   optisch vertikal zentriert, nur ihre Box (und damit der border-bottom) reicht jetzt bis
   zum wahren unteren Rand der Zeile. */
.tulidu-tree-row {
  display: grid;
  grid-template-columns: var(--tulidu-cols);
  align-items: stretch;
  width: 100%;
  /* Seit TO-0048 der eigene Insel-Ton statt der abgesenkten Flaeche (Begruendung am Token). */
  background: var(--tulidu-item-surface);
  /* Seit TO-0045 aus dem Dichte-Token statt fest 6px -- der Wert der Grundstufe ist
     unverändert 6px. */
  margin-top: var(--tulidu-tree-row-gap);
}

/* Sichtbarer Fokus für die Tastatur-Navigation im Baum (TO-0013, tulido.itemNav in app.js).
   Zeile und Zelle sind reine Container ohne eigenes natives Fokus-Aussehen — ohne diese Regel
   sähe ein sehender Tastaturbenutzer nicht, wo er sich befindet (WCAG 2.4.7).

   :focus-visible statt :focus mit Absicht: beide tragen tabindex="-1" (die Zeile ausser der
   einen Roving-Zeile), und ein Element mit tabindex="-1" nimmt bei einem MAUSKLICK trotzdem
   den Fokus an — mit :focus bliebe nach jedem Klick in die Liste ein Rahmen stehen. Da der
   Fokus hier immer aus einem laufenden keydown-Handler heraus gesetzt wird, werten Chrome und
   Firefox ihn als tastaturbedingt und wenden :focus-visible an.

   outline-offset negativ: die Zeile spannt die volle Listenbreite, ein aussenliegender Rahmen
   würde am Rand abgeschnitten. */
.tulidu-tree-row:focus-visible,
.tulidu-tree-cell:focus-visible,
.tulidu-tree-secondary-item:focus-visible,
.tulidu-tree-bandcell:focus-visible {
  outline: 2px solid var(--mud-palette-primary);
  outline-offset: -2px;
  border-radius: 2px;
}

/* The header uses the same shared column template.
   align-items:stretch (statt center) lässt alle Kopf-Zellen die volle Zeilenhöhe
   einnehmen — sonst kollabiert die „Aktionen"-Zelle (nur out-of-flow .sr-only-Inhalt)
   auf reine Padding-Höhe und ihr border-bottom säße höher als bei den Text-Zellen.

   Klebrig beim Scrollen (TO-0048): In einer langen Liste scrollten die Spaltentitel oben
   heraus, und ab da musste man sich merken, welche Spalte welche ist. position:sticky
   haelt sie an der oberen Fensterkante.

   Warum das hier ohne weiteres Zutun funktioniert: Die Seite scrollt im Dokument, nicht in
   einem eigenen Container -- die Kopfleiste steht mit Fixed="false" im Fluss (s.
   MainLayout) und scrollt selbst mit, und weder .tulidu-tree noch eine Zelle darueber
   traegt overflow. Eine dieser drei Bedingungen zu brechen (ein overflow:auto irgendwo im
   Layout, eine fixe Kopfleiste) haette den Kopf lautlos wieder mitscrollen lassen; deshalb
   steht der Grund hier und nicht nur die Regel.

   Eigene Flaeche, weil ein durchsichtiger Kopf die Zeilen unter sich durchscheinen liesse.
   Papier und nicht die abgesenkte Flaeche der Zeilen: der Baum steht auf dem Seitengrund.
   z-index:1 reicht -- die Zeilen darunter sind nicht positioniert. Ueber Dialogen, Menues
   und Popovers liegt der Kopf damit nicht, die rendert MudBlazor weit hoeher. */
.tulidu-tree-headrow {
  display: grid;
  grid-template-columns: var(--tulidu-cols);
  align-items: stretch;
  width: 100%;
  position: sticky;
  top: 0;
  z-index: 1;
  background: var(--mud-palette-background);
}

/* Header row cells. Flex, damit der Text trotz stretch vertikal zentriert bleibt;
   die border-bottom aller Zellen liegt dadurch auf einer Höhe. */
.tulidu-tree-head {
  display: flex;
  align-items: center;
  font-weight: 600;
  color: var(--mud-palette-text-secondary);
  padding: 8px;
  border-bottom: 1px solid var(--mud-palette-table-lines);
}

/* Body cells. The row-bottom border is drawn on each cell so it spans
   the full grid width even though there is no real <tr> element. */
.tulidu-tree-cell {
  /* Senkrechter Innenabstand und Mindesthöhe kommen seit TO-0045 aus den Dichte-Token;
     die Grundstufe trägt unverändert 3px und 32px. Der WAAGRECHTE Abstand bleibt fest:
     er hält die Spalten voneinander frei und hat mit der Dichte nichts zu tun. */
  padding: var(--tulidu-tree-row-padding-y) 8px;
  min-height: var(--tulidu-tree-row-min-height);
  display: flex;
  align-items: center;
  border-bottom: 1px solid var(--tulidu-item-boundary);
  overflow: hidden;
  /* A grid item's default min-width is `auto`, so a long non-wrapping title
     would force the title cell wider than its 1fr track and push the
     following columns out of alignment (rows with truncated titles drifted
     while short-title rows stayed put). min-width:0 lets the cell shrink to
     its track width and the title truncate with the ellipsis instead. */
  min-width: 0;
}

/* Row carries a quick-actions bar (see .tulidu-tree-quickactions below) as its very last
   visual element — the border-bottom that normally closes the row moves there, so the row
   doesn't draw a double line above the bar. Mirrors the existing has-secondary/md pattern. */
.tulidu-tree-row--has-quickactions .tulidu-tree-cell,
.tulidu-tree-row--has-quickactions .tulidu-tree-secondary {
  border-bottom: none;
}

/* MudText/MudTypography (z.B. Priorität „Hoch", Fälligkeitsdatum) bringt von Haus aus
   Material-Typografie-Margins mit (margin-top/-bottom auf dem <p>). Diese blähten die
   betroffenen Zellen über die 32px-Zeilenhöhe hinaus, sodass deren border-bottom tiefer
   sass als bei Nachbarzellen ohne Text → die Trennlinie „fiel auseinander" (sichtbar v.a.
   in der Prioritäts-Spalte). Margin hier neutralisieren, damit alle Zellen gleich hoch sind. */
.tulidu-tree-cell .mud-typography {
  margin: 0;
  line-height: 1.2;
}

/* When the secondary line is actually visible (see breakpoints below),
   the primary cells must not draw their own bottom border — the border
   belongs to the secondary line so the whole row reads as one band.
   Coupled to breakpoint visibility so a row never loses its border at a
   width where the secondary line is hidden. */

/* Select cell (bulk checkbox) — compact, centred. */
.tulidu-tree-cell--select {
  justify-content: center;
  padding: 4px;
}

/* Title cell holds the expander, checkbox, title and (below) description,
   so it stacks vertically.

   Registerlinien (TO-0048): Die Verschachtelung steckte bis hierher allein in der
   padding-left der Titelzeile -- die Tiefe war zaehlbar, aber nicht sichtbar. Jede Ebene
   bekommt jetzt zusaetzlich eine senkrechte Haarlinie am linken Rand ihres Einzugsschritts.

   Warum ein Hintergrundverlauf und kein <span> je Ebene: Ein Element je Ebene waere ein
   zusaetzlicher Knoten in JEDER Zeile, und es laege in der Titel-ZEILE -- die Linie endete
   damit neben der Beschreibung, statt an ihr entlangzulaufen. Der Verlauf liegt auf der
   ganzen ZELLE, reicht ueber Titel- und Beschreibungszeile und kostet keinen Knoten.

   Beide Masse kommen als Custom Property je Zeile aus ItemRow und nicht von hier: den
   Einzug schreibt die Komponente ohnehin schon als padding-left, und dieselbe Zahl an zwei
   Stellen waere die Stelle, an der Linie und Text irgendwann auseinanderlaufen. Auf einer
   Wurzelzeile ist der Einzug 0px -- die Flaeche des Verlaufs ist dann leer, und es wird
   nichts gezeichnet.

   background-position: die Zelle hat 8px waagrechten Innenabstand, dort beginnt der Einzug.
   Die Luecke zwischen zwei Zeilen (--tulidu-tree-row-gap, der Insel-Abstand aus TO-0025)
   unterbricht die Linie sichtbar. Das ist hingenommen und nicht zu beheben: ein Hintergrund
   endet an der Kante seines Kastens, und die Luecke gehoert keiner der beiden Zeilen. */
.tulidu-tree-cell--title {
  flex-direction: column;
  align-items: stretch;
  gap: 0;
  background-image: repeating-linear-gradient(to right,
    var(--tulidu-tree-rail) 0, var(--tulidu-tree-rail) 1px,
    transparent 1px, transparent var(--tulidu-tree-indent-step));
  background-repeat: no-repeat;
  background-size: var(--tulidu-tree-indent) 100%;
  background-position: 8px 0;
}

/* Auf-/Zuklapp-Marke (TO-0048). Fester Slot wie Ziehgriff und Erledigt-Kaestchen: er wird
   auch auf Blatt-Zeilen gerendert (dann leer), damit der Titeltext in jeder Zeile an
   derselben Stelle beginnt.

   Nur eine Marke, kein Bedienelement: Auf- und Zugeklappt wird durch einen Klick auf die
   ganze Titelzelle (s. ItemRow) bzw. mit Links/Rechts ueber tulido.itemNav. Die Marke traegt
   deshalb aria-hidden und keinen eigenen Handler -- den Zustand sagt aria-expanded an der
   Zeile an. Ein Button an dieser Stelle waere ein zusaetzlicher Tab-Stopp und eine weitere
   Zelle in der Tastatur-Navigation, fuer eine Handlung, die die Zeile bereits kennt.

   16px statt der 20px der Nachbar-Slots, Icon eine Stufe kleiner: die Titelspalte ist auf
   schmalen Bildschirmen die knappste Stelle des Rasters (minmax(120px, 1fr)). */
.tulidu-tree-expander {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 16px;
  color: var(--mud-palette-text-secondary);
  line-height: 0;
}

.tulidu-tree-expander .mud-icon-root {
  font-size: 1rem;
}

.tulidu-tree-title-line {
  display: flex;
  align-items: center;
  gap: 2px;
  min-width: 0;
}

/* Sublisten-Navigations-Icon: auf Pointer-Geräten (Maus) erst beim Hover sichtbar,
   damit es das Layout im Ruhezustand nicht überfüllt. Auf Touch-Geräten und bei
   Tastaturfokus immer sichtbar — hover ist dort nicht zuverlässig auslösbar.
   Das Icon bleibt im DOM (nicht display:none / visibility:hidden), damit Screen
   Reader und Tastaturnutzer es immer erreichen. opacity:0 allein wäre ein A11y-
   Verstoß (fokussierbar aber unsichtbar) — deshalb zusätzlich pointer-events:none
   im Ruhezustand und voller opacity bei :focus-visible. */
.tulidu-tree-sublist-link {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  color: inherit;
  text-decoration: none;
  border-radius: 4px;
  padding: 2px;
  line-height: 0;   /* verhindert Extra-Höhe durch den <a>-Inline-Kontext */
}

/* Auf Nicht-Folder-Rows: Icon vollständig ausblenden, aus Tab-Reihenfolge entfernt via tabindex=-1 */
.tulidu-tree-sublist-link--hidden {
  display: none;
}

/* Maus-Gerät: im Ruhezustand ausblenden */
@media (hover: hover) and (pointer: fine) {
  .tulidu-tree-sublist-link {
    opacity: 0;
    transition: opacity 0.15s;
  }
  .tulidu-tree-row:hover .tulidu-tree-sublist-link {
    opacity: 0.6;
  }
}

/* Tastaturfokus: immer sichtbar mit Fokusring — gilt auf allen Geräten */
.tulidu-tree-sublist-link:focus-visible {
  opacity: 1 !important;
}

/* ── Tag-Icon (REQ-14-003) ──────────────────────────────────────────────
   Kleines LocalOffer-Icon direkt nach dem Titeltext. Grau ohne Tags,
   sandgelb (#BA7517) wenn Tags vorhanden. Auf Maus-Geräten im Ruhezustand
   halb-transparent; Tastatur: immer voll sichtbar bei :focus-visible. */
.tulidu-tree-tag-icon {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  color: var(--mud-palette-text-disabled);
  cursor: pointer;
  line-height: 0;
  border-radius: 2px;
}

.tulidu-tree-tag-icon--active {
  color: var(--tulidu-tag-icon-active);
}

@media (hover: hover) and (pointer: fine) {
  .tulidu-tree-tag-icon {
    opacity: 0.35;
    transition: opacity 0.15s;
  }
  .tulidu-tree-row:hover .tulidu-tree-tag-icon {
    opacity: 0.7;
  }
  .tulidu-tree-tag-icon--active {
    opacity: 0.75;
  }
  .tulidu-tree-row:hover .tulidu-tree-tag-icon--active {
    opacity: 1;
  }
}

.tulidu-tree-tag-icon:focus-visible {
  opacity: 1 !important;
  outline: 2px solid currentColor;
  outline-offset: 1px;
}

/* Zähler neben dem Etikett-Icon: zeigt die Anzahl zugewiesener Tags als
   kleine hochgestellte Zahl in derselben Farbe wie das Icon. */
.tulidu-tag-icon-count {
  font-size: 9px;
  font-weight: 600;
  line-height: 1;
  align-self: flex-start;
  margin-top: 1px;
  margin-left: 1px;
  color: inherit;
  letter-spacing: 0;
}

/* Freigabe-Kennzeichnung (UX-Verfeinerung REQ-04-008): grün = von mir geteilt,
   orange = mit mir geteilt. box-shadow: inset statt border-left, da .tulidu-tree-row
   Teil des CSS-Grid ist und ein border die Zeilenbreite verändern und die dokumentierte
   Spaltenausrichtung gefährden würde (s. ItemRow.razor.cs). */
.tulidu-share-indicator--by-me {
  box-shadow: inset 4px 0 0 var(--tulidu-share-by-me);
}

.tulidu-share-indicator--with-me {
  box-shadow: inset 4px 0 0 var(--tulidu-share-with-me);
}

.tulidu-share-indicator-icon {
  display: inline-flex;
  align-items: center;
  flex: 0 0 auto;
}

/* ── Umsortieren per Drag & Drop (REQ-03-006) ────────────────────────────
   Nur bei „Standard"-Sortierung sinnvoll/verfügbar (s. ListDetailViewModel.
   IsDragDropAvailable) — der zugehörige Griff wird in ItemRow ohnehin nur
   dann gerendert. Drop-Zonen als box-shadow: inset (wie die Freigabe-
   Kennzeichnung) statt border/Hintergrund, damit weder Zeilenbreite noch
   -höhe sich ändern und die dokumentierte Spaltenausrichtung intakt bleibt. */

/* Fixed-width slot for the drag handle, analog to .tulidu-tree-done — the
   title text must start at the same x whether or not the handle is shown. */
.tulidu-tree-drag {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 20px;
}

.tulidu-tree-drag-handle {
  display: inline-flex;
  align-items: center;
  color: var(--mud-palette-text-disabled);
  cursor: grab;
  line-height: 0;
  opacity: 0.45;
}

.tulidu-tree-row:hover .tulidu-tree-drag-handle {
  opacity: 0.8;
}

.tulidu-tree-drag-handle:active {
  cursor: grabbing;
}

/* The row currently being dragged — dimmed so the drop target underneath reads clearly. */
.tulidu-tree-row--dragging {
  opacity: 0.4;
}

/* Drop indicators — shown on the row currently under the pointer while dragging.
   Blue (distinct from the green/orange share indicators) so the two meanings never clash. */
.tulidu-tree-row--drop-before {
  box-shadow: inset 0 3px 0 0 var(--tulidu-drop-indicator);
}

.tulidu-tree-row--drop-after {
  box-shadow: inset 0 -3px 0 0 var(--tulidu-drop-indicator);
}

.tulidu-tree-row--drop-into {
  box-shadow: inset 0 0 0 2px var(--tulidu-drop-indicator);
  background-color: var(--tulidu-drop-into-surface);
}

/* Fixed-width slot for the done-checkbox so the title text always starts
   at the same x position, independent of the MudCheckBox wrapper width. */
.tulidu-tree-done {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
}

/* MudCheckBox has internal padding (Material touch target) that inflates
   the row height. Strip it so the checkbox sits flush in the compact row. */
.tulidu-tree-done .mud-button-root {
  padding: 0 !important;
}

/* Optimistisches Feedback für den Done-Checkbox-Klick (gefühlte Geschwindigkeit bei
   langsamer/mobiler Verbindung): tulido.optimistic (app.js) setzt diese Klasse rein
   clientseitig, SOFORT beim Klick, ohne auf die Server-Antwort zu warten — und hebt
   sie wieder auf, sobald der Roundtrip abgeschlossen ist (ItemRow.razor.cs) oder nach
   einem Sicherheits-Timeout. pointer-events: none verhindert dabei genau die Doppel-
   Bedienung, die während der Wartezeit sonst provoziert würde. Bewusst kein optimistisch
   vorweggenommener Checked-Zustand (MudCheckBox rendert intern per SVG/Blazor-State —
   ein visuell "vorgetäuschtes" Häkchen könnte bei einem Fehlschlag falsch stehen bleiben);
   stattdessen nur ein neutrales "wird bearbeitet"-Signal. */
.tulidu-tree-row--pending .tulidu-tree-done {
  pointer-events: none;
  animation: tulidu-pending-pulse 1s ease-in-out infinite;
}

@keyframes tulidu-pending-pulse {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.35; }
}

@media (prefers-reduced-motion: reduce) {
  .tulidu-tree-row--pending .tulidu-tree-done {
    animation: none;
    opacity: 0.5;
  }
}

.tulidu-tree-title-text {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  /* flex: 1 1 auto entfernt — der Text soll nur so breit sein wie nötig,
     damit das Sublisten-Icon direkt dahinter sitzt statt am rechten Rand.
     min-width:0 bleibt damit text-overflow:ellipsis greift. */
  min-width: 0;
  flex: 0 1 auto;
}

.tulidu-tree-title-text--done {
  text-decoration: line-through;
  color: var(--mud-palette-text-secondary);
}

/* Beschreibungszeile (TO-0031): Text + optionale Ellipsis-Schaltfläche in einer Flex-Zeile,
   die den vollständigen Text im ItemDescriptionDialog öffnet. */
.tulidu-tree-desc-row {
  display: flex;
  align-items: center;
  gap: 2px;
}

.tulidu-tree-desc {
  font-style: italic;
  font-size: 0.8em;
  color: var(--mud-palette-text-secondary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  /* min-width: 0 erlaubt text-overflow: ellipsis trotz Flex-Kontext (gleiches Muster wie
     .tulidu-tree-title-text). */
  min-width: 0;
}

/* Faellig-Spalte rechtsbuendig (TO-0048). Das Datum steht seit TO-0043 in der Datenschrift
   mit Tabellenziffern (s. .tulidu-due-row__date) -- erst rechtsbuendig stehen Tag, Monat und
   Jahr in allen Zeilen wirklich untereinander, und eine Spalte, in der man Daten vergleicht,
   ist genau dafuer da. Kopf- und Datenzelle tragen dieselbe Ausrichtung, sonst zeigt die
   Ueberschrift auf eine andere Kante als die Werte darunter.

   Betrifft nur die Spalte: unterhalb von 900px wandert das Datum in das Zusatzband, wo es
   in einer Zeile mit Status und Prioritaet steht und linksbuendig richtig ist. */
.tulidu-tree-cell--due,
.tulidu-tree-head--due {
  justify-content: flex-end;
}

/* Actions cell aligns its menu button to the right.
   padding-top/bottom: 0 — the icon-button is 26px and fits in the 32px row
   without extra vertical padding. */
.tulidu-tree-cell--actions {
  justify-content: center;
  padding: 0 4px;
}

/* MudChip default margin (4px) inflates the status cell beyond the 32px row
   height (3px cell-padding + 4px chip-margin + 24px chip + 4px + 3px = 38px).
   Strip the vertical margin so the chip stays within the compact row.

   Seit TO-0048 steht kein MudChip mehr in einer Baumzelle -- der Status ist dort eine Keyline
   (s. .tulidu-status-key). Die Regel bleibt trotzdem stehen: sie kostet nichts und faengt den
   naechsten Chip ab, der in einer Zelle landet, statt die Zeilenhoehe kommentarlos zu
   sprengen. */
.tulidu-tree-cell .mud-chip {
  margin: 0;
}

/* Sub-list (folder) rows get a slightly heavier title. */
.tulidu-tree-row--folder .tulidu-tree-title-text {
  font-weight: 600;
}

/* Folder title cell is clickable to expand/collapse — show pointer cursor. */
.tulidu-tree-cell--title-folder {
  cursor: pointer;
  user-select: none;
}

/* ------------------------------------------------------------
   Secondary line (mobile / narrow screens)
   When columns are hidden by the media queries, their content is
   shown here instead, on a second line. It starts at the title
   column (grid-column 2), i.e. aligned under the title and indented
   past the selection checkbox — not flush to the far left. Runs to
   the end of the row. Hidden by default; revealed per breakpoint.
   ------------------------------------------------------------ */
.tulidu-tree-secondary {
  display: none; /* shown only when there is hidden content to surface */
  grid-column: 1 / -1; /* spans full row; left indent via inline padding-left from ItemRow */
  padding: 0 8px 4px 8px;
  gap: 8px;
  flex-wrap: wrap;
  align-items: center;
  border-bottom: 1px solid var(--tulidu-item-boundary);
}

.tulidu-tree-secondary-item {
  font-size: 0.8em;
  color: var(--mud-palette-text-secondary);
}

/* ------------------------------------------------------------
   Schnellzugriffs-Icon-Leiste (Sichtbarkeit der Zeilen-Bedienelemente)
   Eigene Zeile unter jedem Item, unabhängig von der Bildschirmbreite (kein Breakpoint-Gating
   wie bei .tulidu-tree-secondary) — sichtbar sobald mindestens ein Schalter oberhalb der
   Sortierzeile aktiv ist (s. ItemRow.razor: HasQuickActions). Übernimmt als letztes Element
   der Zeile deren unteren Trennstrich, s. .tulidu-tree-row--has-quickactions oben.
   ------------------------------------------------------------ */
.tulidu-tree-quickactions {
  grid-column: 1 / -1;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 2px;
  padding: 2px 8px 4px 8px;
  border-bottom: 1px solid var(--tulidu-item-boundary);
}

/* Sublisten-Icon in der Schnellzugriffsleiste ist ein <a>, kein MudIconButton (echte
   Navigation) — an Grösse/Innenabstand der MudIconButton-Nachbarn angeglichen. */
.tulidu-tree-quickaction-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  color: inherit;
  text-decoration: none;
  border-radius: 50%;
}

.tulidu-tree-quickaction-btn:hover,
.tulidu-tree-quickaction-btn:focus-visible {
  background-color: var(--mud-palette-action-default-hover);
}

/* Umsortieren-Block (Nach oben/unten verschieben, Einrücken, Ausrücken): optisch als
   zusammengehörige Gruppe abgesetzt — linke Trennlinie + etwas Abstand zu den Einzelaktionen. */
.tulidu-tree-quickaction-group {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  margin-left: 6px;
  padding-left: 6px;
  border-left: 1px solid var(--mud-palette-table-lines);
}

/* Zellen-Wrapper der zeilenbreiten Bänder (TO-0013): jedes Schnellzugriffs-Icon ist eine eigene
   `role="gridcell"`, damit die Pfeiltasten-Navigation dort genauso greift wie in den Spalten
   (Begründung s. Kopfkommentar von ItemRow.razor).

   `display: inline-flex` ist Pflicht und nicht bloss Kosmetik: `display: contents` — sonst der
   naheliegende Weg für einen reinen Struktur-Wrapper — nimmt dem Element die Box und damit
   browserweit die Fokussierbarkeit (dieselbe Falle wie bei MudBlazors .mud-menu-activator,
   s. CLAUDE.md). Der Wrapper muss fokussierbar bleiben, sonst ist die ganze Umstellung wirkungslos.
   Ohne eigene Abstände, damit das gap der Leiste die Abstände weiterhin allein bestimmt. */
.tulidu-tree-bandcell {
  display: inline-flex;
  align-items: center;
}

/* Responsive: hide header and body cells on small/medium screens.
   These classes mirror the media-query breakpoints above so the
   column count in the grid and the visible cells always match. */

/* Status column: visible by default, hidden < 600px (small). */
.tulidu-tree-cell--hide-sm,
.tulidu-tree-head--hide-sm {
  display: flex; /* visible by default */
}

/* Priorität + Fällig columns: visible by default, hidden < 900px (medium). */
.tulidu-tree-cell--hide-md,
.tulidu-tree-head--hide-md {
  display: flex; /* visible by default */
}

/* Secondary-line items only show the metadata that the current
   breakpoint has hidden from the columns. */
.tulidu-tree-secondary-item--md,
.tulidu-tree-secondary-item--sm {
  display: none;
}

/* < 900px (medium): Priorität + Fällig leave the columns and appear
   in the secondary line. Only rows that actually have md-content carry
   the `--md` class, so no empty band appears. */
@media (max-width: 899px) {
  .tulidu-tree-cell--hide-md,
  .tulidu-tree-head--hide-md {
    display: none;
  }

  .tulidu-tree-secondary--md {
    display: flex;
  }

  .tulidu-tree-secondary-item--md {
    display: inline-flex;
  }

  /* Md-secondary band is visible here → its cells hand the bottom border
     to the band so the row reads as one. */
  .tulidu-tree-row--has-secondary:has(.tulidu-tree-secondary--md) .tulidu-tree-cell {
    border-bottom: none;
  }
}

/* ------------------------------------------------------------
   SortBar — horizontale Sortierleiste
   ------------------------------------------------------------ */

.tulidu-sort-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px;
  margin-bottom: 8px;
  padding: 2px 0;
}

/* Sichtbarkeits-Schalter für Zeilen-Bedienelemente (Navigation/Kommentare/Untereintrag/
   Bearbeiten/Löschen), oberhalb der Sortierzeile. Teilt das Label-Aussehen mit .tulidu-sort-bar. */
.tulidu-row-controls-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px;
  margin-bottom: 4px;
  padding: 2px 0;
}

/* Aktiver Zustand der Sichtbarkeits-Schalter oberhalb der Sortierzeile: MudToggleIconButton
   ändert im Toggled-Zustand nur die Icon-Farbe (ToggledColor) — auf einen Blick zu unauffällig.
   Ergänzt einen deutlich sichtbaren, gefüllten Kreis-Hintergrund, analog zu Material „selected
   icon button". Wird zusammen mit aria-pressed gesetzt (s. ItemTree.razor). */
.tulidu-row-controls-btn--active {
  background-color: var(--mud-palette-primary) !important;
}

.tulidu-row-controls-btn--active .mud-icon-root {
  color: var(--mud-palette-primary-text) !important;
}

.tulidu-sort-label {
  font-size: 0.78rem;
  color: var(--mud-palette-text-secondary);
  margin-right: 2px;
  white-space: nowrap;
}

.tulidu-sort-btn {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  padding: 2px 8px;
  font-size: 0.78rem;
  line-height: 1.5;
  border: 1px solid var(--mud-palette-lines-default);
  border-radius: 12px;
  background: transparent;
  color: var(--mud-palette-text-primary);
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s;
  white-space: nowrap;
}

.tulidu-sort-btn:hover,
.tulidu-sort-btn:focus-visible {
  background: var(--tulidu-surface-sunken);
  border-color: var(--mud-palette-primary);
  outline: none;
}

.tulidu-sort-btn--active {
  background: var(--mud-palette-primary);
  border-color: var(--mud-palette-primary);
  color: var(--mud-palette-primary-text);
  font-weight: 600;
}

.tulidu-sort-btn--active:hover,
.tulidu-sort-btn--active:focus-visible {
  background: var(--mud-palette-primary-darken);
  border-color: var(--mud-palette-primary-darken);
}

.tulidu-sort-btn--reset {
  padding: 2px 6px;
  font-size: 0.72rem;
  opacity: 0.65;
}

/* < 600px (small): Status additionally leaves its column and joins
   the secondary line. Status-only rows reveal their band here (they
   carry `--smonly` instead of `--md`). */
@media (max-width: 599px) {
  .tulidu-tree-cell--hide-sm,
  .tulidu-tree-head--hide-sm {
    display: none;
  }

  .tulidu-tree-secondary--smonly {
    display: flex;
  }

  .tulidu-tree-secondary-item--sm {
    display: inline-flex;
  }

  /* < 600px: any visible secondary band (md or smonly) takes the border. */
  .tulidu-tree-row--has-secondary:has(.tulidu-tree-secondary) .tulidu-tree-cell {
    border-bottom: none;
  }
}

/* ────────────────────────────────────────────────────────────
   Fälligkeitsfarbe (TO-0042)
   Eine Klasse je Dringlichkeitsstufe, geliefert von
   ItemPresentationMud.DueDateClass(). Vorher lieferte dieselbe Stelle einen
   Inline-Style mit festem Hex-Wert; den kann kein Theme übersteuern.

   Nicht zu verwechseln mit .tulidu-due-row* direkt darunter -- das ist das
   Layout der Zeile in „Mein Tag", hier geht es allein um die Farbe. Deshalb
   auch die zwei Bindestriche: .tulidu-due--overdue ist eine Ausprägung von
   „Fälligkeit", nicht ein Teil von .tulidu-due-row.

   Getragen wird die Klasse vom umschliessenden Element (dem <span> im
   DueDateField, dem MudText auf der Listenkarte); Icon und Text darin holen
   sich die Farbe über MudBlazors Color.Inherit, das als color: inherit
   !important gerendert wird.
   ──────────────────────────────────────────────────────────── */
.tulidu-due--overdue {
  color: var(--tulidu-due-overdue);
}

.tulidu-due--urgent {
  color: var(--tulidu-due-urgent);
}

.tulidu-due--soon {
  color: var(--tulidu-due-soon);
}

/* ────────────────────────────────────────────────────────────
   DueItemRow — flache, read-only Zeile der Fälligkeitsübersicht
   auf der Home-Seite. Anders als der Baum (.tulidu-tree-*) keine
   Spaltenausrichtung über Zeilen hinweg: eine kompakte Karte je Item.

   Hintergrundton + Radius (TO-0025, gleiches Muster wie .tulidu-tree-row): jedes Item bekommt
   denselben sehr dezenten, einheitlichen Farbton wie im Item-Baum — dieselbe Variable, damit
   Baum und flache Listen (Home/Mein Tag/Tag-Filter) optisch konsistent bleiben. Seit TO-0048 ist
   das --tulidu-item-surface und nicht mehr die abgesenkte Fläche; die Variable ist dieselbe
   geblieben, nur heller — und weil sie dieselbe ist, zieht diese Zeile ohne Zutun mit. Passt hier sogar
   noch besser zum bestehenden „Karte je Item"-Konzept (s. Kommentar oben) als im Baum, da bereits
   abgerundete Ecken sinnvoll sind. Whitespace zwischen Items kommt weiterhin vom bestehenden
   `<MudDivider Class="my-2">` in Home/MyDay/TagFilter.razor (dort ebenfalls von my-1 auf my-2
   angehoben, analog zum 6px margin-top im Baum) — der Divider selbst bleibt in der
   MudBlazor-Standardfarbe, keine Übernahme von --tulidu-item-boundary hier (liesse sich ohne
   Zugriff auf die kompilierte MudBlazor.dll nicht gegen die tatsächliche Divider-Klasse
   verifizieren, s. CLAUDE.md „MudBlazor 9" — Komponenten-Klassennamen vor Verwendung prüfen). */
.tulidu-due-row {
  padding: 6px 8px;
  background: var(--tulidu-item-surface);
  border-radius: 6px;
}

/* Hauptzeile: Titel (flexibel) + Metadaten (Datum, Priorität) rechts. */
.tulidu-due-row__main {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
}

/* ────────────────────────────────────────────────────────────
   Umsortieren in „Mein Tag" (TO-0024) — Ziehgriff + Drop-Indikatoren, analog
   .tulidu-tree-drag-handle/--dragging/--drop-before/--drop-after, aber für die
   Karten-Zeile hier statt das Grid-Layout des Baums. Eigene Klassen (kein Teilen mit
   .tulidu-tree-*), da tulido.myDayDnd bewusst ein eigenständiges JS-Modul ist. */
.tulidu-due-row__drag-handle {
  display: inline-flex;
  align-items: center;
  color: var(--mud-palette-text-disabled);
  cursor: grab;
  line-height: 0;
  opacity: 0.45;
}

.tulidu-due-row--reorderable:hover .tulidu-due-row__drag-handle {
  opacity: 0.8;
}

.tulidu-due-row__drag-handle:active {
  cursor: grabbing;
}

.tulidu-due-row__reorder-actions {
  display: inline-flex;
  align-items: center;
  flex: 0 0 auto;
}

/* Die gezogene Zeile — gedimmt, damit das Ziel darunter deutlich lesbar bleibt. */
.tulidu-due-row--dragging {
  opacity: 0.4;
}

/* Drop-Indikatoren — dieselbe Farbe wie im Item-Baum (s. .tulidu-tree-row--drop-*), damit
   „hier wird eingefügt" in der ganzen Anwendung einheitlich aussieht. */
.tulidu-due-row--drop-before {
  box-shadow: inset 0 3px 0 0 var(--tulidu-drop-indicator);
}

.tulidu-due-row--drop-after {
  box-shadow: inset 0 -3px 0 0 var(--tulidu-drop-indicator);
}

.tulidu-due-row__title {
  flex: 1 1 auto;
  min-width: 0;            /* erlaubt Ellipsis statt Überlauf */
  font-weight: 600;
}

/* Gitterzellen der flachen Zeile (TO-0014). Die Hüllen sind rein strukturell: sie tragen
   role="gridcell", damit die Pfeiltasten-Navigation etwas zum Anspringen hat, und verhalten sich
   im Flex-Layout der Zeile wie das Element, das sie umschliessen. Bewusst inline-flex und nicht
   display:contents -- Letzteres wäre naheliegend, nimmt dem Element aber jede Fläche, und
   tulido.itemNav hält ein Element ohne offsetParent für nicht bedienbar und überspränge die
   Zelle. */
.tulidu-due-row__cell {
  display: inline-flex;
  align-items: center;
  flex: 0 0 auto;
}

/* Die Titelzelle übernimmt den Platz, den vorher der Titel-Link selbst im Flex-Layout hatte
   (flexibel, schrumpfbar bis zur Ellipsis); der Link darin füllt sie aus. */
.tulidu-due-row__title-cell {
  display: flex;
  align-items: center;
  flex: 1 1 auto;
  min-width: 0;
}

/* Sichtbarer Fokus in der Gitter-Fassung der Zeile (TO-0014) -- dieselbe Marke wie im Item-Baum,
   s. .tulidu-tree-row:focus-visible. Zeile und Zellen sind nur fokussierbar, wo die Zeile in
   einem ItemSummaryList steht; ohne Gitter fehlen die Rollen und die Regel greift nicht. */
.tulidu-due-row[role="row"]:focus-visible,
.tulidu-due-row [role="gridcell"]:focus-visible {
  outline: 2px solid var(--mud-palette-primary);
  outline-offset: -2px;
  border-radius: 2px;
}

.tulidu-due-row__date {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  white-space: nowrap;
}

.tulidu-due-row__date-icon {
  flex: 0 0 auto;
}

/* „Erledigt"-Kurzweg-Checkbox — analog .tulidu-tree-done: MudCheckBox bringt eigenes
   Material-Touch-Target-Padding mit, das die kompakte Kartenzeile sonst unnötig aufbläht. */
.tulidu-due-row__done .mud-button-root {
  padding: 0 !important;
}

.tulidu-due-row__priority {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 20px;    /* fester Slot — hält das Datum zeilenübergreifend ausgerichtet */
  flex: 0 0 20px;
}

/* Breadcrumb-Zeile: kleiner, gedämpft (dezentes Grau), unter dem Titel.
   Bewusst farblich zurückhaltend, damit sie nicht vom Item-Titel ablenkt. */
.tulidu-due-row__breadcrumb {
  margin-top: 2px;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 2px;
  color: var(--mud-palette-text-secondary);
}

.tulidu-due-row__breadcrumb-link {
  color: var(--mud-palette-text-secondary) !important;
}

.tulidu-due-row__breadcrumb-sep {
  opacity: 0.6;
  user-select: none;
}

/* ────────────────────────────────────────────────────────────
   DatePicker-Popover (DueDateField-Baustein).
   Auf Desktop ankert es am Cursor (PositionAtCursor). Auf schmalen
   Screens würde das 260px breite Popover am rechten Rand abgeschnitten
   — dort zentrieren wir es stattdessen mittig im Viewport.
   MudBlazor setzt die Position inline (top/left) auf dem .mud-popover-
   Element, daher die !important-Overrides; nur unter 600px aktiv.
   ──────────────────────────────────────────────────────────── */
@media (max-width: 599px) {
  .tulidu-date-popover.mud-popover {
    position: fixed !important;
    top: 50% !important;
    left: 50% !important;
    transform: translate(-50%, -50%) !important;
    max-width: calc(100vw - 24px);
    max-height: calc(100vh - 24px);
    overflow: auto;
  }
}

/* ────────────────────────────────────────────────────────────
   Ziel-Item-Hervorhebung: wird per JS gesetzt, wenn der Benutzer
   von der Home-Fälligkeitsübersicht zu einem Item navigiert
   (?highlight={id}). Blasses Grün, über 1,5 s sanft verblassend.
   Kurze Haltephase (~25 %) vor dem Ausklang nimmt die Unruhe;
   ease-in-out sorgt für ein weiches, gleichmässiges Verblassen.
   prefers-reduced-motion: keine Animation, nur kurzer statischer Hint.
   ──────────────────────────────────────────────────────────── */
/* Der Grünton kommt seit TO-0043 aus der Palette: --mud-palette-primary-rgb liefert
   das Primär-Grün als Zahlentripel, damit es sich mit einer Deckkraft mischen lässt.
   Vorher stand hier das Logo-Grün rgba(76,175,80,…) — eine Farbe, die sonst nirgends
   in der Oberfläche vorkommt und im dunklen Theme stehen geblieben wäre. */
@keyframes tulidu-highlight-fade {
  0%   { background-color: rgba(var(--mud-palette-primary-rgb), 0.35); }  /* blasses Grün */
  25%  { background-color: rgba(var(--mud-palette-primary-rgb), 0.35); }  /* kurz halten */
  100% { background-color: transparent; }
}

.tulidu-row-highlight {
  animation: tulidu-highlight-fade 1.5s ease-in-out;
}

@media (prefers-reduced-motion: reduce) {
  .tulidu-row-highlight {
    animation: none;
    background-color: rgba(var(--mud-palette-primary-rgb), 0.20);
  }
}

/* ────────────────────────────────────────────────────────────
   NavMenu-Badge: Anzahl offener Freundschaftsanfragen (REQ-17-002).
   ──────────────────────────────────────────────────────────── */
.tulidu-nav-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  margin-left: 8px;
  border-radius: 9px;
  background-color: var(--tulidu-badge-surface);
  color: var(--tulidu-badge-text);
  font-size: 11px;
  font-weight: 600;
  line-height: 1;
}

/* ────────────────────────────────────────────────────────────
   Rechte-Gating (UX-Verfeinerung REQ-04-008, 0.13.0): disabled
   Buttons/Menüeinträge dezent statt farbig-aber-blass darstellen.
   MudBlazor lässt Disabled-Elemente standardmässig in ihrer ursprünglichen
   Farbe (z.B. rotes Löschen-Icon) nur leicht transparent — das wirkt bei
   berechtigungsbedingt gesperrten Aktionen unruhig/alarmierend, obwohl
   nichts falsch ist. Hier wird die Farbe stattdessen auf den neutralen
   "text-disabled"-Ton der Palette vereinheitlicht.
   Deckt sowohl die native :disabled-Pseudoklasse ab (MudButton/MudIconButton
   rendern ein echtes <button>-Element) als auch die .mud-disabled-Klasse
   (MudMenuItem ist kein natives Formularelement, MudBlazor markiert den
   deaktivierten Zustand dort über eine CSS-Klasse statt des Attributs).
   ──────────────────────────────────────────────────────────── */
.mud-icon-button:disabled,
.mud-icon-button.mud-disabled,
.mud-button-root:disabled,
.mud-button-root.mud-disabled,
.mud-menu-item.mud-disabled,
.mud-menu-item:disabled {
  color: var(--mud-palette-text-disabled) !important;
  opacity: 0.6;
}

.mud-icon-button:disabled .mud-icon-root,
.mud-icon-button.mud-disabled .mud-icon-root,
.mud-button-root:disabled .mud-icon-root,
.mud-button-root.mud-disabled .mud-icon-root,
.mud-menu-item.mud-disabled .mud-icon-root,
.mud-menu-item:disabled .mud-icon-root {
  color: var(--mud-palette-text-disabled) !important;
}

/* ────────────────────────────────────────────────────────────
   Benachrichtigungen (REQ-04-009): ungelesene Zeile leicht abgesetzt,
   die Nachricht selbst ist ein natives <button> (statt MudLink — dessen
   OnClick-Unterstützung ist nicht zuverlässig, ein natives Element ist
   ausserdem per Default tastaturbedienbar), optisch aber wie ein Link.
   ──────────────────────────────────────────────────────────── */
.tulidu-notification--unread {
  background-color: var(--mud-palette-action-default-hover);
}

.tulidu-notification-link {
  background: none;
  border: none;
  padding: 0;
  margin: 0;
  font: inherit;
  color: var(--mud-palette-primary);
  text-decoration: underline;
  cursor: pointer;
  text-align: left;
}

.tulidu-notification-link:hover,
.tulidu-notification-link:focus-visible {
  text-decoration: none;
}

/* ────────────────────────────────────────────────────────────
   Kommentare (REQ-03-017)
   Volle Bearbeitungsansicht: CommentSection/CommentItem (nur Listendetail,
   im CommentDialog). Read-only Vorschau: CommentBadge (überall sonst).
   Reaktions-Buttons sind native <button> statt MudButton — brauchen
   individuelles Padding/Layout, das mit MudButtons Innenabständen
   kollidieren würde; nativ bleiben sie trotzdem per Default fokussierbar
   und per Tastatur bedienbar.
   ──────────────────────────────────────────────────────────── */

.tulidu-comments {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.tulidu-comments-heading {
  margin: 0;
  font-size: 1.1rem;
  font-weight: 600;
}

.tulidu-comment-compose,
.tulidu-comment-edit,
.tulidu-comment-reply-compose {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.tulidu-comment-compose-actions {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 8px;
  flex-wrap: wrap;
}

/* Live-Vorschau (TO-0033) neben Editor, Bearbeiten- und Antwort-Feld — MudGrid uebernimmt das
   Nebeneinander/Stapeln je nach Breite, hier nur die Innengestaltung des Panels selbst. */

/* MudGrid arbeitet mit negativen Raendern (Bootstrap-Technik) und erwartet normalerweise einen
   block-artigen Elternknoten, dessen Padding diese Raender auffaengt. .tulidu-comments und
   article.tulidu-comment sind aber selbst "display: flex; flex-direction: column" — ohne
   min-width: 0 haelt ein Flex-Kind an seiner intrinsischen (durch die negativen Raender
   verbreiterten) Breite fest und sprengt so den umschliessenden Dialog nach rechts (gemeldeter
   Bug: Vorschau-Spalte wurde am Dialogrand abgeschnitten, nicht nur schmal). Klassischer
   Flexbox-Fallstrick, s. https://css-tricks.com/flexbox-truncated-text/ fuer den Mechanismus. */
.tulidu-comment-preview-grid {
  min-width: 0;
}

.tulidu-comment-preview {
  height: 100%;
  min-width: 0;
}

.tulidu-comment-preview-heading {
  display: block;
  margin-bottom: 4px;
  color: var(--mud-palette-text-secondary);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.tulidu-comment-preview-content {
  min-height: 2.5em;
}

.tulidu-comment-list,
.tulidu-comment-replies {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.tulidu-comment-replies {
  margin-top: 8px;
  margin-left: 24px;
  padding-left: 12px;
  border-left: 2px solid var(--mud-palette-lines-default);
}

.tulidu-comment {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 10px 12px;
  border-radius: 8px;
  background: var(--tulidu-surface-sunken);
}

.tulidu-comment--reply {
  background: var(--mud-palette-surface);
}

.tulidu-comment-header {
  display: flex;
  align-items: center;
  gap: 8px;
}

.tulidu-comment-meta {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-width: 0;
}

.tulidu-comment-author {
  font-weight: 600;
}

.tulidu-comment-timestamp {
  font-size: 0.8rem;
  color: var(--mud-palette-text-secondary);
}

.tulidu-comment-content {
  overflow-wrap: break-word;
}

.tulidu-comment-content p {
  margin: 0 0 8px 0;
}

.tulidu-comment-content p:last-child {
  margin-bottom: 0;
}

.tulidu-comment-content ul,
.tulidu-comment-content ol {
  margin: 0 0 8px 0;
  padding-left: 24px;
}

.tulidu-comment-content blockquote {
  margin: 0 0 8px 0;
  padding-left: 12px;
  border-left: 3px solid var(--mud-palette-lines-default);
  color: var(--mud-palette-text-secondary);
}

.tulidu-comment-content code {
  background: var(--tulidu-surface-sunken);
  padding: 1px 4px;
  border-radius: 4px;
  font-family: monospace;
}

/* Kommentar-Bilder (REQ-03-017): begrenzt, damit ein grosses Foto nicht die
   ganze Kommentarspalte sprengt — Klick öffnet die Originalgrösse in einem
   neuen Tab (natives Verhalten von <img> in <a>, hier bewusst ohne Link-
   Wrapper: das Bild selbst ist bereits über seine src erreichbar). */
.tulidu-comment-image {
  max-width: 100%;
  max-height: 320px;
  border-radius: 6px;
  display: block;
  margin: 4px 0;
}

.tulidu-mention {
  background: var(--mud-palette-primary-hover);
  color: var(--mud-palette-primary);
  border-radius: 4px;
  padding: 0 4px;
  font-weight: 600;
}

.tulidu-comment-reactions {
  display: flex;
  align-items: center;
  gap: 4px;
  flex-wrap: wrap;
}

.tulidu-reaction-btn {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  background: var(--mud-palette-surface);
  border: 1px solid var(--mud-palette-lines-default);
  border-radius: 12px;
  padding: 2px 8px;
  font-size: 0.85rem;
  cursor: pointer;
  color: inherit;
}

.tulidu-reaction-btn:hover,
.tulidu-reaction-btn:focus-visible {
  background: var(--mud-palette-action-default-hover);
}

.tulidu-reaction-btn--active {
  background: var(--mud-palette-primary-hover);
  border-color: var(--mud-palette-primary);
}

/* ────────────────────────────────────────────────────────────
   CommentBadge (REQ-03-017): kompaktes, überall einsetzbares
   Kennzeichen ausserhalb der Listendetail-Ansicht.
   ──────────────────────────────────────────────────────────── */

.tulidu-comment-badge {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  background: none;
  border: none;
  padding: 2px;
  cursor: pointer;
  color: inherit;
}

.tulidu-comment-badge-count {
  font-size: 0.75rem;
  font-weight: 600;
}

.tulidu-comment-badge-tooltip {
  max-width: 320px;
}

.tulidu-comment-badge-preview {
  display: flex;
  flex-direction: column;
  gap: 8px;
  text-align: left;
}

.tulidu-comment-badge-preview-item {
  display: flex;
  flex-direction: column;
  gap: 2px;
  font-size: 0.85rem;
}

/* ────────────────────────────────────────────────────────────
   QuickAddBar (TO-0018 Phase 4, REQ-18-011 bis REQ-18-023): dauerhaft sichtbare
   Schnell-Erfassungsleiste am Kopf der Eintragsliste (Components/Pages/QuickAddBar.razor).
   Die Klasse .tulidu-quickadd auf dem Wurzel-Element ist zugleich der Marker, über den
   tulido.itemNav (app.js) diese Leiste von der Baumnavigation ausnimmt — nicht umbenennen,
   ohne die JS-Seite mitzuziehen.
   ──────────────────────────────────────────────────────────── */

.tulidu-quickadd {
  margin-bottom: 1rem;
}

.tulidu-quickadd-row {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: 8px;
}

.tulidu-quickadd-field {
  flex: 1 1 240px;
}

/* Breiter als früher (200px): seit TO-0072 steht in der Zielebene der ganze Pfad
   ("Wochenende › Obst") statt nur des eingerückten Titels. */
.tulidu-quickadd-target {
  flex: 0 1 280px;
}

/* Vorschlagszeile (REQ-18-020): dauerhaft sichtbare Schaltflächen statt aufklappender Liste —
   s. Doc-Kommentar in QuickAddBar.razor für die Entscheidung dagegen. */
.tulidu-quickadd-suggestions {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 8px;
}

/* Schlanke Pille statt MudChip: die Zeile ist reines HTML (echte <button>-Elemente, damit
   Enter/Leertaste ohne Zutun funktionieren, s. QuickAddBar.razor.cs), keine MudBlazor-Komponente. */
.tulidu-quickadd-suggestion {
  font: inherit;
  font-size: 0.8125rem;
  color: var(--mud-palette-text-primary);
  background: var(--tulidu-surface-sunken);
  border: 1px solid var(--mud-palette-lines-default);
  border-radius: 999px;
  padding: 4px 12px;
  cursor: pointer;
}

.tulidu-quickadd-suggestion:hover {
  background: var(--mud-palette-action-default-hover);
}

.tulidu-quickadd-suggestion:disabled {
  cursor: default;
  opacity: 0.5;
}

/* :focus-visible statt :focus mit Absicht — gleiche Begründung wie bei .tulidu-tree-row:
   ein Klick soll keinen stehenbleibenden Rahmen hinterlassen, nur echte Tastaturnavigation. */
.tulidu-quickadd-suggestion:focus-visible {
  outline: 2px solid var(--mud-palette-primary);
  outline-offset: 2px;
}

/* Dubletten-Hinweis (REQ-18-023): Platz bleibt über min-height auch im "hidden"-Zustand
   reserviert (s. visibility-Umschaltung in QuickAddBar.razor), damit die Leiste beim Ein- und
   Ausblenden nicht springt. */
.tulidu-quickadd-hint {
  min-height: 1.25rem;
  margin-top: 4px;
  font-size: 0.8125rem;
  color: var(--mud-palette-warning-darken);
}

/* ============================================================
   FÄLLIGKEITSBAND DER STARTSEITE (TO-0049)
   ------------------------------------------------------------
   Vierzehn Tage waagrecht, je Tag ein Balken in der Höhe der fälligen Items; die
   überfälligen stehen als Anker links davor, weil sie ausserhalb der Achse liegen und
   trotzdem das Dringendste sind.

   Warum Grid und nicht Flexbox für die Balken: alle vierzehn Spalten müssen exakt gleich
   breit sein, sonst liest man aus dem Abstand zweier Tage etwas heraus, das nicht dasteht.
   grid-template-columns: repeat(N, 1fr) garantiert das; bei Flexbox hinge die Breite am
   Inhalt der einzelnen Spalte (der Spitzenwert steht nur über einem Balken).

   Die Höhe der Balkenfläche kommt als Inline-Style aus der Komponente — sie ist ein
   Messwert und kein Gestaltungsmittel und kann deshalb nicht aus einer Klasse kommen.
   Farbe und alles Übrige stehen hier.
   ------------------------------------------------------------ */
.tulidu-due-band__body {
  display: flex;
  align-items: stretch;
  gap: 16px;
}

/* Anker: die überfälligen Items. Eigene Schaltfläche, damit die Liste darunter auch auf
   sie eingeschränkt werden kann — der häufigste Griff auf dieser Seite. */
.tulidu-due-band__anchor {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  gap: 2px;
  flex: 0 0 auto;
  min-width: 5.5rem;
  padding: 8px 12px;
  border: 1px solid var(--mud-palette-lines-default);
  border-radius: 8px;
  background: var(--tulidu-surface-sunken);
  color: var(--tulidu-due-overdue);
  cursor: pointer;
}

/* Ohne überfällige Items ist der Anker eine Zustandsanzeige und kein Alarm — die Warnfarbe
   wäre hier eine Falschmeldung. Bedienbar bleibt er trotzdem (er filtert dann auf nichts,
   was ehrlicher ist als eine tote Schaltfläche). */
.tulidu-due-band__anchor--empty {
  color: var(--mud-palette-text-secondary);
}

.tulidu-due-band__anchor--selected {
  border-color: var(--mud-palette-primary);
  box-shadow: inset 0 0 0 1px var(--mud-palette-primary);
}

.tulidu-due-band__anchor:hover {
  background: var(--mud-palette-action-default-hover);
}

.tulidu-due-band__anchor:focus-visible {
  outline: 2px solid var(--mud-palette-primary);
  outline-offset: 2px;
}

.tulidu-due-band__anchor-label {
  font-size: 0.75rem;
  color: var(--mud-palette-text-secondary);
}

.tulidu-due-band__anchor-count {
  font-size: 1.5rem;
  line-height: 1.1;
}

.tulidu-due-band__plot {
  display: flex;
  align-items: stretch;
  gap: 8px;
  flex: 1 1 auto;
  min-width: 0;
}

/* Massstab: nur Höchstwert und Null. Zwischenwerte wären bei ungerader Spitze gerundet und
   damit eine Zahl, die so nirgends vorkommt. */
.tulidu-due-band__scale {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  align-items: flex-end;
  height: 6.5rem;
  font-size: 0.75rem;
  color: var(--mud-palette-text-secondary);
}

.tulidu-due-band__track {
  flex: 1 1 auto;
  min-width: 0;
}

.tulidu-due-band__bars {
  display: grid;
  grid-template-columns: repeat(var(--tulidu-due-band-days, 14), 1fr);
  align-items: end;
  gap: 4px;
  height: 6.5rem;
  border-bottom: 1px solid var(--mud-palette-lines-default);
}

/* Die ganze Spalte ist die Schaltfläche, nicht nur der gefärbte Teil: ein Tag ohne fällige
   Items hätte sonst gar keine Trefferfläche, und gerade der ist einen Klick wert, wenn man
   prüfen will, ob dort wirklich nichts liegt. */
.tulidu-due-band__bar {
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  align-items: stretch;
  height: 100%;
  padding: 0;
  border: 0;
  background: transparent;
  cursor: pointer;
}

.tulidu-due-band__bar:hover {
  background: var(--mud-palette-action-default-hover);
}

.tulidu-due-band__bar:focus-visible {
  outline: 2px solid var(--mud-palette-primary);
  outline-offset: 2px;
}

.tulidu-due-band__bar--selected {
  background: var(--mud-palette-action-default-hover);
  box-shadow: inset 0 -2px 0 0 var(--mud-palette-primary);
}

.tulidu-due-band__peak {
  font-size: 0.75rem;
  line-height: 1;
  text-align: center;
  color: var(--mud-palette-text-secondary);
}

/* min-height, damit ein einzelnes fälliges Item neben einem hohen Balken nicht auf einen
   unsichtbaren Strich zusammenfällt. */
.tulidu-due-band__fill {
  display: block;
  min-height: 3px;
  border-radius: 2px 2px 0 0;
}

.tulidu-due-band__fill--overdue {
  background: var(--tulidu-due-overdue);
}

.tulidu-due-band__fill--urgent {
  background: var(--tulidu-due-urgent);
}

.tulidu-due-band__fill--soon {
  background: var(--tulidu-due-soon);
}

.tulidu-due-band__fill--later {
  background: var(--tulidu-due-later);
}

.tulidu-due-band__axis {
  display: grid;
  grid-template-columns: repeat(var(--tulidu-due-band-days, 14), 1fr);
  gap: 4px;
  margin-top: 4px;
}

.tulidu-due-band__axis-label {
  font-size: 0.75rem;
  text-align: center;
  color: var(--mud-palette-text-secondary);
}

.tulidu-due-band__legend {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 16px;
  margin: 12px 0 0;
  padding: 0;
  list-style: none;
  font-size: 0.75rem;
  color: var(--mud-palette-text-secondary);
}

.tulidu-due-band__legend li {
  display: flex;
  align-items: center;
  gap: 6px;
}

.tulidu-due-band__dot {
  display: inline-block;
  width: 10px;
  height: 10px;
  border-radius: 50%;
}

/* Auf schmalen Geräten hat ein Tag rund 20 px Breite. Die Wochentagskürzel stünden dann
   übereinander statt nebeneinander; die Textalternative jedes Balkens trägt das Datum
   ohnehin, die Achse ist hier verzichtbar. Der Anker rutscht über das Band, damit die
   Balken die volle Breite behalten. */
@media (max-width: 599px) {
  .tulidu-due-band__body {
    flex-direction: column;
  }

  .tulidu-due-band__anchor {
    flex-direction: row;
    justify-content: space-between;
    width: 100%;
  }

  .tulidu-due-band__axis {
    display: none;
  }
}

/* Die vier Kennzahlen aus REQ-09-009 als eine ruhige Zeile statt als vier Kacheln
   (TO-0049). Zusammengehalten von Trennpunkten; umbricht auf schmalen Geräten. */
.tulidu-kpi-row {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 8px;
  margin: 0;
  color: var(--mud-palette-text-secondary);
}

.tulidu-kpi-row span:not(:last-child)::after {
  content: "·";
  margin-left: 8px;
}

.tulidu-kpi-row strong {
  color: var(--mud-palette-text-primary);
  font-weight: 600;
}

.tulidu-kpi-busiest {
  margin: 4px 0 0;
  font-size: 0.8125rem;
}

/* Überschrift einer Sektion mit einer Schaltfläche am rechten Rand. Stand bislang dreimal
   als Inline-Style auf der Startseite. */
.tulidu-section-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 8px;
}

/* ------------------------------------------------------------
   Leerer Zustand (TO-0052, Komponente EmptyState)

   Der Satz und die Schaltfläche stehen in EINER Zeile — das ist der Punkt der
   Sache: der nächste Schritt liegt dort, wo die Aussage steht, und nicht am
   anderen Ende der Seite. Auf schmalen Geräten bricht die Schaltfläche unter den
   Satz, deshalb flex-wrap statt einer festen Zeile.

   Die Fläche ist die abgesenkte, nicht Papier: ein leerer Bereich soll als
   Zustand lesbar sein und nicht als Karte, in der zufällig nichts steht. Beide
   Farben kommen aus der Palettenrolle, damit das dunkle Theme ohne eigenen
   Block mitgeht.
   ------------------------------------------------------------ */
.tulidu-empty-state {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--tulidu-space-3);
  padding: var(--tulidu-space-4);
  border-radius: var(--tulidu-radius-card);
  background: var(--tulidu-surface-sunken);
}

/* Zeilenlänge begrenzt: die längste dieser Zeilen erklärt „Mein Tag" in zwei
   Sätzen und liefe auf einem breiten Bildschirm sonst quer durch. */
.tulidu-empty-state__text,
.tulidu-empty-state__text.mud-typography {
  flex: 1 1 20ch;
  max-width: 60ch;
  margin: 0;
  color: var(--mud-palette-text-secondary);
}

/* TO-0081: extra space below the page content. On an iPhone 15 Pro (iOS 26.7, home screen app)
   the last three entries of a list could be scrolled into view but snapped back like a rubber
   band as soon as the finger lifted, so they could not be operated. Not reproducible on an
   iPhone SE (iOS 26.5) or on Android; the cause is not proven. The slack keeps the last rows
   clear of whatever sits at the bottom edge of the screen (home indicator, floating toolbar).
   env(safe-area-inset-bottom) is 0 without viewport-fit=cover and only adds to the fixed
   4rem; viewport-fit=cover is deliberately NOT set, because it would also push the page under
   the notch in landscape. Padding-bottom only: the other sides stay with the utility classes
   pt-4 px-4 set in MainLayout. */
.tulidu-main-content {
  padding-bottom: calc(env(safe-area-inset-bottom, 0px) + 4rem);
}
