Design System
Every token this template uses, and what it is for.
Re-skinning this template means changing the values in the :root block of
src/styles/global.css and nothing else. This page renders whatever is in
there right now, so it stays true after you have changed it.
Colour
Two constraints decided this palette and neither was stylistic. The warm band, the greens
and the blues are all taken by earlier days. And this template sits directly next to day 75
in the gallery grid, which is a cool drafting grey with an indigo mark on it — so the
neighbour has to be warm, domestic and unmistakably a house. That leaves the magenta-plum
band, which is right for a reason beyond availability: the kitchen is the one room where a
saturated cabinet colour is normal. Warm rose plaster carrying a purple mark is not
confusable at thumbnail size with warm yellow paper carrying an olive mark, or with cool
grey carrying indigo. Every ratio below was computed with
tools/a11y/contrast.py, not eyeballed.
Ground
-
--color-bgPage ground — plaster, hue 27° -
--color-bg-altAlternating band and record cards — chalk -
--color-surfaceCards, forms and the week strips — sheet white -
--color-borderHairlines — decorative only, 1.41:1 -
--color-border-strongInteractive borders 3.41:1 AA
Ink
-
--color-textBody and headings — ink 16.01:1 AAA -
--color-text-faintLabels and eyebrows 9.27:1 AAA -
--color-text-mutedSecondary prose — warm grey 5.84:1 AA
Accent
-
--color-accentButtons, rules and text — damson 6.49:1 AA -
--color-accent-hoverPressed state 10.42:1 AAA -
--color-accent-textAccent-coloured text 5.71:1 AA -
--color-bookingBooking bar ground 7.21:1 AAA -
--color-requiredRequired-field mark only 7.21:1 AAA
Record flags
-
--color-flag-overRecord: ran past the promise 8.98:1 AAA -
--color-flag-underRecord: finished early 7.48:1 AAA -
--color-flag-evenRecord: on the promised day 10.31:1 AAA
Week strip
-
--color-strip-fullWeek strip — solid block 7.21:1 AAA -
--color-strip-partWeek strip — hatched block 3.73:1 AA (graphical) -
--color-strip-noneWeek strip — outline only 3.79:1 AA (graphical)
Dark sections
-
--color-dark-bgHero, living-here band, footer -
--color-dark-surfaceCards inside dark bands -
--color-dark-textText on dark 16.01:1 AAA -
--color-dark-faintMaker strip and callouts 11.39:1 AAA -
--color-dark-mutedSecondary on dark 8.44:1 AAA -
--color-dark-accentAccent on dark — damson light 9.32:1 AAA
Two tokens carry the same idea on two grounds, which is the correct answer rather than a
duplication: no single value clears 4.5:1 against both plaster and ink, so the accent is
--color-accent on light and --color-dark-accent on dark. The maker
strip and the download bar are written as literal hex rather than as var()
fallback chains, because a fallback chain that resolves to currentColor is not
a fix — it is a silent no-op that changes nothing and looks like a repair in the diff.
The three record flags are deliberately not a traffic light. Two of the six records on the home page ran past what was promised and that is the point of the section, so "ran over" is set at the same weight and the same legibility as "finished early". A flag that shouts would turn a record back into an advert.
The week strip is the one place in this template where a block of colour carries meaning, and it is deliberately not carried by colour. Solid, hatched and outline are three different shapes, every block also renders a screen-reader reading of what it means on its own row, and the strip is drawn on white rather than chalk because the mid fill measures 3.73:1 on white and only 2.95:1 on chalk.
Type
Faustina for display, Hanken Grotesk for body, and nothing else. The serif is a gallery decision before it is a craft one: days 74 and 75 both broke to grotesks and a third consecutive grotesk would make three adjacent thumbnails read as one system. Faustina is a compact humanist serif with a large x-height drawn for tight settings, which is the practical requirement too — the headlines here are long and domestic and a wide display serif breaks them over four lines on a phone. Hanken Grotesk is a warm geometric-humanist sans with a generous x-height, and the displacement records are why it wins: six labelled lines per project at small sizes, full of dates and day counts, sitting next to a week strip whose column labels are tiny.
No third family, and specifically no monospace. Day 75 loaded a mono for
its ledger columns; repeating a mono figure column here would echo the neighbour in exactly
the wrong place, and the numbers on this page are day counts inside prose lines rather than
columns that must align. Where figures do stack — the week strip — the
.figures class sets font-variant-numeric: tabular-nums on Hanken
Grotesk, which is harmless where unsupported.
-
We will tell you the day you get your sink back.
-
When not to move the sink.
-
The 1926 story-and-a-half where the chimney chase could not move
-
A photograph of a finished kitchen proves a kitchen was built. It does not tell you apart from the designer, the cabinet supplier or the photographer, all of whom have that same picture.
-
Disconnected 14 Apr, running again 6 May. 22 days without a kitchen sink.
-
W1 W2 W3 W4 W5 W6 W7 W8 · 31 on site · 9 nobody came
-
THE MIDDLE, NOT THE AFTER
Interaction states
Every interactive element carries a themed hover and a visible keyboard focus ring. Tab
through the row below rather than clicking it — the focus ring is the part most templates
leave as the browser default, and it is the one a keyboard user depends on. Nothing here is
muted with opacity: opacity composites text toward its background, which is
exactly what contrast measures.
Decorative marks
Every decorative mark in this template is an inline SVG, and none of them is a character. Day 74 shipped a Geometric Shapes glyph with a variation selector and it rendered as a tofu box on machines whose fonts did not cover it; five sibling templates were converted to inline SVG for the same reason. Day 75 still set the Pro download bar's padlock as an emoji codepoint, which is the same bet with a different die; here it is drawn. A glyph is a font-coverage bet, an SVG is not.
Spacing and radii
Sections are separated by --section-gap. Everything uses a 4px radius and
nothing uses a pill, because a cabinet door has square corners and a page about a room
should not look like an app. Nothing else invents a value.
0.5remtight stacks1reminside cards1.5rembetween cards--section-gapbetween sections