Zum Inhalt

Konzept A — „Operator-Pragmatik" ✅ Implementiert

Status: ✅ Implementiert in Merge 7261426a4d297b5f2876adf04516ee1d8b7bc275 (Color-System- Implementation, 2026-04-28). Source-of-Truth für die Tokens in frontend/operator-ui/src/styles/tokens.css und frontend/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 #f59e0b als 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ß (#FAFBFC light) bzw. nicht reines Schwarz (#0F1115 dark); Augen-Ermüdung minimiert
  • Brand-Primary im Text-Use-Case behutsam — auf Dark-Surface wird --kora-primary automatisch 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-primary mehr 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)