feat: premium redesign — DM Serif, refined palette, flat score badges

- Design tokens (ds.ts, theme.ts, scoreTheme.ts): new warm palette
  (#152642 navy, #f9f8f6 warm white, #e8e7e4 borders, #b8975a gold accent),
  flat score tier badges replacing CSS gradients, Inter + DM Serif Display typography
- Card components: white-background cards, DM Serif score numbers, max-2 badge
  chips with +N overflow tooltip, editorial score badge positioning
- Layout shell: gold left-accent nav active state, 64px top bar, outlined
  workspace chip, DM Serif page titles
- Shared atoms: GenericBadge (outlined/solid variants), ResultFilterBar
  (simplified chip styles), DecisionContextPanel (dot metrics, no left accent)
- Global replacement (118 files): #1e3a5f→#152642, #e2e8f0→#e8e7e4,
  #f4f6f9→#f9f8f6 — all handled via Node.js for proper UTF-8 safety

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Benjamin Sutter
2026-06-09 22:26:30 +02:00
parent 96a2507979
commit da50f3b5ea
132 changed files with 659 additions and 711 deletions
+88 -97
View File
@@ -2,129 +2,124 @@ import type { ConfidenceLevel, DataQualityLevel } from '../domain/enums'
import { CONF_HIGH, CONF_MEDIUM, DQ_HIGH, DQ_MEDIUM } from './constants'
// ── Semantic color tokens ─────────────────────────────────────────────────────
// Single source of truth for badge/score colors. All badge components read from here.
export const DS_COLORS = {
resultType: {
VERIFIED_PORTFOLIO: { bg: 'rgba(30,58,95,0.10)', fg: '#1e3a5f' },
MAISON_WORK: { bg: 'rgba(3,105,161,0.10)', fg: '#0369a1' },
FUTURE_AVAILABILITY: { bg: 'rgba(109,40,217,0.10)', fg: '#6d28d9' },
VERIFIED_PORTFOLIO: { bg: 'rgba(21,38,66,0.10)', fg: '#152642' },
MAISON_WORK: { bg: 'rgba(45,90,138,0.10)', fg: '#2d5a8a' },
FUTURE_AVAILABILITY: { bg: 'rgba(91,63,138,0.10)', fg: '#5b3f8a' },
},
confidence: {
VERY_HIGH: { bg: 'rgba(26,122,74,0.12)', fg: '#1a7a4a' },
HIGH: { bg: 'rgba(26,122,74,0.09)', fg: '#1a7a4a' },
MEDIUM: { bg: 'rgba(30,58,95,0.10)', fg: '#1e3a5f' },
LOW: { bg: 'rgba(217,119,6,0.12)', fg: '#d97706' },
VERY_LOW: { bg: 'rgba(192,57,43,0.12)', fg: '#c0392b' },
VERY_HIGH: { bg: 'rgba(29,99,66,0.12)', fg: '#1d6342' },
HIGH: { bg: 'rgba(29,99,66,0.09)', fg: '#1d6342' },
MEDIUM: { bg: 'rgba(21,38,66,0.10)', fg: '#152642' },
LOW: { bg: 'rgba(161,98,7,0.12)', fg: '#a16207' },
VERY_LOW: { bg: 'rgba(185,28,28,0.12)', fg: '#b91c1c' },
},
risk: {
LOW: { bg: 'rgba(26,122,74,0.10)', fg: '#1a7a4a' },
MEDIUM: { bg: 'rgba(217,119,6,0.10)', fg: '#d97706' },
HIGH: { bg: 'rgba(192,57,43,0.10)', fg: '#c0392b' },
CRITICAL: { bg: 'rgba(127,0,0,0.12)', fg: '#7f1d1d' },
LOW: { bg: 'rgba(29,99,66,0.10)', fg: '#1d6342' },
MEDIUM: { bg: 'rgba(161,98,7,0.10)', fg: '#a16207' },
HIGH: { bg: 'rgba(185,28,28,0.10)', fg: '#b91c1c' },
CRITICAL: { bg: 'rgba(127,0,0,0.12)', fg: '#7f1d1d' },
},
availability: {
AVAILABLE_NOW: { bg: 'rgba(26,122,74,0.10)', fg: '#1a7a4a' },
AVAILABLE_SOON: { bg: 'rgba(217,119,6,0.10)', fg: '#d97706' },
FUTURE_SIGNAL: { bg: 'rgba(109,40,217,0.10)', fg: '#6d28d9' },
AVAILABLE_NOW: { bg: 'rgba(29,99,66,0.10)', fg: '#1d6342' },
AVAILABLE_SOON: { bg: 'rgba(161,98,7,0.10)', fg: '#a16207' },
FUTURE_SIGNAL: { bg: 'rgba(91,63,138,0.10)', fg: '#5b3f8a' },
OCCUPIED: { bg: 'rgba(100,116,139,0.10)', fg: '#475569' },
UNKNOWN: { bg: '#f1f5f9', fg: '#94a3b8' },
UNKNOWN: { bg: '#f4f3f0', fg: '#9a9a9a' },
},
freshness: {
FRESH: { bg: 'rgba(26,122,74,0.10)', fg: '#1a7a4a' },
STALE: { bg: 'rgba(217,119,6,0.10)', fg: '#d97706' },
OUTDATED: { bg: 'rgba(192,57,43,0.10)', fg: '#c0392b' },
FRESH: { bg: 'rgba(29,99,66,0.10)', fg: '#1d6342' },
STALE: { bg: 'rgba(161,98,7,0.10)', fg: '#a16207' },
OUTDATED: { bg: 'rgba(185,28,28,0.10)', fg: '#b91c1c' },
},
dataQuality: {
HIGH: { bg: 'rgba(26,122,74,0.10)', fg: '#1a7a4a' },
MEDIUM: { bg: 'rgba(217,119,6,0.10)', fg: '#d97706' },
LOW: { bg: 'rgba(192,57,43,0.10)', fg: '#c0392b' },
INCOMPLETE: { bg: 'rgba(127,0,0,0.12)', fg: '#7f1d1d' },
HIGH: { bg: 'rgba(29,99,66,0.10)', fg: '#1d6342' },
MEDIUM: { bg: 'rgba(161,98,7,0.10)', fg: '#a16207' },
LOW: { bg: 'rgba(185,28,28,0.10)', fg: '#b91c1c' },
INCOMPLETE: { bg: 'rgba(127,0,0,0.12)', fg: '#7f1d1d' },
},
heat: {
VERY_HOT: { bg: '#fef3c7', border: '#fcd34d', icon: '#d97706', text: '#92400e' },
HOT: { bg: '#fff7ed', border: '#fed7aa', icon: '#ea580c', text: '#c2410c' },
VERY_HOT: { bg: '#fef3c7', border: '#fcd34d', icon: '#a16207', text: '#92400e' },
HOT: { bg: '#fff7ed', border: '#fed7aa', icon: '#a16207', text: '#92400e' },
},
futureCard: {
controlled: {
accent: '#7c3aed',
accentHover: '#6d28d9',
headerBg: '#faf5ff',
accent: '#5b3f8a',
accentHover: '#4a3070',
headerBg: '#faf7ff',
border: '#e9d5ff',
badgeBg: '#ede9fe',
badgeText: '#5b21b6',
},
signal: {
accent: '#1d4ed8',
accentHover: '#1e40af',
headerBg: '#eff6ff',
accent: '#2d5a8a',
accentHover: '#1e4068',
headerBg: '#f0f6ff',
border: '#bfdbfe',
badgeBg: '#dbeafe',
badgeText: '#1e40af',
indicator: '#1d4ed8',
indicator: '#2d5a8a',
},
},
} as const
// ── Text color tokens ─────────────────────────────────────────────────────────
// For sx={{ color: DS_TEXT.secondary }} instead of hardcoded '#475569'
export const DS_TEXT = {
primary: '#1e293b',
secondary: '#475569',
muted: '#64748b',
disabled: '#94a3b8',
primary: '#141414',
secondary: '#5c5c5c',
muted: '#9a9a9a',
disabled: '#c4c4c4',
inverted: '#ffffff',
success: '#1a7a4a',
warning: '#d97706',
error: '#c0392b',
danger: '#dc2626',
info: '#0369a1',
brand: '#1e3a5f',
signal: '#6d28d9',
// Dark variants — use for text on light-tinted surface boxes
success: '#1d6342',
warning: '#a16207',
error: '#b91c1c',
danger: '#b91c1c',
info: '#2d5a8a',
brand: '#152642',
signal: '#5b3f8a',
successDark: '#166534',
warningDark: '#92400e',
signalDark: '#4c1d95',
infoDark: '#0c4a6e',
brandDark: '#162d4a',
brandDark: '#0e1c30',
} as const
// ── Background tokens ─────────────────────────────────────────────────────────
export const DS_BG = {
page: '#f8fafc',
page: '#f9f8f6',
surface: '#ffffff',
subtle: '#f1f5f9',
muted: '#e2e8f0',
subtle: '#f4f3f0',
muted: '#e8e7e4',
} as const
// ── Border tokens ─────────────────────────────────────────────────────────────
export const DS_BORDER = {
default: '#e2e8f0',
muted: '#f1f5f9',
strong: '#cbd5e1',
default: '#e8e7e4',
muted: '#f2f1ee',
strong: '#c8c7c4',
} as const
// ── Surface tokens — bg + border pairs for highlighted/tinted boxes ───────────
// Use as: sx={{ bgcolor: DS_SURFACE.success.bg, border: `1px solid ${DS_SURFACE.success.border}` }}
// ── Surface tokens ────────────────────────────────────────────────────────────
export const DS_SURFACE = {
success: { bg: '#f0fdf4', border: '#bbf7d0' }, // green tint
warning: { bg: '#fffbeb', border: '#fde68a' }, // amber tint
error: { bg: '#fef2f2', border: '#fecaca' }, // red tint
info: { bg: '#f0f9ff', border: '#bae6fd' }, // sky tint
indigo: { bg: '#eef2ff', border: '#e0e7ff' }, // indigo tint (hard-criteria rows)
purple: { bg: '#faf5ff', border: '#e9d5ff' }, // purple tint (pre-market / future)
orange: { bg: '#fff7ed', border: '#fed7aa' }, // orange tint (HOT heat badge bg)
blue: { bg: '#eff6ff', border: '#bfdbfe' }, // blue tint (market signal)
neutral: { bg: '#f8fafc', border: '#e2e8f0' }, // neutral/slate tint (formula rows)
slate: { bg: '#f1f5f9', border: '#e2e8f0' }, // slightly darker neutral
success: { bg: '#f0fdf4', border: '#bbf7d0' },
warning: { bg: '#fffbeb', border: '#fde68a' },
error: { bg: '#fef2f2', border: '#fecaca' },
info: { bg: '#f0f6ff', border: '#bfdbfe' },
indigo: { bg: '#eef2ff', border: '#e0e7ff' },
purple: { bg: '#faf7ff', border: '#e9d5ff' },
orange: { bg: '#fff7ed', border: '#fed7aa' },
blue: { bg: '#f0f6ff', border: '#bfdbfe' },
neutral: { bg: '#f9f8f6', border: '#e8e7e4' },
slate: { bg: '#f4f3f0', border: '#e8e7e4' },
} as const
// ── Match tier surface — bg tint keyed by score tier ─────────────────────────
// Use with SCORE_STRONG / SCORE_MODERATE thresholds from constants.ts
// ── Match tier surface ────────────────────────────────────────────────────────
export const DS_MATCH_TIER = {
strong: DS_SURFACE.success,
@@ -132,49 +127,45 @@ export const DS_MATCH_TIER = {
weak: DS_SURFACE.error,
} as const
// ── Pre-market & market signal shorthand aliases ──────────────────────────────
// DS_COLORS.futureCard.controlled / signal are the full token sets.
// These aliases make imports more readable in supply-side components.
// ── Pre-market & market signal aliases ────────────────────────────────────────
export const DS_PRE_MARKET = DS_COLORS.futureCard.controlled
export const DS_MARKET_SIGNAL = DS_COLORS.futureCard.signal
// ── Badge color presets ───────────────────────────────────────────────────────
// Pass to GenericBadge.color instead of raw hex strings.
// BADGE_COLORS.confidenceHigh replaces '#1a7a4a' at call sites.
export const BADGE_COLORS = {
confidenceHigh: '#1a7a4a',
confidenceMedium: '#d97706',
confidenceLow: '#c0392b',
riskHigh: '#c0392b',
riskMedium: '#d97706',
riskLow: '#1a7a4a',
preMarket: '#7c3aed',
marketSignal: '#1d4ed8',
verified: '#1e3a5f',
info: '#0369a1',
muted: '#64748b',
gold: '#d97706',
silver: '#64748b',
bronze: '#b45309',
confidenceHigh: '#1d6342',
confidenceMedium: '#a16207',
confidenceLow: '#b91c1c',
riskHigh: '#b91c1c',
riskMedium: '#a16207',
riskLow: '#1d6342',
preMarket: '#5b3f8a',
marketSignal: '#2d5a8a',
verified: '#152642',
info: '#2d5a8a',
muted: '#9a9a9a',
gold: '#b8975a',
silver: '#7a8a9a',
bronze: '#7a6050',
} as const
// ── Shadow tokens ─────────────────────────────────────────────────────────────
export const DS_SHADOW = {
card: '0 1px 3px 0 rgba(0,0,0,0.08), 0 1px 2px -1px rgba(0,0,0,0.04)',
panel: '0 4px 6px -1px rgba(0,0,0,0.08), 0 2px 4px -2px rgba(0,0,0,0.04)',
dialog: '0 20px 25px -5px rgba(0,0,0,0.10), 0 8px 10px -6px rgba(0,0,0,0.06)',
card: '0 1px 3px rgba(0,0,0,0.06)',
panel: '0 3px 6px rgba(0,0,0,0.07)',
dialog: '0 16px 24px rgba(0,0,0,0.10)',
} as const
// ── Inquiry status metadata ───────────────────────────────────────────────────
export const INQUIRY_STATUS_META: Record<string, { label: string; fg: string; bg: string }> = {
new: { label: 'Neu', fg: '#dc2626', bg: '#fef2f2' },
in_progress: { label: 'Aktiv', fg: '#d97706', bg: '#fffbeb' },
answered: { label: 'Beantwortet', fg: '#1a7a4a', bg: '#f0fdf4' },
archived: { label: 'Archiviert', fg: '#64748b', bg: '#f8fafc' },
new: { label: 'Neu', fg: '#b91c1c', bg: '#fef2f2' },
in_progress: { label: 'Aktiv', fg: '#a16207', bg: '#fffbeb' },
answered: { label: 'Beantwortet', fg: '#1d6342', bg: '#f0fdf4' },
archived: { label: 'Archiviert', fg: '#9a9a9a', bg: '#f9f8f6' },
}
// ── Score → qualitative level helpers ────────────────────────────────────────
@@ -194,10 +185,10 @@ export function scoreToDataQualityLevel(score: number): DataQualityLevel {
return 'INCOMPLETE'
}
// ── Result type meta — single source for labels + colors ─────────────────────
// ── Result type meta ──────────────────────────────────────────────────────────
export const RESULT_TYPE_META: Record<string, { label: string; color: string; bg: string }> = {
VERIFIED_PORTFOLIO: { label: 'Verifiziertes Objekt', color: '#1e3a5f', bg: 'rgba(30,58,95,0.10)' },
MAISON_WORK: { label: 'Maison Work', color: '#0369a1', bg: 'rgba(3,105,161,0.10)' },
FUTURE_AVAILABILITY: { label: 'Zukunftssignal', color: '#7c3aed', bg: 'rgba(109,40,217,0.10)' },
VERIFIED_PORTFOLIO: { label: 'Verifiziertes Objekt', color: '#152642', bg: 'rgba(21,38,66,0.10)' },
MAISON_WORK: { label: 'Maison Work', color: '#2d5a8a', bg: 'rgba(45,90,138,0.10)' },
FUTURE_AVAILABILITY: { label: 'Zukunftssignal', color: '#5b3f8a', bg: 'rgba(91,63,138,0.10)' },
}
+21 -21
View File
@@ -8,30 +8,30 @@ export function getScoreTier(score: number): ScoreTier {
export const SCORE_THEME = {
gold: {
gradient: 'linear-gradient(135deg,#f8e642 0%,#d4920e 100%)',
border: '#c9900c',
glow: 'rgba(212,146,14,0.35)',
text: '#7a4f00',
label: 'Top Match',
cardBorder: '#fbbf24',
cardBg: 'linear-gradient(160deg,#fffbeb,#fef3c7)',
gradient: '#b8975a',
border: '#a07a3f',
glow: 'transparent',
text: '#ffffff',
label: 'Top Match',
cardBorder: '#b8975a',
cardBg: '#ffffff',
},
silver: {
gradient: 'linear-gradient(135deg,#f1f5f9 0%,#cbd5e1 100%)',
border: '#94a3b8',
glow: 'rgba(148,163,184,0.30)',
text: '#334155',
label: 'Starkes Match',
cardBorder: '#cbd5e1',
cardBg: 'linear-gradient(160deg,#f8fafc,#f1f5f9)',
gradient: '#7a8a9a',
border: '#6b7a8a',
glow: 'transparent',
text: '#ffffff',
label: 'Starkes Match',
cardBorder: '#7a8a9a',
cardBg: '#ffffff',
},
bronze: {
gradient: 'linear-gradient(135deg,#fde8c8 0%,#d4956a 100%)',
border: '#c07a46',
glow: 'rgba(192,122,70,0.25)',
text: '#7c3d0c',
label: 'Gutes Match',
cardBorder: '#f5d0a9',
cardBg: 'linear-gradient(160deg,#fdf6f0,#fef3e8)',
gradient: '#7a6050',
border: '#6a5040',
glow: 'transparent',
text: '#ffffff',
label: 'Gutes Match',
cardBorder: '#7a6050',
cardBg: '#ffffff',
},
} as const
+34 -34
View File
@@ -4,9 +4,9 @@ export const theme = createTheme({
palette: {
mode: 'light',
primary: {
main: '#1e3a5f',
light: '#2d5290',
dark: '#142a45',
main: '#152642',
light: '#1e3a5f',
dark: '#0e1c30',
contrastText: '#ffffff',
},
secondary: {
@@ -16,18 +16,18 @@ export const theme = createTheme({
contrastText: '#ffffff',
},
background: {
default: '#f4f6f9',
default: '#f9f8f6',
paper: '#ffffff',
},
text: {
primary: '#1a2332',
secondary: '#4a5568',
primary: '#141414',
secondary: '#5c5c5c',
},
error: { main: '#c0392b' },
warning: { main: '#d97706' },
success: { main: '#1a7a4a' },
error: { main: '#b91c1c' },
warning: { main: '#a16207' },
success: { main: '#1d6342' },
info: { main: '#2563eb' },
divider: '#e2e8f0',
divider: '#e8e7e4',
},
typography: {
fontFamily: '"Inter", "Segoe UI", system-ui, -apple-system, sans-serif',
@@ -41,37 +41,37 @@ export const theme = createTheme({
subtitle2: { fontSize: '0.8125rem', fontWeight: 600, lineHeight: 1.4 },
body1: { fontSize: '0.875rem', lineHeight: 1.6 },
body2: { fontSize: '0.8125rem', lineHeight: 1.5 },
caption: { fontSize: '0.75rem', lineHeight: 1.4, color: '#64748b' },
caption: { fontSize: '0.75rem', lineHeight: 1.4, color: '#9a9a9a' },
overline: { fontSize: '0.6875rem', fontWeight: 600, letterSpacing: '0.08em', textTransform: 'uppercase' },
button: { fontSize: '0.8125rem', fontWeight: 600, textTransform: 'none' },
},
shape: { borderRadius: 6 },
shape: { borderRadius: 8 },
shadows: [
'none',
'0 1px 2px rgba(0,0,0,0.06), 0 1px 3px rgba(0,0,0,0.08)',
'0 1px 4px rgba(0,0,0,0.06), 0 2px 6px rgba(0,0,0,0.08)',
'0 2px 6px rgba(0,0,0,0.07), 0 4px 10px rgba(0,0,0,0.08)',
'0 3px 8px rgba(0,0,0,0.08), 0 6px 14px rgba(0,0,0,0.08)',
'0 4px 10px rgba(0,0,0,0.08), 0 8px 18px rgba(0,0,0,0.08)',
'0 5px 12px rgba(0,0,0,0.09)', '0 6px 14px rgba(0,0,0,0.09)',
'0 7px 16px rgba(0,0,0,0.09)', '0 8px 18px rgba(0,0,0,0.09)',
'0 9px 20px rgba(0,0,0,0.09)', '0 10px 22px rgba(0,0,0,0.10)',
'0 11px 24px rgba(0,0,0,0.10)', '0 12px 26px rgba(0,0,0,0.10)',
'0 13px 28px rgba(0,0,0,0.10)', '0 14px 30px rgba(0,0,0,0.10)',
'0 15px 32px rgba(0,0,0,0.10)', '0 16px 34px rgba(0,0,0,0.10)',
'0 17px 36px rgba(0,0,0,0.10)', '0 18px 38px rgba(0,0,0,0.10)',
'0 19px 40px rgba(0,0,0,0.10)', '0 20px 42px rgba(0,0,0,0.10)',
'0 21px 44px rgba(0,0,0,0.10)', '0 22px 46px rgba(0,0,0,0.10)',
'0 24px 50px rgba(0,0,0,0.12)',
'0 1px 2px rgba(0,0,0,0.05)',
'0 1px 3px rgba(0,0,0,0.06)',
'0 2px 4px rgba(0,0,0,0.06)',
'0 3px 6px rgba(0,0,0,0.07)',
'0 4px 8px rgba(0,0,0,0.07)',
'0 5px 10px rgba(0,0,0,0.08)', '0 6px 12px rgba(0,0,0,0.08)',
'0 7px 14px rgba(0,0,0,0.08)', '0 8px 16px rgba(0,0,0,0.08)',
'0 9px 18px rgba(0,0,0,0.08)', '0 10px 20px rgba(0,0,0,0.09)',
'0 11px 22px rgba(0,0,0,0.09)', '0 12px 24px rgba(0,0,0,0.09)',
'0 13px 26px rgba(0,0,0,0.09)', '0 14px 28px rgba(0,0,0,0.09)',
'0 15px 30px rgba(0,0,0,0.09)', '0 16px 32px rgba(0,0,0,0.09)',
'0 17px 34px rgba(0,0,0,0.09)', '0 18px 36px rgba(0,0,0,0.09)',
'0 19px 38px rgba(0,0,0,0.09)', '0 20px 40px rgba(0,0,0,0.09)',
'0 21px 42px rgba(0,0,0,0.09)', '0 22px 44px rgba(0,0,0,0.09)',
'0 24px 48px rgba(0,0,0,0.10)',
],
components: {
MuiCard: {
defaultProps: { elevation: 1 },
styleOverrides: {
root: {
border: '1px solid #e2e8f0',
'&:hover': { boxShadow: '0 2px 8px rgba(0,0,0,0.10)' },
transition: 'box-shadow 0.15s ease',
border: '1px solid #e8e7e4',
'&:hover': { borderColor: '#c8c7c4' },
transition: 'border-color 0.15s ease',
},
},
},
@@ -81,20 +81,20 @@ export const theme = createTheme({
root: { borderRadius: 6, padding: '6px 16px' },
contained: {
'&.MuiButton-containedPrimary': {
background: '#1e3a5f',
'&:hover': { background: '#142a45' },
background: '#152642',
'&:hover': { background: '#0e1c30' },
},
},
},
},
MuiChip: {
styleOverrides: {
root: { borderRadius: 4, fontSize: '0.75rem', fontWeight: 600, height: 22 },
root: { borderRadius: 6, fontSize: '0.75rem', fontWeight: 500, height: 22 },
},
},
MuiTableCell: {
styleOverrides: {
head: { fontWeight: 600, fontSize: '0.75rem', color: '#64748b', textTransform: 'uppercase', letterSpacing: '0.05em', padding: '8px 12px' },
head: { fontWeight: 600, fontSize: '0.75rem', color: '#9a9a9a', textTransform: 'uppercase', letterSpacing: '0.05em', padding: '8px 12px' },
body: { fontSize: '0.8125rem', padding: '10px 12px' },
},
},
+14 -14
View File
@@ -64,29 +64,29 @@ export function probabilityColor(prob: number): 'success' | 'warning' | 'error'
return 'error'
}
// Hex color variants for use in sx (when MUI color tokens aren't enough)
// Hex color variants for use in sx props
export function dataQualityHex(score: number): string {
if (score >= DQ_HIGH) return '#1a7a4a'
if (score >= DQ_MEDIUM) return '#d97706'
return '#c0392b'
if (score >= DQ_HIGH) return '#1d6342'
if (score >= DQ_MEDIUM) return '#a16207'
return '#b91c1c'
}
export function confidenceHex(score: number): string {
if (score >= CONF_HIGH) return '#1a7a4a'
if (score >= CONF_MEDIUM) return '#1e3a5f'
return '#d97706'
if (score >= CONF_HIGH) return '#1d6342'
if (score >= CONF_MEDIUM) return '#152642'
return '#a16207'
}
export function probabilityHex(prob: number): string {
if (prob >= PROB_HIGH) return '#1a7a4a'
if (prob >= PROB_MEDIUM) return '#d97706'
return '#c0392b'
if (prob >= PROB_HIGH) return '#1d6342'
if (prob >= PROB_MEDIUM) return '#a16207'
return '#b91c1c'
}
export function matchScoreHex(score: number): string {
if (score >= SCORE_STRONG) return '#1a7a4a'
if (score >= SCORE_MODERATE) return '#d97706'
return '#c0392b'
if (score >= SCORE_STRONG) return '#1d6342'
if (score >= SCORE_MODERATE) return '#a16207'
return '#b91c1c'
}
export function criterionScoreColor(score: number): 'success' | 'warning' | 'error' {
@@ -94,7 +94,7 @@ export function criterionScoreColor(score: number): 'success' | 'warning' | 'err
}
export function criterionScoreTextColor(score: number): string {
return score >= 70 ? '#1a7a4a' : score >= 50 ? '#d97706' : '#c0392b'
return score >= 70 ? '#1d6342' : score >= 50 ? '#a16207' : '#b91c1c'
}
// ── Misc ──────────────────────────────────────────────────────────────────────