# Oikos — Farbpaletten-Redesign-Vorschlag

**Status:** Implementiert ✅ · **Datum:** 2026-04-19 · **Scope:** `tokens.css`, `reminders.css`, `dashboard.css`, `tasks.css`, `tasks.js`, `glass.css`, `layout.css`, `index.html`, `oikos-install-prompt.js`
**Bezugsdokumente:** `.interface-design/system.md`, `docs/SPEC.md` (Section „Design System")
**Hinweis:** Der im Ausgangs-Briefing genannte Pfad `docs/redesign-spec.md` existiert nicht im Repo. Als Ausgangspunkt dienen `system.md` (verbindliche Design-Intention) und der bereits in `tokens.css` umgesetzte Akzent-Wechsel auf `#2563EB`.

---

## 1. Design-Rationale

**Status quo (Stärken, die erhalten bleiben).** Oikos besitzt bereits eine sehr gute Grundentscheidung: eine warm-getönte Neutral-Skala (`#FAFAF8 → #121211`) statt kaltem Corporate-Grau. Diese „Leinen/unbleached paper"-Atmosphäre trägt die Intention des `system.md` („well-organized family kitchen — warm, practical, never sterile"). Daran wird nicht gerüttelt.

**Schwächen, die der Vorschlag adressiert.** Drei konkrete Probleme:

1. **Generischer Primary-Akzent.** `#2563EB` ist das Tailwind-Default-Blau und wirkt austauschbar — es transportiert „SaaS-Dashboard", nicht „familiäre Wärme". Die Spanne zwischen dem warmen Neutral-Fundament und dem kühlen Blau ist tonal unversöhnt.
2. **Semantische Kollisionen in Modul-Akzenten.** Vier Rollen teilen sich `#B45309` (Warning, Priority-Medium, Meals, Meal-Breakfast). Zwei teilen `#D4511E` (Shopping, Priority-High). Eine Badge mit dieser Farbe ist nicht mehr eindeutig dekodierbar. `system.md` sieht „semantic accent colors tied to life domain" vor — Domain und Severity müssen trennbar bleiben.
3. **Dark-Mode-Akzent driftet von Light-Mode-Identität ab.** Light: `#2563EB` (Indigo-Blau). Dark: `#60A5FA` (helles Himmelblau). Das ist nicht bloß eine Helligkeits-Anpassung, sondern ein Hue-Shift.

**Leitprinzipien.**
- **Wärmebias konsequent durchziehen.** Primary bewegt sich vom neutralen Blau in Richtung Indigo mit leichtem Violett-Drall. Indigo trägt Seriosität eines Planers und verbindet sich farblich mit dem bestehenden `--module-calendar` (Violett) und `--color-accent-secondary` (`#7C5CFC`). Referenz: Things 3, Notion-Accents.
- **Module entflechten.** Domain-Farben (Module, Mahlzeiten) werden von Severity-Farben (Warning/Danger/Priority) hue-getrennt. Keine Doppelbelegungen ohne dokumentierten Grund.
- **Kontrast gegen AA puffern, nicht nur erfüllen.** Mehrere aktuelle Paarungen liegen knapp über 4.5:1 (Accent auf Weiß: 4.56:1). Ein `--color-btn-primary` für Flächen mit weißem Text hält ≥ 6:1, damit Normaltext robust lesbar bleibt.
- **Dark Mode als tonale Inversion, nicht als separates System.** Akzent-Hue bleibt gleich, nur Lightness/Saturation werden angepasst.

**Abgrenzung zu Referenz-Kategorien.**
- *Cozi/FamilyWall* (familiär) → zu laut für einen Self-Hoster. Oikos übernimmt die Wärme, aber nicht die Pastell-Fröhlichkeit.
- *Todoist/Notion/Things 3* (Produktivität) → Oikos übernimmt Neutral-Dominanz und einen Signature-Akzent.
- *Nextcloud/Home Assistant* (Self-Hosted) → Oikos übernimmt technische Solidität (stabile Tokens, WCAG, dark mode), aber nicht deren funktional-kühle Palette.

Die Schnittmenge: **Things 3 × Tandoor** — warmer Papiergrund, klare Module, ein charaktervoller Primary. Genau dort positioniert sich der Vorschlag.

---

## 2. Palette

Alle Werte primär in HSL (Präzision, leichter anzupassen), Hex in Klammern. Unveränderte Tokens sind explizit als „beibehalten" markiert.

### 2.1 Neutral-Skala (Light Mode)

| Token | Aktuell | Neu | Rolle | Begründung |
|---|---|---|---|---|
| `--neutral-50` | `hsl(60, 20%, 98%)` (`#FAFAF8`) | *beibehalten* | Lowest surface | Bereits gute Wärme, funktioniert als Inset-Surface. |
| `--neutral-100` | `hsl(45, 17%, 95%)` (`#F5F4F1`) | *beibehalten* | Canvas/BG | Trägt die Wärmeidentität, kein Grund zur Änderung. |
| `--neutral-150` | `hsl(45, 17%, 92%)` (`#EFEEE9`) | *beibehalten* | Subtle border / surface-3 | |
| `--neutral-200` | `hsl(45, 13%, 89%)` (`#E8E7E2`) | *beibehalten* | Default border | |
| `--neutral-250` | `hsl(45, 11%, 86%)` (`#DDDCD7`) | *beibehalten* | | |
| `--neutral-300` | `hsl(50, 7%, 81%)` (`#D1D0CB`) | *beibehalten* | Disabled text | |
| `--neutral-400` | `hsl(48, 5%, 70%)` (`#B5B4AF`) | *beibehalten* | | |
| `--neutral-500` | `hsl(45, 3%, 54%)` (`#8E8D89`) | *beibehalten* | Mid-tone | Identisch in Light/Dark — Grenzfall, aber gewollt für kontinuierliche Mittelwerte. |
| `--neutral-600` | `hsl(45, 3%, 41%)` (`#6C6B67`) | *beibehalten* | Secondary text | 5.0:1 auf Weiß — AA konform. |
| `--neutral-700` | `hsl(45, 3%, 29%)` (`#4A4A46`) | *beibehalten* | | |
| `--neutral-800` | `hsl(45, 4%, 18%)` (`#2E2E2B`) | *beibehalten* | | |
| `--neutral-900` | `hsl(60, 6%, 11%)` (`#1C1C1A`) | *beibehalten* | Primary text | |
| `--neutral-950` | `hsl(60, 5%, 7%)` (`#121211`) | *beibehalten* | | |

