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
The trap in a carpenter template is obvious and worth naming: it wants to be brown, and
brown is gone — three trades in a row already own the wood-tone band. So the chrome is not
the material. The wood is warm; the furniture is paper, ink and a green that belongs to the
shop rather than the board. Every ratio below was computed with
tools/a11y/contrast.py, not eyeballed.
Ground
-
--color-bgPage ground — shop paper -
--color-bg-altAlternating band — oak tint -
--color-surfaceCards and panels -
--color-borderHairlines -
--color-border-strongInteractive borders 3.20:1 AA
Ink
-
--color-textBody and headings — walnut ink 15.20:1 AAA -
--color-text-faintLabels and eyebrows 10.26:1 AAA -
--color-text-mutedSecondary prose — pencil grey 5.14:1 AA
Accent
-
--color-accentButtons, rules and text — moss 6.01:1 AA -
--color-accent-hoverPressed state 9.65:1 AAA -
--color-accent-textAccent-coloured text 5.30:1 AA -
--color-leadtimeLead-time bar ground 6.84:1 AA -
--color-requiredRequired-field mark only 9.30:1 AAA
Dark sections
-
--color-dark-bgHero, process band, footer -
--color-dark-surfaceCards inside dark bands -
--color-dark-textText on dark 15.20:1 AAA -
--color-dark-faintMaker strip and callouts 10.40:1 AAA -
--color-dark-mutedSecondary on dark 8.21:1 AAA -
--color-dark-accentAccent on dark — moss light 7.93: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 warm paper and walnut 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.
Type
Familjen Grotesk for display, Commissioner for body — two sans, deliberately, because days 72 and 73 both led with a serif and a third in a row makes three adjacent gallery thumbnails look like one template in three colours. Familjen Grotesk is squared-off and slightly narrow: it looks set out with a try square, and the narrowness keeps a long specific headline off a third line on mobile. Commissioner is a low-contrast humanist with a generous x-height, chosen for the spec blocks — four short labelled lines carrying fractions and species names is cut-list typography and it needs a body face that stays legible at 13px rather than one with personality.
-
That is the job
-
Built-in, or bought-in.
-
A window seat over a floor that fell away an inch to the bay
-
A factory carcase is a rectangular prism. Your 1918 alcove is not, and that gap is the entire commercial reason this trade exists.
-
East wall out of plumb 5⁄8" top to bottom; face frames dominoed and built 3⁄8" narrow.
-
RECENT BUILT-INS
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.
Spacing and radii
Sections are separated by --section-gap. Cards use an 8px radius, pills use
999px, and the credential chips use 4px because a joinery site should look machined rather
than rounded over. Nothing else invents a value.
0.5remtight stacks1reminside cards1.5rembetween cards--section-gapbetween sections