feat(redesign): Design-Tokens + Ebene-2 "Cyber trifft Safety" (additiv)
CI / detect-changes (push) Successful in 19s
CI / branch-name (push) Has been skipped
CI / guardrail-integrity (push) Has been skipped
CI / secret-scan (push) Has been skipped
CI / dep-audit (push) Has been skipped
CI / sbom-scan (push) Has been skipped
CI / build-sha-integrity (push) Successful in 7s
CI / validate-canonical-controls (push) Successful in 4s
CI / loc-budget (push) Successful in 21s
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / nodejs-build (push) Successful in 3m13s
CI / test-go (push) Has been skipped
CI / iace-gt-coverage (push) Has been skipped
CI / test-python-backend (push) Has been skipped
CI / test-python-document-crawler (push) Has been skipped
CI / test-python-dsms-gateway (push) Has been skipped

Schritt A (Tokens): zentrale Design-Sprache aus dem Claude-Design-Handoff —
Tailwind-Tokens (re/geltung/severity/domain) + Fonts (Public Sans / Source
Serif 4 / IBM Plex Mono) + components/redesign/{tokens.ts,Chips.tsx}
(GeltungChip, SeverityChip, DomainTag, MonoId) + Showcase /sdk/design-system.
Bestehende Farben/sans unangetastet.

Schritt B (Ebene 2): CyberMeetsSafety als USP-Hero im CRA/Cyber-Tab
(/sdk/iace/[id]/cra) — Domaenen-Bar, Hazard-Karten (CE-gemildert -> Cyber-Befund
-> Restrisiko, Warum-Box, Pflicht/Empfehlung-Massnahmen, aufklappbarer
Norm-Bezug), Massnahmen-Backlog mit Geltung-Filter. Gebunden an echte
cross_links/findings/open_measures. Bisheriger CRACyberView bleibt eingeklappt
erhalten -> kein Inhaltsverlust.

Guardrail-Doku: design/redesign/ (HANDOFF_README, CONTENT_INVENTORY mit
40-Screen-Mapping + Waisen-Liste, Arbeitsbereich.dc.html-Referenz).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Benjamin Bönisch
2026-06-18 16:49:04 +02:00
parent 43e02f794a
commit 42d4b4d9c5
10 changed files with 1312 additions and 3 deletions
@@ -0,0 +1,55 @@
// Design-language tokens — single source of truth for the redesign.
// Mirrors design/redesign/HANDOFF_README.md (Claude Design handoff). The same
// values are mirrored into tailwind.config.ts (namespaces re/geltung/severity/domain)
// for utility-class use; components that need the exact chip look import from here.
export const COLORS = {
page: '#EDEFF3', surface: '#FFFFFF', border: '#E4E7EE', borderSoft: '#F0F1F5',
ink: '#1A1D29', muted: '#5A6273', muted2: '#6B7184', faint: '#8089A0', fainter: '#9AA1B2',
brand: '#4338CA', brandText: '#3B36B0', brandTint: '#EEF0FF', brandTint2: '#F6F4FF',
panel: '#15182A', panelText: '#E8EAF2', panelText2: '#C7CBDA', panelAccent: '#9B8BF5',
} as const
// --- Geltung: Pflicht / Empfehlung / Kann (the core 3-tier obligation system) ---
export type Geltung = 'pflicht' | 'empfehlung' | 'kann'
export const GELTUNG: Record<Geltung, {
label: string; bg: string; text: string; border: string; marker: 'square' | 'diamond' | 'circle'
}> = {
pflicht: { label: 'Pflicht', bg: '#FBECEA', text: '#A23323', border: '#F3D2CC', marker: 'square' },
empfehlung: { label: 'Empfehlung', bg: '#EEF0FF', text: '#3B36B0', border: '#DAD9F7', marker: 'diamond' },
kann: { label: 'Kann', bg: '#F1F3F7', text: '#5A6273', border: '#E2E6EE', marker: 'circle' },
}
export const PFLICHT_MARKER = '#C0362C' // filled square color
export function normalizeGeltung(v: string | Geltung): Geltung {
const s = String(v || '').toLowerCase()
if (['pflicht', 'mandatory', 'required', 'must', 'core'].includes(s)) return 'pflicht'
if (['empfehlung', 'recommended', 'should', 'review'].includes(s)) return 'empfehlung'
if (['kann', 'optional', 'may', 'can'].includes(s)) return 'kann'
return 'empfehlung' // unknown → recommendation (never silently drop; never over-state as Pflicht)
}
// --- Severity (Dringlichkeit) ---
export type Severity = 'kritisch' | 'hoch' | 'mittel' | 'niedrig'
export const SEVERITY: Record<Severity, { label: string; bg: string; text: string }> = {
kritisch: { label: 'Kritisch', bg: '#FBE9E7', text: '#B5362A' },
hoch: { label: 'Hoch', bg: '#FBF1E0', text: '#9A6410' },
mittel: { label: 'Mittel', bg: '#FAF6DD', text: '#897209' },
niedrig: { label: 'Niedrig', bg: '#E9F5EF', text: '#2C7A52' },
}
export function normalizeSeverity(v: string | Severity): Severity {
const s = String(v || '').toLowerCase()
if (['kritisch', 'critical'].includes(s)) return 'kritisch'
if (['hoch', 'high'].includes(s)) return 'hoch'
if (['mittel', 'medium', 'moderate'].includes(s)) return 'mittel'
if (['niedrig', 'low', 'minor'].includes(s)) return 'niedrig'
return 'mittel'
}
// --- Domains (Safety / Cyber / Schnittstelle) ---
export type Domain = 'safety' | 'cyber' | 'bridge'
export const DOMAIN: Record<Domain, { label: string; accent: string; tint: string; border: string; warn?: string }> = {
safety: { label: 'Safety (Maschine/CE)', accent: '#0E8A66', tint: '#F3FAF7', border: '#D7ECE3' },
cyber: { label: 'Cyber (CRA)', accent: '#6A43D6', tint: '#F6F1FE', border: '#E4D8F7' },
bridge: { label: 'Cyber × Safety', accent: '#BE7714', tint: '#FCF6EF', border: '#F2E6D5', warn: '#9A6410' },
}