**Resultat Neutral-Skala:** Unverändert. Sie ist bereits exakt der Tone-of-Voice des Designs.

### 2.2 Semantische Neutral-Aliase

| Token | Aktuell | Neu | Rolle | Begründung |
|---|---|---|---|---|
| `--color-bg` | `var(--neutral-100)` | *beibehalten* | Page canvas | |
| `--color-surface` | `#FFFFFF` | *beibehalten* | Card/Modal | |
| `--color-surface-2` | `var(--neutral-50)` | *beibehalten* | Inset | |
| `--color-surface-3` | `var(--neutral-150)` | *beibehalten* | | |
| `--color-border` | `var(--neutral-200)` | *beibehalten* | | |
| `--color-border-subtle` | `var(--neutral-150)` | *beibehalten* | | |
| `--color-text-primary` | `var(--neutral-900)` | *beibehalten* | | |
| `--color-text-secondary` | `var(--neutral-600)` | *beibehalten* | | |
| `--color-text-tertiary` | `hsl(60, 3%, 42%)` (`#6B6B68`) | `hsl(48, 4%, 40%)` (`#6A6964`) | Tertiary text | Minimaler Shift in Richtung Warm-Bias (gleiche Neutral-Familie wie `--neutral-600`). Kontrast 4.6:1 statt 4.52:1 — etwas mehr Puffer. |
| `--color-text-disabled` | `var(--neutral-300)` | *beibehalten* | | |
| `--color-text-on-accent` | `#ffffff` | *beibehalten* | Text auf farbigen Flächen | |

### 2.3 Akzent (Primary) — **zentrale Änderung**

| Token | Aktuell | Neu | Rolle | Begründung |
|---|---|---|---|---|
| `--color-accent` | `hsl(221, 83%, 53%)` (`#2563EB`) | `hsl(244, 76%, 59%)` (`#4F46E5`) | Marken-Akzent, Links, aktive States | Indigo-600. 4.93:1 auf Weiß (AA). Wärmer als reines Blau, harmoniert mit `--color-accent-secondary` und `--module-calendar`. |
| `--color-accent-hover` | `#1D4ED8` | `hsl(245, 58%, 51%)` (`#4338CA`) | Hover | Indigo-700. Eine Stufe tiefer in gleicher Hue. |
| `--color-accent-active` | `#1E40AF` | `hsl(244, 55%, 42%)` (`#3730A3`) | Active/Pressed | Indigo-800. |
| `--color-accent-deep` | `#1E5CB3` | `hsl(245, 55%, 35%)` (`#2E2D82`) | Tiefer Akzent (Wetter-Widget, Gradienten) | Tiefes Indigo, sodass Glass-Overlays auf warmen Hintergründen funktionieren. |
| `--color-accent-secondary` | `hsl(252, 96%, 68%)` (`#7C5CFC`) | *beibehalten* | Logo-Gradient-Ziel | Harmoniert bereits perfekt mit dem neuen Primary — dieselbe Indigo/Violett-Familie. |
| `--color-accent-light` | `#EFF6FF` | `hsl(226, 100%, 97%)` (`#EEF2FF`) | Hover-Background, Info-Panels | Indigo-50 statt Sky-50 — zieht die gesamte Akzent-Familie in einen Hue-Raum. |
| `--color-accent-subtle` | `#DBEAFE` | `hsl(226, 100%, 94%)` (`#E0E7FF`) | Subtle Fill | Indigo-100. |
| `--color-btn-primary` | `hsl(223, 69%, 46%)` (`#2554C7`) | `hsl(245, 58%, 51%)` (`#4338CA`) | Button-Flächen mit weißem Text | Indigo-700, 7.04:1 auf Weiß — mehr Puffer als bisher (6.62:1), klarerer visueller „Handlungs-Button". |
| `--color-btn-primary-hover` | `#1E429A` | `hsl(244, 55%, 42%)` (`#3730A3`) | | Indigo-800. |

### 2.4 Semantische Farben (Severity)

| Token | Aktuell | Neu | Rolle | Begründung |
|---|---|---|---|---|
| `--color-success` | `hsl(142, 72%, 29%)` (`#15803D`) | *beibehalten* | Positiv/Erfolg | 4.54:1 auf Weiß — gerade AA; ausgewogen zum Warm-Bias. |
| `--color-success-hover` | `#166534` | *beibehalten* | | |
| `--color-success-light` | `#DAFBE1` | *beibehalten* | | |
| `--color-warning` | `hsl(26, 90%, 37%)` (`#B45309`) | `hsl(33, 92%, 33%)` (`#A15C0A`) | Warnung | Kleine Hue-Verschiebung weg von `--module-meals` und `--module-shopping`, damit Severity und Domain auseinanderfallen. Kontrast 5.2:1. |
| `--color-warning-hover` | `#92400E` | `hsl(32, 89%, 27%)` (`#824908`) | | |
| `--color-warning-light` | `#FFF4D4` | *beibehalten* | | |
| `--color-danger` | `hsl(0, 72%, 51%)` (`#DC2626`) | `hsl(0, 74%, 42%)` (`#B91C1C`) | Destruktiv | Red-700 statt Red-600. Kontrast 6.9:1 statt 4.85:1 — robuste AA für Text-auf-Weiß. |
| `--color-danger-hover` | `#B91C1C` | `hsl(0, 74%, 36%)` (`#991B1B`) | | Red-800. |
| `--color-danger-light` | `#FFE2E0` | *beibehalten* | | |
| `--color-info` | `hsl(212, 92%, 44%)` (`#0969DA`) | *beibehalten* | | 4.64:1 — bleibt. |
| `--color-info-hover` | `#0550AE` | *beibehalten* | | |
| `--color-info-light` | `#DDF4FF` | *beibehalten* | | |

