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
+1 -1
View File
@@ -170,7 +170,7 @@ const PropertyRow = memo(function PropertyRow({
<IconButton
size="small"
onClick={() => onEdit(property.id)}
sx={{ color: '#94a3b8', '&:hover': { color: '#1e3a5f' } }}
sx={{ color: '#94a3b8', '&:hover': { color: '#152642' } }}
>
<Edit2 size={14} />
</IconButton>
+18 -18
View File
@@ -125,7 +125,7 @@ const LeadListItem = memo(function LeadListItem({
sx={{
px: 2, py: 1.5,
borderBottom: '1px solid #f1f5f9',
borderLeft: `3px solid ${selected ? '#1e3a5f' : 'transparent'}`,
borderLeft: `3px solid ${selected ? '#152642' : 'transparent'}`,
bgcolor: selected ? '#f0f9ff' : 'white',
cursor: 'pointer',
'&:hover': { bgcolor: selected ? '#f0f9ff' : '#f8fafc' },
@@ -181,7 +181,7 @@ function ContactRow({ contact }: { contact: ExtractedContact }) {
href={href}
target="_blank"
rel="noopener noreferrer"
sx={{ color: '#1e3a5f', fontWeight: 500, fontSize: '0.8125rem', textDecoration: 'none', '&:hover': { textDecoration: 'underline' }, display: 'flex', alignItems: 'center', gap: 0.5 }}
sx={{ color: '#152642', fontWeight: 500, fontSize: '0.8125rem', textDecoration: 'none', '&:hover': { textDecoration: 'underline' }, display: 'flex', alignItems: 'center', gap: 0.5 }}
>
{contact.value}
<ExternalLink size={11} />
@@ -241,7 +241,7 @@ function PropertyMatchCard({
}}
onClick={() => navigate('/supply/properties')}
>
<Building2 size={14} color="#1e3a5f" style={{ flexShrink: 0 }} />
<Building2 size={14} color="#152642" style={{ flexShrink: 0 }} />
<Box sx={{ flex: 1, minWidth: 0 }}>
<Typography variant="body2" sx={{ fontWeight: 600, color: '#0f172a', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
{p.title}
@@ -271,8 +271,8 @@ function PropertyMatchCard({
onClick={() => setOpen(v => !v)}
sx={{
textTransform: 'none', fontSize: '0.75rem',
bgcolor: open ? '#1e3a5f' : undefined,
borderColor: open ? '#1e3a5f' : undefined,
bgcolor: open ? '#152642' : undefined,
borderColor: open ? '#152642' : undefined,
'&:hover': { bgcolor: open ? '#162d4a' : undefined },
}}
>
@@ -302,7 +302,7 @@ function PropertyMatchCard({
onClick={handleCopy}
sx={{
textTransform: 'none', fontSize: '0.72rem',
color: copied ? '#16a34a' : '#1e3a5f',
color: copied ? '#16a34a' : '#152642',
}}
>
{copied ? 'Kopiert!' : 'Kopieren'}
@@ -370,7 +370,7 @@ function LeadDetail({ lead }: { lead: MarketLead }) {
href={signal.source.url}
target="_blank"
rel="noopener noreferrer"
sx={{ display: 'flex', alignItems: 'center', gap: 0.5, ml: 'auto', color: '#1e3a5f', fontSize: '0.75rem', fontWeight: 600, textDecoration: 'none', '&:hover': { textDecoration: 'underline' } }}
sx={{ display: 'flex', alignItems: 'center', gap: 0.5, ml: 'auto', color: '#152642', fontSize: '0.75rem', fontWeight: 600, textDecoration: 'none', '&:hover': { textDecoration: 'underline' } }}
>
Quelle öffnen <ExternalLink size={11} />
</Box>
@@ -403,7 +403,7 @@ function LeadDetail({ lead }: { lead: MarketLead }) {
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 0.5 }}>
{signal.marketIndicators!.map((ind, i) => (
<Box key={i} sx={{ display: 'flex', alignItems: 'flex-start', gap: 0.75 }}>
<TrendingUp size={12} color="#1e3a5f" style={{ marginTop: 3, flexShrink: 0 }} />
<TrendingUp size={12} color="#152642" style={{ marginTop: 3, flexShrink: 0 }} />
<Typography variant="body2" sx={{ lineHeight: 1.5, color: '#1e293b' }}>{ind}</Typography>
</Box>
))}
@@ -531,7 +531,7 @@ const HinweisPropertyCard = memo(function HinweisPropertyCard({
cursor: 'default',
}}
>
<Building2 size={14} color="#1e3a5f" style={{ flexShrink: 0 }} />
<Building2 size={14} color="#152642" style={{ flexShrink: 0 }} />
<Box sx={{ flex: 1, minWidth: 0 }}>
<Typography variant="body2" sx={{ fontWeight: 600, color: '#0f172a', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
{p.title}
@@ -561,8 +561,8 @@ const HinweisPropertyCard = memo(function HinweisPropertyCard({
onClick={() => setOpen(v => !v)}
sx={{
textTransform: 'none', fontSize: '0.75rem',
bgcolor: open ? '#1e3a5f' : undefined,
borderColor: open ? '#1e3a5f' : undefined,
bgcolor: open ? '#152642' : undefined,
borderColor: open ? '#152642' : undefined,
'&:hover': { bgcolor: open ? '#162d4a' : undefined },
}}
>
@@ -581,7 +581,7 @@ const HinweisPropertyCard = memo(function HinweisPropertyCard({
size="small"
startIcon={copied ? <CheckCircle2 size={13} /> : <Copy size={13} />}
onClick={handleCopy}
sx={{ textTransform: 'none', fontSize: '0.72rem', color: copied ? '#16a34a' : '#1e3a5f' }}
sx={{ textTransform: 'none', fontSize: '0.72rem', color: copied ? '#16a34a' : '#152642' }}
>
{copied ? 'Kopiert!' : 'Kopieren'}
</Button>
@@ -644,7 +644,7 @@ const HinweisListItem = memo(function HinweisListItem({
sx={{
px: 2, py: 1.5,
borderBottom: '1px solid #f1f5f9',
borderLeft: `3px solid ${selected ? '#1e3a5f' : 'transparent'}`,
borderLeft: `3px solid ${selected ? '#152642' : 'transparent'}`,
bgcolor: selected ? '#f0f9ff' : 'white',
cursor: 'pointer',
'&:hover': { bgcolor: selected ? '#f0f9ff' : '#f8fafc' },
@@ -654,7 +654,7 @@ const HinweisListItem = memo(function HinweisListItem({
<Box sx={{ display: 'flex', alignItems: 'flex-start', gap: 0.75, mb: 0.25 }}>
<Box sx={{ mt: 0.25, flexShrink: 0 }}>
{hinweis.direction === 'SUCHE'
? <Search size={14} color="#1e3a5f" />
? <Search size={14} color="#152642" />
: <Building2 size={14} color="#7c3aed" />
}
</Box>
@@ -1003,7 +1003,7 @@ function HinweisErfassenDialog({
variant="contained"
onClick={handleSave}
disabled={mutation.isPending || !isValid}
sx={{ textTransform: 'none', bgcolor: '#1e3a5f', '&:hover': { bgcolor: '#162d4a' } }}
sx={{ textTransform: 'none', bgcolor: '#152642', '&:hover': { bgcolor: '#162d4a' } }}
>
Speichern
</Button>
@@ -1075,7 +1075,7 @@ export default function MarketIntelligence() {
<Box sx={{ width: 360, flexShrink: 0, borderRight: '1px solid #e2e8f0', display: 'flex', flexDirection: 'column', overflow: 'hidden' }}>
<Box sx={{ px: 2, py: 1.25, borderBottom: '1px solid #e2e8f0', display: 'flex', alignItems: 'center', gap: 1, flexShrink: 0 }}>
<Typography variant="subtitle2" sx={{ fontWeight: 600, flex: 1 }}>Erkannte Signale</Typography>
<Chip label={leadsLoading ? '…' : leads.length} size="small" sx={{ bgcolor: '#1e3a5f', color: '#fff', fontSize: '0.7rem', height: 20 }} />
<Chip label={leadsLoading ? '…' : leads.length} size="small" sx={{ bgcolor: '#152642', color: '#fff', fontSize: '0.7rem', height: 20 }} />
</Box>
<Box sx={{ flex: 1, overflowY: 'auto' }}>
{leadsLoading
@@ -1130,7 +1130,7 @@ export default function MarketIntelligence() {
onClick={() => setErfassenOpen(true)}
sx={{
textTransform: 'none', fontSize: '0.72rem',
bgcolor: '#1e3a5f', '&:hover': { bgcolor: '#162d4a' },
bgcolor: '#152642', '&:hover': { bgcolor: '#162d4a' },
minWidth: 'auto',
}}
>
@@ -1147,7 +1147,7 @@ export default function MarketIntelligence() {
onClick={() => setHinweisFilter(f)}
sx={{
height: 22, fontSize: '0.68rem', cursor: 'pointer',
bgcolor: hinweisFilter === f ? '#1e3a5f' : '#f1f5f9',
bgcolor: hinweisFilter === f ? '#152642' : '#f1f5f9',
color: hinweisFilter === f ? 'white' : '#475569',
}}
/>
+2 -2
View File
@@ -104,7 +104,7 @@ function MatchListItem({
sx={{
textTransform: 'none',
fontSize: '0.75rem',
bgcolor: '#1e3a5f',
bgcolor: '#152642',
'&:hover': { bgcolor: '#162d4a' },
}}
>
@@ -351,7 +351,7 @@ export default function MyListings() {
variant="contained"
startIcon={<Plus size={16} />}
onClick={() => navigate('/supply/new-listing')}
sx={{ bgcolor: '#1e3a5f', '&:hover': { bgcolor: '#162d4a' }, textTransform: 'none' }}
sx={{ bgcolor: '#152642', '&:hover': { bgcolor: '#162d4a' }, textTransform: 'none' }}
>
Neues Inserat
</Button>
+1 -1
View File
@@ -177,7 +177,7 @@ export default function Properties() {
variant={criticalGaps.length > 0 || staleOrOutdated.length > 0 ? 'contained' : 'outlined'}
onClick={() => navigate('/supply/data-quality')}
sx={criticalGaps.length > 0 || staleOrOutdated.length > 0
? { bgcolor: '#1e3a5f', '&:hover': { bgcolor: '#162d4a' }, textTransform: 'none', fontSize: '0.75rem', py: 0.375, px: 1.5, flexShrink: 0 }
? { bgcolor: '#152642', '&:hover': { bgcolor: '#162d4a' }, textTransform: 'none', fontSize: '0.75rem', py: 0.375, px: 1.5, flexShrink: 0 }
: { textTransform: 'none', fontSize: '0.75rem', py: 0.375, px: 1.5, flexShrink: 0 }
}
>