Move completed implementation plans (2026-04-20), design specs, and audit documents to docs/archive/ for historical reference while keeping the main docs/ directory focused on active documentation. Archived: - 1 implementation plan (superpowers/plans/) - 2 design specs (superpowers/specs/) - 3 design documents (designs/) - 5 audit/proposal documents (root level) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
34 KiB
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:
- Generischer Primary-Akzent.
#2563EBist 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. - 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.mdsieht „semantic accent colors tied to life domain" vor — Domain und Severity müssen trennbar bleiben. - 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-primaryfü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):
- 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. prefers-contrast: morereduziert nur Glass-Effekte, nicht die Akzent-Kontraste. Bei--module-notesLight (4.08:1) sollte inprefers-contrast: moreauf#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: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
- Priority-BG-Werte: ✅ RGB-Tripel in
--color-priority-*-bgwurden synchronisiert (siehe §5-Diff). prefers-contrast: more: ✅ Media-Block setzt--module-notes: #A16207(6.3:1) — abgefangen.- Bewusste Token-Shares dokumentieren: Kommentare in
tokens.cssfü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
- 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. - Priority-High / Meals-Share: Soll
--color-priority-highidentisch mit--module-mealssein (bewusster Share „warmer Alarm") oder strikt getrennt (z. B.#D13C0A)? - Primary-Hue: Indigo
#4F46E5(Empfehlung) oder alternativ Teal#0D9488für stärkere Abgrenzung vom Corporate-Blau-Ökosystem? - 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 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.