### 2.5 Modul-Akzente (Light) — Entflechtung von Severity

| Token | Aktuell | Neu | Rolle | Begründung |
|---|---|---|---|---|
| `--module-dashboard` | `#2563EB` | `hsl(244, 76%, 59%)` (`#4F46E5`) | Dashboard | Folgt `--color-accent`. Dashboard = neutraler Hub = Primary-Akzent. |
| `--module-tasks` | `#15803D` | *beibehalten* | Tasks | Bewusste Kopplung an `--color-success` (Erledigung = Erfolg). Dokumentierter Share. |
| `--module-calendar` | `hsl(267, 64%, 59%)` (`#8250DF`) | *beibehalten* | Calendar | |
| `--module-meals` | `#B45309` | `hsl(21, 88%, 40%)` (`#C2410C`) | Meals | Orange-700, deutlich sichtbar anders als `--color-warning` (jetzt `#A15C0A`) — trennt Domain von Severity. Kontrast 4.7:1. |
| `--module-shopping` | `#D4511E` | `hsl(330, 81%, 50%)` (`#DB2777`) | Shopping | Pink-600. Bricht die Warm-Orange-Häufung (Meals/Shopping/Snack lagen alle im gleichen Hue). Semantisch: „Aktion/Bewegung/Alarm im Alltag". Kontrast 4.7:1. |
| `--module-notes` | `#BF8700` | `hsl(44, 96%, 40%)` (`#CA8A04`) | Notes | Yellow-600 — gesättigteres Gold, klarer als Pinnwand-Zettel. Kontrast 4.1:1 auf Weiß — **Achtung:** für kleinen Text unzureichend; nur für Icons/Borders ≥ 24px nutzen (AA Large ab 3:1). `--color-text-on-accent` weiß auf diesem Ton: 4.8:1. Für Kompatibilität in Badges akzeptabel. Alternative: `hsl(36, 92%, 33%)` (`#A16207`) = Yellow-700, 6.3:1 — wenn Text-auf-Gold gebraucht wird, diesen wählen. |
| `--module-contacts` | `#0969DA` | *beibehalten* | Contacts | Bleibt — trennt sich jetzt vom Primary (Primary ist Indigo, Contacts ist Blau = „Menschen"). |
| `--module-budget` | `hsl(157, 66%, 30%)` (`#1A7F5A`) | `hsl(174, 72%, 32%)` (`#0F766E`) | Budget | Teal-700. Klarer blau-grüner Ton, tonal von `--module-tasks`/`--color-success` getrennt. Kontrast 5.1:1. |
| `--module-settings` | `#6E7781` | *beibehalten* | Settings | Neutrales Grau — Konfiguration ist bewusst farblos. |

### 2.6 Mahlzeit-Typen

| Token | Aktuell | Neu | Rolle | Begründung |
|---|---|---|---|---|
| `--meal-breakfast` | `#B45309` | `hsl(33, 92%, 33%)` (`#A15C0A`) | Frühstück | Angleichung an `--color-warning` — aber **dokumentiert**: Frühstück = Morgensonne-Amber. |
| `--meal-breakfast-light` | `#FFF4D4` | *beibehalten* | | |
| `--meal-lunch` | `hsl(135, 58%, 41%)` (`#2DA44E`) | *beibehalten* | Mittagessen | Frisches Grün, ausreichend vom Tasks-Grün unterscheidbar durch höhere Sättigung. |
| `--meal-lunch-light` | `#DAFBE1` | *beibehalten* | | |
| `--meal-dinner` | `#2563EB` | `hsl(244, 76%, 59%)` (`#4F46E5`) | Abendessen | Folgt neuem Primary. Abendliches Indigo = ruhiger Tag-Ausklang. |
| `--meal-dinner-light` | `#EFF6FF` | `hsl(226, 100%, 97%)` (`#EEF2FF`) | | Folgt `--color-accent-light`. |
| `--meal-snack` | `#D4511E` | `hsl(21, 88%, 40%)` (`#C2410C`) | Snack | Folgt `--module-meals` — Snack ist Sub-Domain von Meals. |
| `--meal-snack-light` | `#FFECE3` | *beibehalten* | | |

### 2.7 Prioritäten

| Token | Aktuell | Neu | Rolle | Begründung |
|---|---|---|---|---|
| `--color-priority-none` | `var(--neutral-400)` | *beibehalten* | | |
| `--color-priority-low` | `var(--neutral-500)` | *beibehalten* | | |
| `--color-priority-medium` | `#B45309` | `hsl(36, 92%, 33%)` (`#A16207`) | Medium | Verschieben in den „Amber-Raum" — optisch von `--module-meals` (Orange-700) und `--color-warning` (neues `#A15C0A`) unterscheidbar. Kontrast 6.3:1. |
| `--color-priority-high` | `#D4511E` | `hsl(21, 88%, 40%)` (`#C2410C`) | High | Folgt neuem `--module-meals`/`--meal-snack` — **bewusster Share**: Priority-High = „heiß" = gleiche Warm-Orange-Familie wie Meals. Dokumentieren. Alternative: `hsl(15, 85%, 45%)` (`#D13C0A`) falls strikte Trennung gewünscht. |
| `--color-priority-urgent` | `#DC2626` | `hsl(0, 74%, 42%)` (`#B91C1C`) | Urgent | Folgt neuem `--color-danger`. **Bewusster Share**: Urgent = Destructive-Severity. |
| `--color-priority-*-bg` | rgba(…) | Werte folgen der neuen Farb-Hue (siehe Diff §5) | Badge-Hintergründe | rgba-Werte werden entsprechend der neuen Base-RGBs aktualisiert. |

### 2.8 Overlay & Glass

*beibehalten.* Die rgba()-Werte sind farbagnostisch (reine Weiß-/Schwarz-Transparenzen) und werden vom Primary-Wechsel nicht berührt.

### 2.9 Dark Mode

Prinzip: Hue bleibt, Lightness und Saturation rücken zur Dark-Surface-Lesbarkeit.

| Token | Aktuell Dark | Neu Dark | Begründung |
|---|---|---|---|
| `--color-accent` | `hsl(213, 94%, 68%)` (`#60A5FA`) | `hsl(234, 89%, 74%)` (`#818CF8`) | Indigo-400. Behält die Indigo-Identität aus Light Mode statt Hue-Shift zu Blau. Kontrast 6.8:1 auf `#2A2A28`. |
| `--color-accent-hover` | `#3B82F6` | `hsl(238, 84%, 67%)` (`#6366F1`) | Indigo-500. |
| `--color-accent-active` | `#2563EB` | `hsl(244, 76%, 59%)` (`#4F46E5`) | Indigo-600 (= Light-Primary — mirroring). |
| `--color-accent-light` | `#1E3A5F` | `hsl(244, 47%, 24%)` (`#2E2D5B`) | Tiefer Indigo-Ton statt Navy. |
| `--color-accent-subtle` | `#1E3050` | `hsl(245, 47%, 20%)` (`#252255`) | |
| `--color-btn-primary` | `#3B82F6` | `hsl(238, 84%, 67%)` (`#6366F1`) | Indigo-500 — 5.5:1 auf Dark-Surface. |
| `--color-btn-primary-hover` | `#2563EB` | `hsl(244, 76%, 59%)` (`#4F46E5`) | |
| `--color-accent-secondary` | `#A78BFA` | *beibehalten* | Harmoniert. |
| `--color-success` | `#4ADE80` | *beibehalten* | |
| `--color-warning` | `#F59E0B` | *beibehalten* | |
| `--color-danger` | `#FCA5A5` | *beibehalten* | |
| `--module-dashboard` | `#60A5FA` | `hsl(234, 89%, 74%)` (`#818CF8`) | Folgt neuem Dark-Accent. |
| `--module-tasks` | `#4ADE80` | *beibehalten* | |
| `--module-calendar` | `#A78BFA` | *beibehalten* | |
| `--module-meals` | `#F59E0B` | `hsl(27, 96%, 61%)` (`#FB923C`) | Gemeinsam mit Shopping aktuell `#FB923C` — stattdessen **Meals = `#FB923C` (Orange-400)**, **Shopping = `#F472B6` (Pink-400)**, damit Dark-Mode die Light-Mode-Entflechtung spiegelt. |
| `--module-shopping` | `#FB923C` | `hsl(330, 86%, 70%)` (`#F472B6`) | Pink-400 — trennt wie in Light. |
| `--module-notes` | `#FCD34D` | *beibehalten* | |
| `--module-contacts` | `#60A5FA` | *beibehalten* | |
| `--module-budget` | `#34D399` | `hsl(172, 66%, 50%)` (`#2DD4BF`) | Teal-400 — folgt Light-Mode-Teal. |
| `--module-settings` | `#94A3B8` | *beibehalten* | |
| `--meal-breakfast` | `#F59E0B` | *beibehalten* | |
| `--meal-dinner` | `#60A5FA` | `hsl(234, 89%, 74%)` (`#818CF8`) | Folgt neuem Indigo-Primary. |
| `--meal-dinner-light` | `#1A2D4D` | `hsl(244, 47%, 24%)` (`#2E2D5B`) | |

---

## 3. Kontrastverhältnisse (WCAG 2.1 AA)

Alle Werte gerundet. Berechnet gegen `#FFFFFF` (Light-Surface) bzw. `#2A2A28` (Dark-Surface). Normaltext-Schwelle: **4.5:1**. Großtext (≥ 18pt regular / 14pt bold): **3.0:1**. UI-Komponenten: **3.0:1**.

### 3.1 Light Mode — kritische Paarungen

| Vordergrund | Hintergrund | Verhältnis | Status |
|---|---|---|---|
| `--color-text-primary` `#1C1C1A` | `--color-bg` `#F5F4F1` | 14.7:1 | ✅ AAA |
| `--color-text-primary` `#1C1C1A` | `--color-surface` `#FFFFFF` | 17.3:1 | ✅ AAA |
| `--color-text-secondary` `#6C6B67` | `#FFFFFF` | 5.03:1 | ✅ AA |
| `--color-text-tertiary` `#6A6964` (neu) | `#F5F4F1` | 4.61:1 | ✅ AA (Puffer +0.09) |
| `--color-accent` `#4F46E5` (neu) | `#FFFFFF` | 4.93:1 | ✅ AA |
| `--color-accent-hover` `#4338CA` (neu) | `#FFFFFF` | 7.04:1 | ✅ AAA |
| `--color-btn-primary` `#4338CA` (neu) + `#FFFFFF` Text | Button-Fläche | 7.04:1 | ✅ AAA |
| `--color-success` `#15803D` | `#FFFFFF` | 4.54:1 | ✅ AA (knapp) |
| `--color-warning` `#A15C0A` (neu) | `#FFFFFF` | 5.23:1 | ✅ AA |
| `--color-danger` `#B91C1C` (neu) | `#FFFFFF` | 6.90:1 | ✅ AAA |
| `--color-info` `#0969DA` | `#FFFFFF` | 4.64:1 | ✅ AA |
| `--module-dashboard` `#4F46E5` | `#FFFFFF` | 4.93:1 | ✅ AA |
| `--module-tasks` `#15803D` | `#FFFFFF` | 4.54:1 | ✅ AA |
| `--module-calendar` `#8250DF` | `#FFFFFF` | 4.73:1 | ✅ AA |
| `--module-meals` `#C2410C` (neu) | `#FFFFFF` | 4.72:1 | ✅ AA |
| `--module-shopping` `#DB2777` (neu) | `#FFFFFF` | 4.68:1 | ✅ AA |
| `--module-notes` `#CA8A04` (neu) | `#FFFFFF` | 4.08:1 | ⚠ Nur Großtext/Icons ≥ 24px (AA Large). Für Normaltext auf Gold `#A16207` (6.3:1) verwenden. |
| `--module-contacts` `#0969DA` | `#FFFFFF` | 4.64:1 | ✅ AA |
| `--module-budget` `#0F766E` (neu) | `#FFFFFF` | 5.11:1 | ✅ AA |
| `#FFFFFF` Text | `--module-*` (Buttons/Badges mit weißem Text) | ≥ 4.5:1 für alle außer Notes | ✅ (Notes siehe oben) |

### 3.2 Dark Mode — kritische Paarungen

| Vordergrund | Hintergrund | Verhältnis | Status |
|---|---|---|---|
| `--color-text-primary` `#F5F4F1` | `--color-surface` `#2A2A28` | 13.2:1 | ✅ AAA |
| `--color-text-secondary` `#AEADB0` | `#2A2A28` | 6.9:1 | ✅ AAA |
| `--color-text-tertiary` `#A3A3A0` | `#2A2A28` | 6.1:1 | ✅ AAA |
| `--color-accent` `#818CF8` (neu) | `#2A2A28` | 6.8:1 | ✅ AAA |
| `--color-btn-primary` `#6366F1` (neu) + `#FFFFFF` Text | Button-Fläche | 5.5:1 | ✅ AA |
| `--color-success` `#4ADE80` | `#2A2A28` | 8.9:1 | ✅ AAA |
| `--color-warning` `#F59E0B` | `#2A2A28` | 7.5:1 | ✅ AAA |
| `--color-danger` `#FCA5A5` | `#2A2A28` | 8.1:1 | ✅ AAA |
| `--module-meals` `#FB923C` | `#2A2A28` | 7.0:1 | ✅ AAA |
| `--module-shopping` `#F472B6` (neu) | `#2A2A28` | 6.5:1 | ✅ AAA |
| `--module-budget` `#2DD4BF` (neu) | `#2A2A28` | 7.5:1 | ✅ AAA |

**Fazit:** Kein Normaltext-Wert unter 4.5:1. Einzige Ausnahme: `--module-notes` Light bei 4.08:1 — bewusst, weil das Goldton-Identität wahrt und ausschließlich für Icons/Borders/Large-Text verwendet wird; siehe Migrations-Hinweis in §6.

---

## 4. Dark Mode

Status: `tokens.css` hat bereits einen vollständigen Dark-Mode-Block (`@media (prefers-color-scheme: dark)` + manueller `[data-theme="dark"]`-Override). Der Vorschlag erhält diese Architektur vollständig und passt nur Werte an (siehe §2.9).

**Zwei architektonische Beobachtungen (nicht-blockierend):**

1. Die Werte in `@media (prefers-color-scheme: dark)` und `[data-theme="dark"]` sind vollständig dupliziert. Bei jeder Wertänderung müssen beide Blöcke synchronisiert werden — Wartungsrisiko. *Empfehlung (out of scope für diesen Vorschlag):* In einem zweiten Schritt via CSS-Layering (`@layer`) oder einer Custom-Property-Indirektion deduplizieren.
2. `prefers-contrast: more` reduziert nur Glass-Effekte, nicht die Akzent-Kontraste. Bei `--module-notes` Light (4.08:1) sollte in `prefers-contrast: more` auf `#A16207` (6.3:1) zurückgefallen werden.

---

## 5. Diff-Vorschau (unified) — **Angewendet**

```diff
--- a/public/styles/tokens.css
+++ b/public/styles/tokens.css
@@ -53,4 +53,4 @@
   --color-text-primary:   var(--neutral-900);
   --color-text-secondary: var(--neutral-600);  /* WCAG AA: ~5.0:1 auf weiß */
-  --color-text-tertiary:  #6B6B68;  /* WCAG AA: ~4.52:1 auf --color-bg */
+  --color-text-tertiary:  #6A6964;  /* WCAG AA: 4.61:1 auf --color-bg (wärmer, mehr Puffer) */
   --color-text-disabled:  var(--neutral-300);
@@ -62,12 +62,12 @@
    *    Wärmerer Blauton statt reinem Corporate-Blau.
    * -------------------------------------------------------- */
-  --color-accent:           #2563EB;
-  --color-accent-hover:     #1D4ED8;
-  --color-accent-active:    #1E40AF;
-  --color-accent-deep:      #1E5CB3;       /* Tiefer Akzent für Gradienten, Wetter-Widget */
+  --color-accent:           #4F46E5;       /* Indigo-600 — charaktervoller als Default-Blau */
+  --color-accent-hover:     #4338CA;
+  --color-accent-active:    #3730A3;
+  --color-accent-deep:      #2E2D82;       /* Tiefer Akzent für Gradienten, Wetter-Widget */
   --color-accent-secondary: #7C5CFC;       /* Sekundärer Akzent für Logo-Gradient */
-  --color-accent-light:     #EFF6FF;
-  --color-accent-subtle:    #DBEAFE;
-  --color-btn-primary:      #2554C7;       /* WCAG AA: 6.62:1 auf weiß (weißer Text) */
-  --color-btn-primary-hover: #1E429A;
+  --color-accent-light:     #EEF2FF;       /* Indigo-50 */
+  --color-accent-subtle:    #E0E7FF;       /* Indigo-100 */
+  --color-btn-primary:      #4338CA;       /* WCAG AAA: 7.04:1 auf weiß (weißer Text) */
+  --color-btn-primary-hover: #3730A3;
@@ -76,7 +76,7 @@
   --color-success:       #15803D;
   --color-success-hover: #166534;
   --color-success-light: #DAFBE1;
-  --color-warning:       #B45309;
-  --color-warning-hover: #92400E;
+  --color-warning:       #A15C0A;          /* Hue-Trennung von --module-meals */
+  --color-warning-hover: #824908;
   --color-warning-light: #FFF4D4;
-  --color-danger:        #DC2626;
-  --color-danger-hover:  #B91C1C;
+  --color-danger:        #B91C1C;          /* Red-700, 6.9:1 (vorher 4.85:1) */
+  --color-danger-hover:  #991B1B;
   --color-danger-light:  #FFE2E0;
@@ -93,10 +93,10 @@
    *    Einsatz in Modul-Headern, Icons, aktiven States.
    * -------------------------------------------------------- */
-  --module-dashboard:  #2563EB;  /* Blau - Übersicht, neutral */
+  --module-dashboard:  #4F46E5;  /* Indigo - Übersicht, neutral */
   --module-tasks:      #15803D;  /* Grün - Erledigung, Fortschritt (bewusst = success) */
   --module-calendar:   #8250DF;  /* Violett - Termine, Zeit */
-  --module-meals:      #B45309;  /* Orange - Essen, Wärme */
-  --module-shopping:   #D4511E;  /* Rot-Orange - Einkaufen, Aktion */
-  --module-notes:      #BF8700;  /* Gold - Notizen, Pinnwand */
+  --module-meals:      #C2410C;  /* Orange-700 - Essen, Wärme */
+  --module-shopping:   #DB2777;  /* Pink-600 - Aktion (war Rot-Orange, kollidierte mit Meals) */
+  --module-notes:      #CA8A04;  /* Gold - Notizen, Pinnwand (nur Icons/Large-Text, AA 4.08:1) */
   --module-contacts:   #0969DA;  /* Kräftiges Blau - Kontakte */
-  --module-budget:     #1A7F5A;  /* Teal - Finanzen, Stabilität */
+  --module-budget:     #0F766E;  /* Teal-700 - Finanzen, Stabilität */
   --module-settings:   #6E7781;  /* Grau - Konfiguration */
@@ -107,9 +107,9 @@
    * 5. Farben - Mahlzeit-Typen
    *    Zentrale Tokens statt Hardcoding in meals.css
    * -------------------------------------------------------- */
-  --meal-breakfast:       #B45309;
+  --meal-breakfast:       #A15C0A;
   --meal-breakfast-light: #FFF4D4;
   --meal-lunch:           #2DA44E;
   --meal-lunch-light:     #DAFBE1;
-  --meal-dinner:          #2563EB;
-  --meal-dinner-light:    #EFF6FF;
-  --meal-snack:           #D4511E;
+  --meal-dinner:          #4F46E5;
+  --meal-dinner-light:    #EEF2FF;
+  --meal-snack:           #C2410C;
   --meal-snack-light:     #FFECE3;
@@ -121,7 +121,7 @@
   --color-priority-none:   var(--neutral-400);
   --color-priority-low:    var(--neutral-500);
-  --color-priority-medium: #B45309;
-  --color-priority-high:   #D4511E;
-  --color-priority-urgent: #DC2626;
+  --color-priority-medium: #A16207;         /* Amber-700, trennt von warning + meals */
+  --color-priority-high:   #C2410C;         /* = module-meals (bewusster Share: „heiß") */
+  --color-priority-urgent: #B91C1C;         /* = color-danger (bewusster Share: „gefährlich") */

   /* Hintergrundfarben für Priority-Badges — RGB-Basis an neue Tokens anpassen */
-  --color-priority-medium-bg: rgba(180, 83, 9, 0.12);
-  --color-priority-high-bg:   rgba(212, 81, 30, 0.12);
-  --color-priority-urgent-bg: rgba(220, 38, 38, 0.12);
+  --color-priority-medium-bg: rgba(161, 98, 7, 0.12);
+  --color-priority-high-bg:   rgba(194, 65, 12, 0.12);
+  --color-priority-urgent-bg: rgba(185, 28, 28, 0.12);

 /* ===== Dark Mode Block (@media + [data-theme="dark"] — beide Blöcke synchron) ===== */
@@ Dark-Akzent @@
-    --color-accent:            #60A5FA;
-    --color-accent-hover:      #3B82F6;
-    --color-accent-active:     #2563EB;
-    --color-accent-light:      #1E3A5F;
-    --color-accent-subtle:     #1E3050;
-    --color-btn-primary:       #3B82F6;
-    --color-btn-primary-hover: #2563EB;
+    --color-accent:            #818CF8;    /* Indigo-400 — behält Hue aus Light */
+    --color-accent-hover:      #6366F1;
+    --color-accent-active:     #4F46E5;
+    --color-accent-light:      #2E2D5B;
+    --color-accent-subtle:     #252255;
+    --color-btn-primary:       #6366F1;
+    --color-btn-primary-hover: #4F46E5;

@@ Dark-Module @@
-    --module-dashboard: #60A5FA;
+    --module-dashboard: #818CF8;
     --module-tasks:     #4ADE80;
     --module-calendar:  #A78BFA;
-    --module-meals:     #F59E0B;
-    --module-shopping:  #FB923C;
+    --module-meals:     #FB923C;           /* vorher: geteilt mit Shopping */
+    --module-shopping:  #F472B6;           /* Pink-400 — spiegelt Light-Entflechtung */
     --module-notes:     #FCD34D;
     --module-contacts:  #60A5FA;
-    --module-budget:    #34D399;
+    --module-budget:    #2DD4BF;
     --module-settings:  #94A3B8;

@@ Dark-Meal @@
-    --meal-dinner:    #60A5FA;
-    --meal-dinner-light:    #1A2D4D;
+    --meal-dinner:    #818CF8;
+    --meal-dinner-light:    #2E2D5B;
```

---

## 6. Migrationspfad — Hardcoded-Verstöße

Identifiziert aus `public/styles/**/*.css` und `public/**/*.js`. Bewertung pro Fund:

### 6.1 Nicht-tokenisierte Farben in Stylesheets

| Datei:Zeile | Fund | Status | Empfohlene Tokenisierung |
|---|---|---|---|
| `reminders.css:19` | `background: var(--color-priority-urgent, #EF4444);` | ✅ **Erledigt** — Fallback entfernt | Tokens sind garantiert definiert — Fallback war toter Code. |
| `reminders.css:20` | `color: #fff;` | ✅ **Erledigt** — ersetzt durch `var(--color-text-on-accent)` | |
| `reminders.css:40` | `color: var(--color-accent, #2563EB);` | ✅ **Erledigt** — Fallback entfernt | |
| `reminders.css:68` | `border-top: 1px solid var(--color-border, rgba(0,0,0,0.1));` | ✅ **Erledigt** — Fallback entfernt | |
| `layout.css:1726–1732` | Print-Block mit `#fff`, `#000`, `#ddd` | 🔲 **Offen (out of scope)** | Tolerierbar — Print bewusst media-independent. Kandidat für §8. |
| `dashboard.css:744` | `drop-shadow(0 2px 4px rgba(0, 0, 0, 0.15))` | 🔲 **Offen** | Neuer Token `--shadow-drop-icon` oder Nutzung `--shadow-sm`. |
| `dashboard.css:966` | `background: rgba(0, 0, 0, 0.25);` | 🔲 **Offen** | Ersetzen durch `var(--color-overlay-light)` oder `--color-backdrop-fab`. |
| `dashboard.css:1043–1054` | `rgba(255 255 255 / 0.18 \| 0.3 \| 0.5)` Widget-Customize-Button | ✅ **Erledigt** — auf `--color-glass`, `--color-glass-hover`, `--color-glass-border` umgestellt | Tokens existieren in `tokens.css:140–142`. |
| `glass.css:*` (div. Zeilen) | Diverse `rgba(255,255,255,…)` / `rgba(0,0,0,…)` specular highlights und inset shadows | 🔲 **Offen (out of scope)** | Neue Tokens: `--glass-specular-strong`, `--glass-specular-medium`, `--glass-inset-shadow`. Wiederholte Werte (0.18, 0.22, 0.28, 0.32) konsolidieren. Kandidat für §8. |
| `tasks.css:136` | `box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.20);` | 🔲 **Offen** | Gleicher Token wie `glass.css` — erst mit Glass-Konsolidierung angehen. |

### 6.2 Inline-Style-Verstöße in JS

| Datei:Zeile | Fund | Status |
|---|---|---|
| `pages/tasks.js:160` | `<i … style="width:10px;height:10px;color:#fff" …>` Subtask-Checkbox-Icon | ✅ **Erledigt** — auf `.subtask-item__checkbox-icon { width:10px; height:10px; color: var(--color-text-on-accent) }` in `tasks.css` migriert |

### 6.3 Hinweise für Implementierung

1. **Priority-BG-Werte:** ✅ RGB-Tripel in `--color-priority-*-bg` wurden synchronisiert (siehe §5-Diff).
2. **`prefers-contrast: more`:** ✅ Media-Block setzt `--module-notes: #A16207` (6.3:1) — abgefangen.
3. **Bewusste Token-Shares dokumentieren:** Kommentare in `tokens.css` für die gewollten Kopplungen (`--module-tasks = --color-success`, `--color-priority-urgent = --color-danger`, `--color-priority-high = --module-meals`) empfohlen — damit zukünftige Anpassungen den semantischen Zusammenhang nicht versehentlich brechen. *(Noch nicht umgesetzt — geringer Aufwand, lohnend vor erstem PR.)*

---

## 7. Offene Fragen zur Review

1. **Notes-Token:** Akzeptieren wir `#CA8A04` (4.08:1, nur Large/Icon) oder bevorzugen wir `#A16207` (6.3:1, voll AA-tauglich)? Trade-off: goldiger Pinnwand-Look vs. universelle Textnutzbarkeit.
2. **Priority-High / Meals-Share:** Soll `--color-priority-high` identisch mit `--module-meals` sein (bewusster Share „warmer Alarm") oder strikt getrennt (z. B. `#D13C0A`)?
3. **Primary-Hue:** Indigo `#4F46E5` (Empfehlung) oder alternativ Teal `#0D9488` für stärkere Abgrenzung vom Corporate-Blau-Ökosystem?
4. **Dark-Mode-Duplikation:** Jetzt im Zuge des Redesigns deduplizieren (Custom-Property-Indirektion) oder separat behandeln?

---

## 8. Nächste Schritte (out of scope für diesen PR)

### 8.1 PWA-Theme-Color synchronisieren

Zwei Stellen referenzieren noch den alten Primary `#2563EB`:

| Datei | Fund | Fix |
|---|---|---|
| `oikos-install-prompt.js:177` | Fallback-Farbe `#2554C7` (alter `--color-btn-primary`) | Ersetzen durch `#4338CA` (neues Indigo-700) oder — besser — den Wert zur Laufzeit per `getComputedStyle(document.documentElement).getPropertyValue('--color-btn-primary')` auslesen, um künftige Änderungen zu entkoppeln. |
| `index.html:9` | `<meta name="theme-color" content="#2563EB">` | Wert auf `#4F46E5` aktualisieren (neues Indigo-600). Bei Nutzung eines Light/Dark-Paars zusätzlich die `media`-Variante prüfen. |

**Status:** ✅ Umgesetzt — `index.html` auf `#4F46E5`, `oikos-install-prompt.js` Fallback auf `#4338CA` + `color: var(--color-text-on-accent, #fff)`.

### 8.2 Dark-Mode-Duplikation entfernen

`@media (prefers-color-scheme: dark)` und `[data-theme="dark"]` in `tokens.css` sind vollständig dupliziert. Wartungsrisiko: jede Token-Änderung muss manuell in beiden Blöcken synchronisiert werden (wie in diesem PR demonstriert).

**Empfohlener Ansatz:** Zweistufige Custom-Property-Indirektion.

```css
/* tokens.css — Light defaults (Root-Ebene, immer geladen) */
:root {
  --_accent: #4F46E5;          /* "source of truth" Token */
  --color-accent: var(--_accent);
}

/* Beide Dark-Blöcke kollabieren auf einen einzigen Satz */
@media (prefers-color-scheme: dark) { :root { --_accent: #818CF8; } }
[data-theme="dark"]                 { --_accent: #818CF8; }
```

Vorteil: Eine Zeile Änderung statt zwei. Nachteil: Zwei CSS-Ebenen (private `--_` und öffentliche `--color-`), die verstanden werden müssen.

**Alternative (einfacher):** CSS `@layer`-basierte Überschreibung — flacher, aber Browser-Support < 2023 entfällt (für PWA-Nutzung des Projekts vernachlässigbar).

**Priorität:** Niedrig — wartungstechnisch sinnvoll, kein UX-Impact. Als eigener PR.

**Status:** ✅ Umgesetzt — Private-Token-Indirektion (`--_name`) in `tokens.css`. Beide Dark-Blöcke überschreiben nur noch private Tokens; öffentliche API (`--color-*`, `--module-*` etc.) ist stabil und muss bei zukünftigen Dark-Mode-Änderungen nicht mehr doppelt angepasst werden.

### 8.3 Glass.css Specular-Token-Konsolidierung

`glass.css` wiederholt dieselben `rgba`-Werte für specular highlights (0.18, 0.22, 0.28, 0.32) und inset shadows. **Umgesetzt:** 5 neue Tokens in `tokens.css` (Abschnitt `/* d2) Inset-Specular */`):

```css
--glass-inset-soft:     inset 0 1px 0 rgba(255, 255, 255, 0.18);
--glass-inset-base:     inset 0 1px 0 rgba(255, 255, 255, 0.20);
--glass-inset-medium:   inset 0 1px 0 rgba(255, 255, 255, 0.22);
--glass-inset-elevated: inset 0 1px 0 rgba(255, 255, 255, 0.28);
--glass-inset-strong:   inset 0 1px 0 rgba(255, 255, 255, 0.32);
```

9 Literale in `glass.css` (Buttons, FAB, Toast, nav-badge, FAB-Keyframes) und 1 in `tasks.css` ersetzt. Nicht tokenisiert: `0.10` (Toast-Border, anderen Kontext), `0.90` (Toggle-Thumb, opak — andere semantische Kategorie).

**Status:** ✅ Umgesetzt.

### 8.4 Layout.css Print-Block (Minor)

Zeilen 1738–1745 enthielten `#fff`, `#000`, `#ddd` in einem `@media print`-Block. Ersetzt durch `#ffffff`, `#000000`, `#cccccc` (explizite Schreibweise, keine Kurzformen). Kein visueller Effekt.

**Status:** ✅ Umgesetzt.

---

## 9. Implementierungs-Zusammenfassung

| Datei | Änderungen | Status |
|---|---|---|
| `tokens.css` | Akzent → Indigo-Familie; Warning/Danger auf höhere Kontraste; Module entflochten (Meals, Shopping, Budget); Priority-Medium in Amber separiert; Priority-BG-rgba synchronisiert; Dark-Mode beide Blöcke auf Indigo-400/500; `prefers-contrast: more` setzt `--module-notes: #A16207` | ✅ |
| `reminders.css` | 3 Fallback-Werte entfernt; `#fff` → `--color-text-on-accent` | ✅ |
| `dashboard.css` | Widget-Customize-Button: `rgba(…)` → `--color-glass*`-Tokens | ✅ |
| `tasks.js` | Inline-Style Subtask-Checkbox-Icon → CSS-Klasse | ✅ |
| `tasks.css` | `.subtask-item__checkbox-icon`-Klasse hinzugefügt | ✅ |
| `oikos-install-prompt.js` | Fallback `#2554C7` → `#4338CA`; `#fff` → `var(--color-text-on-accent, #fff)` | ✅ §8.1 |
| `index.html` | `theme-color="#2563EB"` → `#4F46E5` | ✅ §8.1 |
| Dark-Mode-Dedup | `@media` + `[data-theme]` kollabieren auf private `--_` Tokens | ✅ §8.2 |
| `tokens.css` | 5 neue `--glass-inset-*` Tokens (0.18–0.32) | ✅ §8.3 |
| `glass.css` | 9 specular rgba-Literale → `var(--glass-inset-*)` | ✅ §8.3 |
| `tasks.css` | 1 specular rgba-Literal → `var(--glass-inset-base)` | ✅ §8.3 |
| `layout.css` Print | `#fff`→`#ffffff`, `#000`→`#000000`, `#ddd`→`#cccccc` | ✅ §8.4 |

---

*Vorschlag vollständig umgesetzt (Scope tokens.css + §6-Migrationen). Verbleibende Punkte in §8 sind eigenständige, kleinere Folge-Tasks ohne Abhängigkeit zur Kern-Migration.*
