The Fire · design system · v0
Every page of The Fire is a rendering of a public record. The design has one job: make the number legible and make its provenance impossible to lose. Everything below is a constraint, not a preference.
01 — The one rule everything else follows
The type system carries a claim. Sans is for language a human wrote. Mono is for anything derived from the record — counts, dates, division numbers, session IDs, hashes, percentages, sources. The reader can tell at a glance which parts of a page are argument and which parts are arithmetic, without being told.
Headlines, prose, party and member names, section titles, any sentence.
Every numeral. Labels. Dates. Vote IDs. Sources. Snapshot hashes.
An autonomous accountability machine has to be visibly separable from its author. The typographic split is the cheapest possible version of that disclosure, and it runs on every page without anyone maintaining it.
02 — Type scale
Sans runs at 400 for prose and 500 for anything structural. There is no 600+, no italic, and no third family. Tight negative tracking on display sizes; wide positive tracking on uppercase mono labels. Nothing in between.
Both families ship as one variable file each, from our own origin, with a one-year immutable cache. Geist Mono is subset to Latin plus the punctuation the record actually contains — every French diacritic in a riding name, the em dash Parliament uses in constituency names, and the numeric operators. Satoshi is served byte-identical to the file the foundry distributes: unsubset, unconverted, still a TrueType variable font rather than a WOFF2. That costs about 70 kB and it is deliberate — see §07. satoshi-variable.ttf 124 kB · geist-mono.woff2 38 kB. Over the wire, gzipped: 54 kB · 38 kB.
03 — Ground and marks
The palette is almost entirely neutral so that the single warm value means something when it appears. Lit amber is reserved for data that crossed a threshold — a dissent, a break, an exception. It is never used for chrome, never for a hover state on a link, never for emphasis in prose.
There is one ground, and it is this one. The riding pages shipped light first, on the argument that a reference document people cite from wants to look like paper. That was overruled on 2026-08-05 — one site, one surface, and a reader arriving at their own constituency from the essay should not feel they have changed buildings. There is no prefers-color-scheme branch anywhere on the site. The single exception is @media print, where the tokens invert wholesale: a black flood at 300 dpi is unreadable and costs a cartridge, and the riding pages are meant to be printable. Type, structure, figures and sources are otherwise identical — the printout is the same document, not a reduced one.
One token exists only because of that decision. Six rules on the riding pages were set in --ink, which was correct as near-black at 2 px on paper and became a light source at near-white on ash. --rule-strong #4A4740 carries the same structural weight without emitting light. A value that is right on one ground is not right on the other simply inverted.
Each party's value is derived from its own live brand hex, lifted in lightness at constant hue so it survives a dark ground. The official value is disclosed on every page that uses it. No party is ever assigned a warmer or cooler value to imply anything about its record.
| Party | Display | Official | Votes | Dissents | Rate |
|---|---|---|---|---|---|
| Conservative | #5C8FD6 | #142F52 | 510,183 | 831 | 1 in 614 |
| Liberal | #E8555C | #D71920 | 479,128 | 775 | 1 in 618 |
| NDP | #F58220 | #F58220 | 189,681 | 127 | 1 in 1,494 |
| Bloc Québécois | #51A5E1 | #080236 | 78,220 | 20 | 1 in 3,911 |
| Green | #3FBF63 | #20A242 | 4,685 | 0 | — |
The Bloc's own post-2021 brand colour is the deep navy #080236, not the light blue every broadcaster uses. We use a lifted version of the blue they also ship, because navy is illegible on this ground — and we say so here.
04 — The number block
The standard component. Number in mono, label in caps mono, and a plain sentence underneath saying what the number is out of. The third line is not optional — a count without a denominator is a talking point, not a fact.
05 — Standing rules
06 — Grid and rhythm
Prose is capped at 38em regardless of container width. Sections are separated by a 1px rule at --rule and 5.5rem of space, always in that order — the rule belongs to the section beginning, not the one ending. Data components go full width; sentences never do. Charts are the only elements permitted to exceed the text column.
07 — The Satoshi problem
Satoshi is distributed under the ITF Free Font License. It is free for commercial use, but §02 reads: “You are not allowed to transmit the Font Software over the Internet in font serving or for font replacement … without the prior written consent of the Licensor,” and the same section prohibits modifying the file. The licensed delivery path is the Fontshare API, from their CDN.
The CDN is a legitimate way to use the font, and for most sites it is the obvious answer. Here it costs two things: an external dependency on a page that claims to be independently verifiable, and every reader's IP address handed to a third party at the moment they look up their own MP's voting record. The second one is the real objection, and it is the one rule 07 exists to prevent.
So there is no clean option. Self-hosting is outside the licence as written; the CDN is inside the licence and outside our own rules. On 2026-08-05 the author chose to self-host, having been shown the clause, and accepted the risk. That is recorded here rather than quietly absorbed, because a project that asks members of Parliament to live with their record on a public page has to be able to do the same.
The file is served unmodified. §02 bars two separate things: serving
the font, and modifying it. Subsetting it to Latin would have saved roughly 70 kB and
converting it to WOFF2 another 10 kB — and both are arguably modifications. Shipping
the exact bytes the foundry distributes means the arrangement is outside one clause
instead of two. The 124 kB is the price of that, paid on purpose.
Written consent is still worth asking for. ITF grant it routinely.
Nothing is blocked on it, and if it is refused, reverting is one CSS variable and one
font file — the fallback stack is already Geist-shaped.
The two faces are not interchangeable and the swap was not free. Satoshi's x-height is 0.500 em against Geist's 0.530, so it reads about six per cent smaller at the same size; every body size on the site went up to compensate. Its advance is 4.7% wider on the same string, so tracking tightened from −.005em to −.011em. Its descender is shallower and it carries a 100-unit line gap, so leading came down from 1.62 to 1.60. Its cap-to-x ratio is 1.48 against Geist's 1.34 — bigger capitals over smaller lowercase, which is why the uppercase mono labels sit beside it without looking undersized. And it draws no italic at all, in any of its five weights, which is why rule 02 has a clause about synthetic oblique.