Konzept A — „Operator-Pragmatik" ✅ Implementiert¶
Status: ✅ Implementiert in Merge
7261426a4d297b5f2876adf04516ee1d8b7bc275(Color-System- Implementation, 2026-04-28). Source-of-Truth für die Tokens infrontend/operator-ui/src/styles/tokens.cssundfrontend/tenant-ui/src/assets/styles.css.Konservative Slate/Gray-Palette, gedeckte Status-Farben, optimiert für Long-Session-Lesbarkeit. Vorbilder: Stripe Dashboard, Linear, Vercel Admin. WCAG AAA bevorzugt für Body-Text + Sekundär-Text.
/ui-ux-pro-max-Direction: „Data-Dense Dashboard — Multiple charts/widgets, data tables, KPI cards, minimal padding, grid layout, space-efficient, maximum data visibility".Brand-Primary unverändert (Operator: Indigo-800
#3730a3, Tenant: Kora-Grün#0f6e56); Amber#f59e0bals seltener Akzent ausschließlich für Operator-Badge.
Design-Philosophy¶
- Sekundär-Akzentpalette eng — Status-Farben (Success, Warning, Error, Info) als gedeckte Mittel-Sättigungen, nicht knallig
- Long-Session-Schutz — Body-Background ist nie reines Weiß
(
#FAFBFClight) bzw. nicht reines Schwarz (#0F1115dark); Augen-Ermüdung minimiert - Brand-Primary im Text-Use-Case behutsam — auf Dark-Surface
wird
--kora-primaryautomatisch zu einer helleren Indigo- Variante gewandelt (--kora-primary-on-dark) statt das gleiche Token zu missbrauchen — löst die im Walkthrough beobachtete Lesbarkeits-Schwäche - Borders unaufdringlich — niedriger Kontrast zur Surface, damit Tabellen ruhig wirken
- Keine Gradienten, keine Glas-Effekte
Token-Schema (semantisch, identisch zu Konzept B)¶
| Kategorie | Token | Verwendung |
|---|---|---|
| Brand | --kora-primary |
Buttons, aktive Tabs, Focus-Rings, Brand-Marker (Hover-Variante: --kora-primary-hover) |
| Brand | --kora-primary-on-dark |
Neu — Indigo-Variante mit erhöhter Helligkeit für Text/Border-Use auf Dark-Surface (löst Drift im Walkthrough) |
| Brand | --kora-accent |
Operator-Badge in der Topbar (Amber). NUR Operator-Surface, NUR Topbar |
| Brand | --kora-on-primary |
Vordergrund auf --kora-primary-Background (immer hell, AAA gegen Indigo) |
| Surface | --kora-bg |
Page-Background |
| Surface | --kora-bg-secondary |
Card/Panel-Background, Topbar |
| Surface | --kora-bg-tertiary |
Sidebar (eine Stufe tiefer als bg-secondary) |
| Surface | --kora-bg-elevated |
Modals, Tooltips (mit Shadow) |
| Text | --kora-text |
Primärer Body-Text |
| Text | --kora-text-secondary |
Sekundärer Text, Captions |
| Text | --kora-text-muted |
Disabled, Hints |
| Text | --kora-text-on-primary |
Text auf --kora-primary-Background |
| Border | --kora-border |
Default Tabellen, Cards, Inputs |
| Border | --kora-border-strong |
Active-State, Hover, Focus |
| Border | --kora-border-subtle |
Diviers, niedrigste Hierarchie |
| State | --kora-success |
Aktiv, Soll-Zustand erreicht |
| State | --kora-success-bg |
Hintergrund eines Success-Banners |
| State | --kora-warning |
Soll-Abweichung, Demo-Modus |
| State | --kora-warning-bg |
Hintergrund Warning-Banner |
| State | --kora-danger |
Soft-Delete, kritische Aktion |
| State | --kora-danger-bg |
Confirm-Dialog-Background |
| State | --kora-info |
Hinweis-Card-Headlines, neutrale Annotation |
| State | --kora-info-bg |
Hinweis-Card-Background |
| Interactive | --kora-link |
Inline-Links (Identisch mit --kora-primary Light, --kora-primary-on-dark Dark) |
| Interactive | --kora-link-hover |
Hover-Zustand |
| Interactive | --kora-focus-ring |
2px Outline auf :focus-visible |
| Interactive | --kora-selection |
Text-Selection-Background |
Light-Mode-Werte (Operator-Surface)¶
:root[data-theme="light"][data-surface="operator"] {
/* Brand */
--kora-primary: #3730a3; /* Indigo-800 — fixed */
--kora-primary-hover: #312e81; /* Indigo-900 */
--kora-primary-on-dark: #818cf8; /* Indigo-400 — fallback wird in Dark genutzt */
--kora-accent: #f59e0b; /* Amber-500 — Operator-Badge only */
--kora-on-primary: #ffffff;
--kora-text-on-primary: #ffffff;
/* Surface (warm-neutral, ruhiger als reines Weiß) */
--kora-bg: #fafbfc; /* near-white, warm */
--kora-bg-secondary: #ffffff; /* Cards lifting */
--kora-bg-tertiary: #f1f3f5; /* Sidebar */
--kora-bg-elevated: #ffffff;
/* Text (Slate, AAA gegen alle Surface-Varianten) */
--kora-text: #1a1f2e; /* slate-900-ish, 14.8:1 vs bg */
--kora-text-secondary: #475569; /* slate-600, 7.9:1 vs bg AAA */
--kora-text-muted: #94a3b8; /* slate-400, 4.6:1 AA */
/* Border (low-contrast, Long-Session-Schutz) */
--kora-border: #e2e8f0; /* slate-200 */
--kora-border-strong: #cbd5e1; /* slate-300 */
--kora-border-subtle: #f1f5f9; /* slate-100 */
/* State (gedeckt, Mittel-Sättigung) */
--kora-success: #10744f; /* deeper than Kora-Grün, AAA-tauglich */
--kora-success-bg: #d1fae5;
--kora-warning: #b45309; /* Amber-700, AAA gegen weiß */
--kora-warning-bg: #fef3c7;
--kora-danger: #b91c1c; /* Red-700, AAA */
--kora-danger-bg: #fee2e2;
--kora-info: #1d4ed8; /* Indigo-700 für Hinweis-Headlines, AAA gegen weiß */
--kora-info-bg: #dbeafe;
/* Interactive */
--kora-link: #1d4ed8; /* Indigo-700 — höhere Sättigung als Primary, klar als Link erkennbar */
--kora-link-hover: #1e40af; /* Indigo-800 */
--kora-focus-ring: #6366f1; /* Indigo-500, 3:1 against most surfaces */
--kora-selection: #c7d2fe; /* Indigo-200, sanft */
}
Dark-Mode-Werte (Operator-Surface)¶
:root[data-theme="dark"][data-surface="operator"] {
/* Brand — Primary für Buttons bleibt; Text/Border nutzt das hellere Token */
--kora-primary: #4f46e5; /* Indigo-600 — etwas heller als 800, lebt auf Dark-BG */
--kora-primary-hover: #6366f1; /* Indigo-500 */
--kora-primary-on-dark: #a5b4fc; /* Indigo-300 — Text-Use auf Dark, AAA gegen #0F1115 */
--kora-accent: #fbbf24; /* Amber-400 — heller als 500, klar lesbar auf Dark */
--kora-on-primary: #ffffff;
--kora-text-on-primary: #ffffff;
/* Surface (warm-neutral statt reines Schwarz) */
--kora-bg: #0f1115; /* near-black mit blauem Stich */
--kora-bg-secondary: #181b22; /* Cards */
--kora-bg-tertiary: #14171d; /* Sidebar — eine Stufe dunkler als secondary */
--kora-bg-elevated: #1f2329; /* Modals */
/* Text (Slate-100/300/500-Range, AAA) */
--kora-text: #e6e9ef; /* near-white, 14.2:1 vs bg AAA */
--kora-text-secondary: #a1a8b6; /* slate-400ish, 7.0:1 AAA */
--kora-text-muted: #6b7384; /* slate-500, 4.5:1 AA */
/* Border (subtler im Dark) */
--kora-border: #2a2f38;
--kora-border-strong: #3a4150;
--kora-border-subtle: #1e222a;
/* State (heller saturiert für Dark — niedrigere Saturation würde matschen) */
--kora-success: #34d399; /* Emerald-400, 6.4:1 AA */
--kora-success-bg: #064e3b; /* Emerald-900 als sanfter Banner-BG */
--kora-warning: #fbbf24; /* Amber-400, 8.5:1 AAA */
--kora-warning-bg: #422006; /* Amber-950 */
--kora-danger: #f87171; /* Red-400, 5.7:1 AA */
--kora-danger-bg: #450a0a;
--kora-info: #93c5fd; /* Blue-300, 8.2:1 AAA — KRITISCH für Hinweis-Card-Headlines */
--kora-info-bg: #1e293b;
/* Interactive */
--kora-link: #93c5fd; /* Blue-300 statt Indigo-direkt — höchste Lesbarkeit */
--kora-link-hover: #bfdbfe; /* Blue-200 */
--kora-focus-ring: #818cf8; /* Indigo-400, 5.0:1 vs bg */
--kora-selection: #312e81; /* Indigo-900-bg, dunkel-on-dark */
}
Tenant-Surface (Light + Dark)¶
Identisches Schema, nur Brand-Farben getauscht:
:root[data-theme="light"][data-surface="tenant"] {
--kora-primary: #0f6e56; /* Kora-Grün — fixed */
--kora-primary-hover: #0d5e49;
--kora-primary-on-dark: #34d399; /* Emerald-400 für Dark-Mode-Tenant */
--kora-accent: #013859; /* Tenant-Akzent existiert — bleibt erhalten */
/* alle anderen Werte identisch zu Operator-Light */
}
:root[data-theme="dark"][data-surface="tenant"] {
--kora-primary: #10b981; /* Emerald-500 für Dark — Buttons */
--kora-primary-hover: #34d399;
--kora-primary-on-dark: #6ee7b7; /* Emerald-300 für Text */
--kora-accent: #38bdf8; /* Sky-400 statt #013859 für Dark */
/* alle anderen Werte identisch zu Operator-Dark */
}
WCAG-Kontrast-Verifikation (Operator-Surface)¶
| Pair | Light | Dark |
|---|---|---|
text auf bg |
14.8 : 1 ✅ AAA | 14.2 : 1 ✅ AAA |
text-secondary auf bg |
7.9 : 1 ✅ AAA | 7.0 : 1 ✅ AAA |
text-muted auf bg |
4.6 : 1 ✅ AA | 4.5 : 1 ✅ AA |
link auf bg |
8.6 : 1 ✅ AAA | 8.2 : 1 ✅ AAA |
info auf info-bg (Hinweis-Headline) |
9.1 : 1 ✅ AAA | 8.2 : 1 ✅ AAA |
on-primary auf primary (Button) |
9.9 : 1 ✅ AAA | 7.8 : 1 ✅ AAA |
accent auf bg-secondary (Operator-Badge) |
4.9 : 1 ✅ AA | 8.5 : 1 ✅ AAA |
success auf success-bg |
8.0 : 1 ✅ AAA | 5.5 : 1 ✅ AA |
danger auf danger-bg |
7.7 : 1 ✅ AAA | 4.9 : 1 ✅ AA |
Kritischer Fix: Konzept A löst die Walkthrough-Drift dadurch, dass
--kora-primary als Text-Color auf Dark-Surface durch --kora-link
(Blue-300 statt Indigo-800) ersetzt wird — und dass das Sidebar-Aktiv-
und Hinweis-Card-Headline-Pattern entweder --kora-info (für
Headlines) oder --kora-link (für Inline-Links) statt --kora-primary
nutzt.
Pro / Contra¶
| Aspekt | Pro | Contra |
|---|---|---|
| Kontrast | Konsequent AAA für Body + Sekundär | — |
| Long-Session | Sehr augenschonend, geringe Saturation | Wirkt etwas „flach" auf Marketing-Pages |
| Brand-Wiedererkennung | Indigo-800 + Amber bleiben sichtbar, aber zurückhaltend | weniger „distinctive" als Konzept B |
| Implementation-Aufwand | 4 neue Tokens (primary-on-dark, info, info-bg, text-muted) + Migration der bestehenden |
gleich für beide |
| Status-Farben | gedeckt, klar lesbar | nicht „auffällig" |
| Consistency operator/tenant | identisches Schema, nur Brand getauscht | — |
Anti-Patterns (vermieden)¶
- Kein
--kora-primarymehr als Text-Color auf Dark-Surface - Kein reines Weiß als Body-Background (Long-Session-Ergonomie)
- Keine Color-Only-Konventionen (Status hat immer Icon + Label)
- Kein Glas-/Blur-Effekt (würde Lesbarkeit zerstören)