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
+20 -27
View File
@@ -1,5 +1,5 @@
import { useState } from 'react'
import { Alert, Box, Button, Chip, Collapse, IconButton, Typography } from '@mui/material'
import { Alert, Box, Button, Collapse, IconButton, Typography } from '@mui/material'
import { AlertTriangle, ChevronDown, ChevronUp, Target } from 'lucide-react'
import type { ReactNode } from 'react'
@@ -32,16 +32,16 @@ interface Props {
children?: ReactNode
}
const SEVERITY_COLOR: Record<NonNullable<DecisionMetric['severity']>, string> = {
neutral: '#f1f5f9',
positive: '#f0fdf4',
warning: '#fef9c3',
critical: '#fef2f2',
const SEVERITY_DOT: Record<NonNullable<DecisionMetric['severity']>, string> = {
neutral: '#9a9a9a',
positive: '#1d6342',
warning: '#a16207',
critical: '#b91c1c',
}
const SEVERITY_TEXT: Record<NonNullable<DecisionMetric['severity']>, string> = {
neutral: '#475569',
positive: '#1a7a4a',
neutral: '#5c5c5c',
positive: '#1d6342',
warning: '#92400e',
critical: '#991b1b',
}
@@ -61,9 +61,8 @@ export function DecisionContextPanel({
return (
<Box
sx={{
bgcolor: '#f8fafc',
borderBottom: '1px solid #e2e8f0',
borderLeft: '3px solid #1e3a5f',
bgcolor: '#f9f8f6',
borderBottom: '1px solid #e8e7e4',
px: 2.5,
py: 1.25,
flexShrink: 0,
@@ -73,9 +72,9 @@ export function DecisionContextPanel({
<Box sx={{ display: 'flex', alignItems: 'flex-start', gap: 2, flexWrap: 'wrap' }}>
{/* Decision question */}
<Box sx={{ display: 'flex', alignItems: 'flex-start', gap: 1, flex: 1, minWidth: 200 }}>
<Target size={15} color="#1e3a5f" style={{ marginTop: 2, flexShrink: 0 }} />
<Target size={15} color="#152642" style={{ marginTop: 2, flexShrink: 0 }} />
<Box>
<Typography variant="body2" sx={{ fontWeight: 700, fontSize: '0.8125rem', color: '#1e293b', lineHeight: 1.3 }}>
<Typography variant="body2" sx={{ fontWeight: 700, fontSize: '0.8125rem', color: '#141414', lineHeight: 1.3 }}>
{decision}
</Typography>
{context && (
@@ -88,22 +87,16 @@ export function DecisionContextPanel({
{/* Metric chips */}
{metrics.length > 0 && (
<Box sx={{ display: 'flex', gap: 0.5, flexWrap: 'wrap', alignItems: 'center' }}>
<Box sx={{ display: 'flex', gap: 1, flexWrap: 'wrap', alignItems: 'center' }}>
{metrics.map((m, i) => {
const sev = m.severity ?? 'neutral'
return (
<Chip
key={i}
label={`${m.value} ${m.label}`}
size="small"
sx={{
bgcolor: SEVERITY_COLOR[sev],
color: SEVERITY_TEXT[sev],
fontWeight: sev !== 'neutral' ? 700 : 400,
fontSize: '0.7rem',
height: 22,
}}
/>
<Box key={i} sx={{ display: 'flex', alignItems: 'center', gap: 0.5 }}>
<Box sx={{ width: 6, height: 6, borderRadius: '50%', bgcolor: SEVERITY_DOT[sev], flexShrink: 0 }} />
<Typography sx={{ fontSize: '0.75rem', color: SEVERITY_TEXT[sev], fontWeight: sev !== 'neutral' ? 600 : 400, lineHeight: 1.2 }}>
{m.value} {m.label}
</Typography>
</Box>
)
})}
</Box>
@@ -118,7 +111,7 @@ export function DecisionContextPanel({
variant={a.primary ? 'contained' : 'outlined'}
onClick={a.onClick}
sx={a.primary
? { bgcolor: '#1e3a5f', '&:hover': { bgcolor: '#162d4a' }, textTransform: 'none', fontSize: '0.75rem', py: 0.375, px: 1.25 }
? { bgcolor: '#152642', '&:hover': { bgcolor: '#0e1c30' }, textTransform: 'none', fontSize: '0.75rem', py: 0.375, px: 1.25 }
: { textTransform: 'none', fontSize: '0.75rem', py: 0.375, px: 1.25 }
}
>