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
+16 -30
View File
@@ -16,10 +16,10 @@ interface Props {
isPropertyManager?: boolean
}
const FILTER_OPTIONS: { value: FilterSource; label: string; color: string }[] = [
{ value: 'ALL', label: 'Alle', color: '#1e3a5f' },
{ value: 'PLATFORM', label: 'Plattform', color: '#1e3a5f' },
{ value: 'MAISON_WORK', label: 'Maison Work', color: '#0369a1' },
const FILTER_OPTIONS: { value: FilterSource; label: string }[] = [
{ value: 'ALL', label: 'Alle' },
{ value: 'PLATFORM', label: 'Plattform' },
{ value: 'MAISON_WORK', label: 'Maison Work' },
]
const SORT_OPTIONS: { value: SortBy; label: string }[] = [
@@ -28,6 +28,9 @@ const SORT_OPTIONS: { value: SortBy; label: string }[] = [
{ value: 'rent', label: 'Mietpreis' },
]
const ACTIVE_CHIP = { bgcolor: '#152642', color: 'white', border: '1px solid #152642', fontWeight: 600 }
const INACTIVE_CHIP = { bgcolor: 'transparent', color: 'text.secondary', border: '1px solid #e8e7e4', fontWeight: 400 }
export function ResultFilterBar({
filterSource,
onFilterChange,
@@ -45,7 +48,7 @@ export function ResultFilterBar({
{/* Source filter + toggles */}
<Box sx={{ display: 'flex', alignItems: 'center', flexWrap: 'wrap', gap: 0.5 }}>
<Stack direction="row" spacing={0.5} sx={{ flexWrap: 'wrap', gap: 0.5 }}>
{FILTER_OPTIONS.map(({ value, label, color }) => {
{FILTER_OPTIONS.map(({ value, label }) => {
const active = filterSource === value
return (
<Chip
@@ -54,12 +57,7 @@ export function ResultFilterBar({
size="small"
clickable
onClick={() => onFilterChange(value)}
sx={{
bgcolor: active ? color : 'transparent',
color: active ? 'white' : 'text.secondary',
border: `1px solid ${active ? color : '#e2e8f0'}`,
fontWeight: active ? 600 : 400,
}}
sx={active ? ACTIVE_CHIP : INACTIVE_CHIP}
/>
)
})}
@@ -67,36 +65,28 @@ export function ResultFilterBar({
<Divider orientation="vertical" flexItem sx={{ mx: 0.5 }} />
{/* Future Availability toggle */}
<Chip
size="small"
clickable
icon={<Zap size={11} color={showFutureAvailability ? '#7c3aed' : '#94a3b8'} />}
icon={<Zap size={11} color={showFutureAvailability ? '#5b3f8a' : '#c4c4c4'} />}
label="Future Availability"
onClick={() => onShowFutureAvailabilityChange(!showFutureAvailability)}
sx={{
bgcolor: showFutureAvailability ? '#f3e8ff' : 'transparent',
color: showFutureAvailability ? '#6d28d9' : 'text.disabled',
border: `1px solid ${showFutureAvailability ? '#c4b5fd' : '#e2e8f0'}`,
fontWeight: showFutureAvailability ? 600 : 400,
textDecoration: showFutureAvailability ? 'none' : 'line-through',
...(showFutureAvailability ? ACTIVE_CHIP : INACTIVE_CHIP),
bgcolor: showFutureAvailability ? '#152642' : 'transparent',
'& .MuiChip-icon': { ml: 0.75 },
}}
/>
{/* Eigene Objekte toggle — only for Property Managers */}
{isPropertyManager && (
<Chip
size="small"
clickable
icon={<Building2 size={11} color={showOwnProperties ? '#1e3a5f' : '#94a3b8'} />}
label="Eigene Objekte einblenden"
icon={<Building2 size={11} color={showOwnProperties ? 'white' : '#c4c4c4'} />}
label="Eigene Objekte"
onClick={() => onShowOwnPropertiesChange?.(!showOwnProperties)}
sx={{
bgcolor: showOwnProperties ? 'rgba(30,58,95,0.10)' : 'transparent',
color: showOwnProperties ? '#1e3a5f' : 'text.disabled',
border: `1px solid ${showOwnProperties ? '#1e3a5f' : '#e2e8f0'}`,
fontWeight: showOwnProperties ? 600 : 400,
...(showOwnProperties ? ACTIVE_CHIP : INACTIVE_CHIP),
'& .MuiChip-icon': { ml: 0.75 },
}}
/>
@@ -113,11 +103,7 @@ export function ResultFilterBar({
size="small"
clickable
onClick={() => onSortChange(value)}
sx={{
bgcolor: sortBy === value ? '#1e3a5f' : 'transparent',
color: sortBy === value ? 'white' : 'text.secondary',
border: `1px solid ${sortBy === value ? '#1e3a5f' : '#e2e8f0'}`,
}}
sx={sortBy === value ? ACTIVE_CHIP : INACTIVE_CHIP}
/>
))}
</Stack>