Files
oikos/docs/color-redesign-proposal.md
T
Ulas Kalayci 18c90653d4 refactor: dark-mode token deduplication via private-variable indirection (v0.20.17)
All tokens with dark-mode overrides gain a private --_name counterpart in :root.
Public tokens (--color-*, --module-*, --glass-* etc.) become stable var(--_name)
references. Both dark blocks now only override compact private tokens — no more
manual two-block sync for every future colour change.

Also removes the redundant --color-surface-2 dark override (already auto-derived
via var(--neutral-50)). No visual change.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 06:53:08 +02:00

34 KiB
Raw Blame History

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-snackbewusster 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

--- 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:17261732 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:10431054 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:140142.
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.

/* 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 */):

--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 17381745 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; #fffvar(--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.180.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.