`, dann Uhrzeit-Span `shrink-0 tabular-nums text-muted-foreground`, dann Titel-Span `min-w-0 break-words`). `cellClass` Z. 220-227 zeigt das Muster Array → `.filter(Boolean).join(' ')` für zusammengesetzte Klassen. Doc-Kommentar Z. 27-55 erwähnt „Zaehl-Plakette“ (Z. 33).
+- calendar-widget.test.tsx: 10 Tests; `ev(id, start, end, extra?)` Z. 44-54 nimmt `Partial
` (also `{ color: '#c44040' }`); `within`, `fireEvent` importiert; Test 3 Z. 121-141 (Plakette zählt), Test 4 Z. 143-166 (Tooltip per `fireEvent.mouseEnter` auf `[data-date="2026-07-20"]`, danach `screen.getByTestId('calendar-day-tooltip')`). Termintitel stehen auch in „Nächste Termine“ im DOM — Tooltip-Abfragen IMMER mit `within(tooltip)`.
+- CalendarEvent (apps/web/src/lib/calendar-api.ts Z. 41-51): `color?: string`.
+- SOURCE_COLOR_PALETTE (calendar-source-form.tsx Z. 12-21): #c44040, #40a060, #4060c4, #8040c4, #c49040, #409090, #c44080, #808080 — alle mittlere Töne, weiße Schrift lesbar.
+- globals.css: 127 Zeilen, `@import "tailwindcss"` Z. 1, `@custom-variant dark` Z. 22, `@theme inline` Z. 24-50, Tokens, `body` Z. 115-119, `.app-shell-main`-Media-Block Z. 121-126 (Dateiende). Kein `@layer`, kein `.wmde-markdown`.
+- markdown.css (node_modules/.pnpm/@uiw+react-markdown-preview@5.2.1_*/node_modules/@uiw/react-markdown-preview/markdown.css): Z. 477-481 `.wmde-markdown ul, .wmde-markdown ol { margin 0; padding-left: 2em }` ohne list-style; Z. 483-485 `ol ol, ul ol → lower-roman`; Z. 636-638 `.wmde-markdown div > ol:not([type]) → decimal` (nur ol, ul hat nichts); Z. 878-880 `.wmde-markdown .task-list-item { list-style-type: none }`; Z. 893-895 `.wmde-markdown .contains-task-list input[type='checkbox']` (Klassennamen bestätigt: `contains-task-list` am ul, `task-list-item` am li).
+- CHANGELOG.md `## Unveröffentlicht`: `### Geändert` hat einen Punkt (Kalenderquellen Adressfeld), `### Behoben` hat zwei (Notiz-Widget Listen abhaken, Textbereich Hell/Dunkel). Neue Punkte jeweils als letzte Zeile des Abschnitts anhängen.
+- Testbasis: `pnpm --filter @tessera/web exec vitest run` = 52 Dateien / 347 Tests; Skripte `test`/`type-check` in apps/web/package.json vorhanden.
+
+
+
+
+
+ Task 1: Kalender-Plakette in Kalenderfarbe, Farbpunkt im Tooltip, Sortierung je Tag + Tests
+ apps/web/src/components/dashboard/widgets/calendar-month.ts, apps/web/src/components/dashboard/widgets/calendar-month.test.ts, apps/web/src/components/dashboard/widgets/calendar-widget.tsx, apps/web/src/components/dashboard/widgets/calendar-widget.test.tsx
+
+ - calendar-month.test.ts Test 2b: `groupEventsByDate` mit e2 (20.07. 14:00) VOR e1 (20.07. 09:00) in der Eingabe → `grouped.get('2026-07-20')?.map((e) => e.id)` ist `['e1', 'e2']` (Sortierung nach Start; Test 2 bleibt unverändert grün).
+ - calendar-widget.test.tsx Test 3b „Plakette traegt die Kalenderfarbe des fruehesten Termins, Tooltip-Zeilen mit Farbpunkt“: fetchEvents liefert `ev('Lunch', 20.07. 14:00-15:00, { color: '#4060c4' })` ZUERST und `ev('Team Meeting', 20.07. 09:00-10:00, { color: '#c44040' })` danach. Plakette `within(day20).getByTestId('calendar-day-count')`: `toHaveTextContent('2')`, `toHaveStyle({ backgroundColor: '#c44040' })`, `toHaveClass('text-white')`, `not.toHaveClass('bg-primary')`. Dann `fireEvent.mouseEnter(day20)`; im Tooltip `within(tooltip).getAllByTestId('tooltip-color-dot')` hat Länge 2, Punkt [0] `toHaveStyle({ backgroundColor: '#c44040' })`, Punkt [1] `toHaveStyle({ backgroundColor: '#4060c4' })`; `tooltip.textContent.indexOf('Team Meeting')` ist kleiner als `indexOf('Lunch')` (Reihenfolge nach Startzeit).
+ - calendar-widget.test.tsx Test 3c „Plakette ohne Kalenderfarbe behaelt bg-primary“: ein Termin am 21.07. ohne `color`. Plakette `toHaveClass('bg-primary')`, `toHaveClass('text-primary-foreground')`, `not.toHaveClass('text-white')`, `badge.style.backgroundColor` ist `''`. Nach `mouseEnter`: genau ein `tooltip-color-dot` vorhanden (Rückfallfarbe `var(--muted-foreground)` NICHT per toHaveStyle prüfen — jsdom löst Custom Properties nicht auf).
+ - Sollte `toHaveStyle({ backgroundColor: '#c44040' })` in jsdom wider Erwarten nicht greifen, ersatzweise `expect(badge.style.backgroundColor).toBe('rgb(196, 64, 64)')` (jsdom normalisiert hex zu rgb) — Erwartung ändern, nicht die Implementierung.
+
+
+ Reihenfolge RED → GREEN: erst die drei Tests aus `` schreiben und laufen lassen (müssen fehlschlagen), dann implementieren.
+
+ 1. calendar-month.ts, `groupEventsByDate` (Z. 106-114): nach dem Sammeln jede Tagesgruppe nach Start aufsteigend sortieren — Komparator wie in `selectUpcomingEvents` (`new Date(a.start).getTime() - new Date(b.start).getTime()`); `Array.prototype.sort` ist stabil, Termine mit gleichem Start behalten die API-Reihenfolge. Doc-Kommentar der Funktion und Kopfkommentar (Starttag-Regel Z. 14-17) um einen Satz ergänzen: Gruppen sind nach Start sortiert, damit Plakettenfarbe (erster Termin) und Tooltip-Reihenfolge deterministisch sind (quick-260916-jvj).
+
+ 2. calendar-widget.tsx, Plakette (Z. 244-251): vor dem `return` der Zelle `const badgeColor = day.events[0]?.color;` bestimmen (Gruppe ist jetzt sortiert, [0] = frühester Termin). Klassenstring nach dem `cellClass`-Muster zusammensetzen: unveränderter Basisteil (`absolute bottom-px right-px flex h-[clamp(10px,3cqw,16px)] min-w-[clamp(10px,3cqw,16px)] items-center justify-center rounded-full px-0.5 text-[clamp(7px,1.8cqw,10px)] font-semibold leading-none`) plus bei `badgeColor` `text-white`, sonst `bg-primary text-primary-foreground`. `style={badgeColor ? { backgroundColor: badgeColor } : undefined}` — ohne Farbe darf KEIN style-Attribut entstehen (Test 3c prüft `''`). `data-testid` bleibt `calendar-day-count`.
+
+ 3. calendar-widget.tsx, Tooltip-Zeile (Z. 314-321): als erstes Kind der `flex gap-2`-Zeile einen Span einfügen mit `data-testid="tooltip-color-dot"`, `className="mt-1 h-2 w-2 shrink-0 rounded-full"`, `style={{ backgroundColor: event.color || 'var(--muted-foreground)' }}`, `aria-hidden="true"` — exakt dieselbe Rückfallregel wie der Listen-Punkt Z. 272-277 (`mt-1` zentriert den 8-px-Punkt in der 16-px-Zeile von `text-xs`). Uhrzeit- und Titel-Span unverändert dahinter.
+
+ 4. Doc-Kommentar calendar-widget.tsx Z. 33 („Zaehl-Plakette an Tagen mit Terminen“) ergänzen: Plakette in der Farbe des Kalenders des fruehesten Termins, sonst Akzentfarbe; Tooltip-Zeilen mit Farbpunkt (quick-260916-jvj). ASCII-Umlaute wie im umgebenden Kommentar (ae/oe/ue), das ist dort Konvention.
+
+ Keine weiteren Änderungen: Liste „Nächste Termine“, Portal, Klemmung, Ladefenster bleiben unangetastet. Commit: `feat(web): Kalender-Plakette in der Farbe des Kalenders, Farbpunkt je Tooltip-Zeile`.
+
+
+ cd /home/vicolab/projects/tessera-ctl && grep -q "tooltip-color-dot" apps/web/src/components/dashboard/widgets/calendar-widget.tsx && grep -q "day.events\[0\]?.color" apps/web/src/components/dashboard/widgets/calendar-widget.tsx && grep -q "Test 3b" apps/web/src/components/dashboard/widgets/calendar-widget.test.tsx && grep -q "Test 3c" apps/web/src/components/dashboard/widgets/calendar-widget.test.tsx && grep -q "Test 2b" apps/web/src/components/dashboard/widgets/calendar-month.test.ts && pnpm --filter @tessera/web exec vitest run src/components/dashboard/widgets/calendar-month.test.ts src/components/dashboard/widgets/calendar-widget.test.tsx && pnpm --filter @tessera/web type-check
+
+ calendar-month.test.ts und calendar-widget.test.tsx komplett grün (10 → 12 Widget-Tests, +1 Month-Test); Plakette bekommt bei `color` Inline-Hintergrund + `text-white`, ohne `color` unverändert `bg-primary text-primary-foreground` ohne style-Attribut; Tooltip-Zeilen mit Farbpunkt in Startzeit-Reihenfolge; tsc 0 Fehler.
+
+
+
+ Task 2: Aufzählungspunkte in Markdown-Ansichten (globals.css), CHANGELOG, voller Testlauf
+ apps/web/src/app/globals.css, CHANGELOG.md
+
+ 1. globals.css: ans Dateiende (nach dem `.app-shell-main`-Media-Block Z. 121-126) einen Block anhängen, eingeleitet von einem kurzen deutschen Kommentar (Muster der bestehenden Kommentare, ASCII-Umlaute wie dort): Tailwind-Preflight setzt `ul, ol { list-style: none }` in `@layer base`, markdown.css von @uiw/react-markdown-preview stellt es nicht wieder her — deshalb fehlten auf „Was ist neu“ und in der Notiz-Vorschau die Punkte; ungeschichtete Regel hier schlägt die Layer-Regel; Aufgabenlisten bleiben ohne Punkt (quick-260916-jvj). Danach genau diese vier Regeln, je eine Zeile: `.wmde-markdown ul { list-style: disc; }` — `.wmde-markdown ul ul { list-style: circle; }` — `.wmde-markdown ol { list-style: decimal; }` — `.wmde-markdown ul.contains-task-list, .wmde-markdown li.task-list-item { list-style: none; }`. Kein `@layer`, kein `!important`, keine weiteren Selektoren. Klassennamen `contains-task-list`/`task-list-item` sind gegen markdown.css Z. 878/894 bestätigt.
+
+ 2. CHANGELOG.md, Abschnitt `## Unveröffentlicht`: unter `### Geändert` als letzte Zeile `- Kalender-Widget: Plakette am Tag in der Farbe des Kalenders` anhängen; unter `### Behoben` als letzte Zeile `- „Was ist neu“ und Notiz-Ansicht: Aufzählungspunkte wieder sichtbar` anhängen. Typografische Anführungszeichen „…“ wie im Bestand, kein Punkt am Zeilenende, Überschriften zeichengenau unverändert, kein CRLF.
+
+ 3. Volle Gates laufen lassen (siehe verify). Kein `biome check` (bekannter Konfigurationsfehler, biome.json nicht anfassen), kein Docker-Build, kein Deploy, kein Testserver, kein `git push`. Commit: `fix(web): Aufzählungspunkte in Markdown-Ansichten (Was ist neu, Notiz) wieder sichtbar; Changelog`.
+
+ In der SUMMARY vermerken: Plakettenfarbe = frühester Termin des Tages (bei mehreren Quellen an einem Tag keine Mischung, bewusst einfach); `groupEventsByDate` sortiert jetzt (war vorher API-Reihenfolge); CSS-Block ist bewusst ungeschichtet, weil Preflight in `@layer base` liegt.
+
+
+ cd /home/vicolab/projects/tessera-ctl && grep -q '^\.wmde-markdown ul { list-style: disc; }' apps/web/src/app/globals.css && grep -q '^\.wmde-markdown ul ul { list-style: circle; }' apps/web/src/app/globals.css && grep -q '^\.wmde-markdown ol { list-style: decimal; }' apps/web/src/app/globals.css && grep -q '^\.wmde-markdown ul\.contains-task-list, \.wmde-markdown li\.task-list-item { list-style: none; }' apps/web/src/app/globals.css && grep -q 'quick-260916-jvj' apps/web/src/app/globals.css && grep -qx -- '- Kalender-Widget: Plakette am Tag in der Farbe des Kalenders' CHANGELOG.md && grep -qx -- '- „Was ist neu“ und Notiz-Ansicht: Aufzählungspunkte wieder sichtbar' CHANGELOG.md && grep -qx '## Unveröffentlicht' CHANGELOG.md && ! grep -q $'\r' CHANGELOG.md && pnpm --filter @tessera/web type-check && pnpm --filter @tessera/web exec vitest run
+
+ globals.css enthält die vier Listen-Regeln mit Kommentar am Dateiende; CHANGELOG.md hat beide neuen Stichpunkte in den richtigen Abschnitten; `type-check` Exit 0; `vitest run` komplett grün mit 52 Dateien / 350 Tests (Umlaut-Wächter 3/3, changelog.test.ts grün eingeschlossen).
+
+
+
+
+
+## Trust Boundaries
+
+| Boundary | Description |
+|----------|-------------|
+| API → Browser (event.color) | Farbwert stammt aus der gespeicherten Kalenderquelle (Formular-Palette, im Backend als String abgelegt) und landet als Inline-`backgroundColor` im DOM |
+| Markdown → DOM | Bereits durch `rehypeSanitize` abgedeckt (260916-dcz/iex); dieser Auftrag ändert nur CSS, keine Sanitizer-Konfiguration |
+
+## STRIDE Threat Register
+
+| Threat ID | Category | Component | Severity | Disposition | Mitigation Plan |
+|-----------|----------|-----------|----------|-------------|-----------------|
+| T-JVJ-01 | Tampering | calendar-widget.tsx Inline-Stil aus `event.color` | low | accept | React setzt `style.backgroundColor` als Eigenschaftswert (kein HTML, kein `url()`-Kontext); ungültige Werte verwirft der Browser. Identische Nutzung besteht bereits beim Listen-Farbpunkt (Z. 275). Keine neue Angriffsfläche. |
+| T-JVJ-02 | Information Disclosure | globals.css `.wmde-markdown`-Regeln | low | accept | Reines Styling ohne Datenfluss; Selektoren wirken nur innerhalb des Markdown-Containers. |
+| T-JVJ-SC | Tampering | npm/pnpm installs | low | accept | Keine Paketinstallation in diesem Auftrag (nur Quell- und CSS-Änderungen). |
+
+
+
+- `pnpm --filter @tessera/web type-check` → Exit 0
+- `pnpm --filter @tessera/web exec vitest run` → 52 Dateien / 350 Tests grün (Basis 347: +2 calendar-widget, +1 calendar-month); darin Umlaut-Wächter 3/3 und changelog.test.ts
+- grep-Gates aus beiden Tasks (Plakette `day.events[0]?.color`, `tooltip-color-dot`, vier CSS-Regeln, zwei CHANGELOG-Zeilen, kein CRLF)
+- Kein biome, kein Docker, kein Deploy, kein Push
+
+
+
+- Plakette im Monatsraster zeigt die Kalenderfarbe des frühesten Termins des Tages (weiße Schrift), ohne Farbe unverändert Akzentfarbe
+- Tooltip-Zeilen mit Farbpunkt (gleiche Rückfallregel wie die Liste), Reihenfolge nach Startzeit
+- „Was ist neu“ und Notiz-Vorschau zeigen Aufzählungspunkte; Aufgabenlisten mit Kästchen bleiben ohne Punkt
+- CHANGELOG.md um zwei kurze Stichpunkte ergänzt
+- Alle Gates grün, zwei Commits, kein Push
+
+
+