diff --git a/site/src/components/NerdCorner.svelte b/site/src/components/NerdCorner.svelte index b6093ee..0b28a31 100644 --- a/site/src/components/NerdCorner.svelte +++ b/site/src/components/NerdCorner.svelte @@ -22,12 +22,28 @@ time: v => `${v.toFixed(1)} h`, }; - // Colours for past years — current year is always blue-400 - const PALETTE = [ - '#f97316', '#34d399', '#a78bfa', '#f43f5e', - '#facc15', '#22d3ee', '#fb923c', '#4ade80', + // Cool→warm ramp for past years; current year is always blue-400 + // t=0 → oldest past year (muted purple), t=1 → most recent past year (warm coral) + // Stops: [t, hue, sat%, light%] + const _RAMP: [number, number, number, number][] = [ + [0.00, 265, 38, 52], // muted purple + [0.18, 230, 45, 55], // slate-blue + [0.36, 185, 52, 50], // teal + [0.54, 145, 48, 47], // green + [0.70, 50, 72, 52], // amber-yellow + [0.84, 25, 80, 55], // orange + [1.00, 5, 70, 57], // warm coral-red ]; + function _rampColor(t: number): string { + let i = 0; + while (i < _RAMP.length - 2 && t > _RAMP[i + 1][0]) i++; + const [t0, h0, s0, l0] = _RAMP[i]; + const [t1, h1, s1, l1] = _RAMP[i + 1]; + const f = (t - t0) / (t1 - t0); + return `hsl(${Math.round(h0 + (h1 - h0) * f)},${Math.round(s0 + (s1 - s0) * f)}%,${Math.round(l0 + (l1 - l0) * f)}%)`; + } + function dayOfYear(d: Date): number { return Math.floor((d.getTime() - new Date(d.getFullYear(), 0, 0).getTime()) / 86400000); } @@ -68,8 +84,14 @@ } const colorDomain = years.map(String); - const colorRange = years.map((y, i) => - y === _currentYear ? '#60a5fa' : PALETTE[i % PALETTE.length]); + const pastYears = years.filter(y => y !== _currentYear); + const colorRange = years.map(y => { + if (y === _currentYear) return '#60a5fa'; + if (y < 2000) return '#71717a'; // undated bucket (year 0 / "0000") + const i = pastYears.indexOf(y); + const t = pastYears.length <= 1 ? 0.5 : i / (pastYears.length - 1); + return _rampColor(t); + }); return { rows, colorDomain, colorRange }; }