diff --git a/frontend/src/components/ClusterGrid.tsx b/frontend/src/components/ClusterGrid.tsx
index aa03a8a..e77d222 100644
--- a/frontend/src/components/ClusterGrid.tsx
+++ b/frontend/src/components/ClusterGrid.tsx
@@ -103,13 +103,23 @@ function statusFor(p: any): SpotStatusEntry | undefined {
// Status column, using the same colours as the per-cell fills (NEW DXCC =
// call cell, NEW BAND = band cell, NEW SLOT = mode cell). Returns null when
// there's nothing notable to show.
-function statusBadge(t: TFn, s: SpotStatusEntry | undefined): { text: string; fg: string; bg: string } | null {
+type Badge = { text: string; fg: string; bg: string; bd: string };
+
+// tok builds a badge from a semantic status token (success/warning/caution/
+// danger/info/neutral) so the colours adapt to every theme via CSS variables,
+// instead of the hard-coded light-theme pastels that looked wrong in dark mode.
+function tok(name: string, text: string): Badge {
+ if (name === 'neutral') return { text, fg: 'var(--muted-foreground)', bg: 'var(--muted)', bd: 'var(--border)' };
+ return { text, fg: `var(--${name}-muted-foreground)`, bg: `var(--${name}-muted)`, bd: `var(--${name}-border)` };
+}
+
+function statusBadge(t: TFn, s: SpotStatusEntry | undefined): Badge | null {
switch (s?.status) {
- case 'new': return { text: t('clg2.newDxcc'), fg: '#be123c', bg: '#ffe4e6' };
- case 'new-band': return { text: t('clg2.newBand'), fg: '#92400e', bg: '#fde68a' };
- case 'new-mode': return { text: t('clg2.newMode'), fg: '#854d0e', bg: '#fef08a' };
- case 'new-slot': return { text: t('clg2.newSlot'), fg: '#854d0e', bg: '#fef08a' };
- default: return s?.worked_call ? { text: t('clg2.wkdCall'), fg: '#0369a1', bg: '#e0f2fe' } : null;
+ case 'new': return tok('danger', t('clg2.newDxcc'));
+ case 'new-band': return tok('warning', t('clg2.newBand'));
+ case 'new-mode': return tok('caution', t('clg2.newMode'));
+ case 'new-slot': return tok('caution', t('clg2.newSlot'));
+ default: return s?.worked_call ? tok('neutral', t('clg2.wkdCall')) : null;
}
}
@@ -132,8 +142,8 @@ const makeColCatalog = (t: TFn): ColEntry[] => [
// the rest of the row across every theme instead of always shouting orange.
cellStyle: (p: any): any => {
const s = statusFor(p);
- if (s?.status === 'new') return { backgroundColor: '#ffe4e6', color: '#be123c', fontWeight: 700 };
- if (s?.worked_call) return { color: '#0369a1', fontWeight: 700 };
+ if (s?.status === 'new') return { backgroundColor: 'var(--danger-muted)', color: 'var(--danger-muted-foreground)', fontWeight: 700 };
+ if (s?.worked_call) return { color: 'var(--info)', fontWeight: 700 };
return { fontWeight: 700 };
},
tooltipValueGetter: (p: any) => {
@@ -162,18 +172,20 @@ const makeColCatalog = (t: TFn): ColEntry[] => [
},
cellRenderer: (p: any) => {
const s = statusFor(p);
- const badges: { text: string; fg: string; bg: string }[] = [];
+ const badges: Badge[] = [];
const b = statusBadge(t, s);
if (b) badges.push(b);
- if (s?.new_county) badges.push({ text: t('clg2.newCounty'), fg: '#6b21a8', bg: '#f3e8ff' });
- if (s?.new_pota) badges.push({ text: t('clg2.newPota'), fg: '#166534', bg: '#dcfce7' });
- if (badges.length === 0) return —;
+ if (s?.new_county) badges.push(tok('info', t('clg2.newCounty')));
+ if (s?.new_pota) badges.push(tok('success', t('clg2.newPota')));
+ if (badges.length === 0) return —;
return (
{badges.map((bd, i) => (
{bd.text}
))}