Skip to content

Sheet01 / 05 · The previous design

Claim typeEvidence · every figure measured

Groundoklch(31% 0.08 40) · deep

Measured4 September 2026

The previous design

This is what it looked like before, and why it is still here.

Keeping the old one as a switch would have been a nice trick and a bad answer, because the argument this site makes is that you hold yourself to a line rather than offering people a choice of looks. So it is not an option you can turn on. It is the exhibit.

The redesign is not a repaint. Almost everything that was wrong with the last one was structural, and the visual language changing is the smallest part of what happened. What follows is the part that can be measured, which is the only part worth putting on a page.

None of these numbers are estimates and none of them are rounded in my favour. Where a gate produces the figure, the figure on this page is read out of that gate rather than typed beside it, because I got that wrong twice in one afternoon and had to correct it by hand both times.

Kept because it is evidence. Deleted would have been tidier and would have proved nothing.

Sheet02 / 05 · What it cost

Claim typeStructural · reproducible by fetch

Groundoklch(93% 0.025 85) · bone, not white

Sourcesrc/hooks/useDeviceClass.ts

What it cost

One stylesheet, three copies of every page, and a shader nobody asked for.

The old site was built three times over. There was a mobile tree, a tablet tree and a desktop tree, and the browser picked between them after the page had already arrived.

That choice was made in JavaScript, which meant the server had no idea which one you wanted. It sent the compact one to everybody, on every device, every time. Your laptop downloaded the phone layout, hydrated it, threw it away, and built the desktop one from scratch in front of you.

It left the wreckage in the page. Thirty-eight elements ended up sharing an id with another element, including the one the skip link points at, and seven streaming placeholders were parked on the body holding a copy of a page nobody would ever see.

styles.css was 11,535 lines. The three trees lived in portfolio-v2/mobile, /tablet and /desktop, chosen by useDeviceClass, which returns compact on the server because a server has no viewport. Confirmed by fetching the homepage HTML: it contained m-hero and mobile-footer and no hero-blueprint at all.

Three of everything, and the wrong one shipped to everybody.

Sheet03 / 05 · The worst thing on it

Claim typeMeasured · Lighthouse attribution

Groundoklch(72% 0.17 55) · the only accent surface

Source@paper-design/shaders-react

The single worst thing on it

162 seconds

That is how much main-thread time one decorative background was charged with, on the phone Lighthouse tests against. Not milliseconds.

It was a WebGL mesh gradient sitting behind my own name at thirty-five per cent opacity, running an animation loop that never stopped. 263 kilobytes of shader code for a wash you would struggle to describe from memory after looking straight at it.

There was a check in front of it that was supposed to skip it on weaker hardware. It wanted four cores and four gigabytes, and the phone Lighthouse emulates has eight and four, so it ran on exactly the device it existed to protect.

@paper-design/shaders-react, loaded on all three shells. Total blocking time was 30,700ms in the run that started this. Replacing it with the same five colours as CSS radial gradients took that to 130ms and the score from 55 to 91 on its own.

Sheet04 / 05 · What changed

Claim typeMeasured · same tool, same throttling

Groundoklch(26% 0.065 40) · deeper

RunLighthouse 13.4.1, mobile, against production

What changed, measured

Fifty-five to ninety-one, and none of it was a redesign.

Every one of these came from the old design, before a single line of the new one existed. Worth saying plainly, because it would be easy to let the new look take credit for it.

Lighthouse, mobile, against production. 4 September 2026.
MetricWasNow
Performance, mobile5591
Total blocking time30,700ms130ms
Speed index5.0s1.5s
Accessibility100100
Same tool, same throttling, same page. Lighthouse 13.4.1, mobile, against production, 4 September 2026. Accessibility did not move because it was already there, and holding it at 100 through the work was the constraint rather than the achievement.

The look is the last thing that changed, not the first.

Sheet05 / 05 · Still wrong

Claim typeCounted · read from the gate

Groundoklch(93% 0.025 85) · bone

Commandnpm run tokens:check

Still wrong

53 colour literals, and a design that arrived with sixty-three.

The count on the front page is not a boast about how low it is. It is on screen because hiding it would be the entire problem.

There are 53 raw colour values in this codebase that bypass the theme, and a ratchet that only ever lets that number go down. The new design was handed over with a table of nineteen tokens and a note saying four grounds and one accent is the whole palette, and then used sixty-three distinct colours across its nine drawings.

Fifteen of those were already a token and thirty-six were drift, within a shade of one and doing its job. The rest were real roles nothing had named. They are named now, and 56 pairings are checked on every run, nine of them measured and not gated because they are decoration.

Nine values ship at something other than what was drawn, each one because the gate would not pass it. The largest single change was an ordinal at 3.83:1 on its resting ground and 2.82:1 on the ground it takes on hover, which matters because the whole row is one link and it has to hold on both.

A design that argues against colour literals does not get to arrive with sixty-three of them.