The Fire · design system · v0

Simple. Sharp.
Nothing decorative.

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

Mono means a machine made it.

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.

Sans — Satoshi

Headlines, prose, party and member names, section titles, any sentence.

Nathaniel Erskine-Smith has broken with his own caucus more often than any other sitting member.

Mono — Geist Mono

Every numeral. Labels. Dates. Vote IDs. Sources. Snapshot hashes.

2,691 votes · 73 dissents · 2.71%
44-1 / №348 · 2026-06-18 · aebf3673…4bc3f
Why this is not just taste

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

Six sizes, two families, one weight axis.

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.

Display3.1rem / 500 / −.04em Party discipline
Head1.9rem / 500 / −.03em Almost nothing happens
Sub1.25rem / 500 / −.02em What was being voted on
Body1rem / 400 / −.011em Of 1,270,388 votes cast in the House of Commons since 2006, 1,814 broke with the member’s own caucus.
Small0.86rem / 400 Independents are excluded from this chart. The source database records no party position for them, so their dissent flag is an artefact.
Numeralmono / 500 / tabular 1,270,388
Labelmono / 500 / +.18em / caps Votes cast since 2006
Sans charset AÀÂÇÉÈÊËÎÏÔÙÛÜŒaàâçéèêëîïôùûüœ ABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789 —–’“”§№%·×→
Mono charset 0123456789 O0 Il1 rn m S5 B8 Z2 −+×÷=%‰ ()[]{}⟨⟩ ../:;-_ →↑↓ #№§ †‡ aebf3673…4bc3f

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

Cold ground. Bone marks. One lit accent.

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.

ground#0A0A0BThe page. Never lighter.
ground-2#0F0F10Row hover, inset panel.
raise#141416Card, callout.
rule#232326Structural divider.
rule-2#1A1A1CTable row divider.
bone#ECE7DDHeadlines, numerals, primary text.
bone-2#B9B3A8Body prose.
muted#807B72Secondary, table headers.
dim#57544ELabels, captions, provenance.
dark#37352FUnlit data. Absence.
lit#FFCF8AA dissent. Earned, never decorative.
lit-hot#FFE6C215+ dissents on one division.

Party colour is identity, never judgement.

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.

Votes cast and dissents recorded, by caucus, 2006-05-08 to 2026-06-18. Denominator excludes recorded absences and paired votes, per correction 0001; /discipline still shows the withdrawn figures and says so.
PartyDisplayOfficialVotesDissentsRate
Conservative#5C8FD6#142F52510,1838311 in 614
Liberal#E8555C#D71920479,1287751 in 618
NDP#F58220#F58220189,6811271 in 1,494
Bloc Québécois#51A5E1#08023678,220201 in 3,911
Green#3FBF63#20A2424,6850

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

A figure never appears without its denominator.

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.

1,270,388Votes cast Every yea and nay by every member, 2006-05-08 to 2026-06-18.
1,814Broke with caucus 0.143% of all votes cast. One in every 700.
4,116Divisions with none Of 4,654 recorded divisions — 88.4% had zero dissent.

05 — Standing rules

What the design is not allowed to do.

  1. The mark is a mark, not a picture.The flame appears once per page at 24px, in the masthead, and full size on the front page only — which is the one page about the project rather than about the record. It is the sole saturated colour on the site. It never appears inside a chart, never beside a number, never at a size where it competes with the thing being counted. Amended 2026-08-05. This rule previously read “No flame imagery. Ever.” — the argument being that a logo with a fire in it would make the project look like the thing it refuses to be. Overruled by the author, who owns the mark and wanted it used. The scale limit above is what survived of the original objection, and it is the part that was actually load-bearing.
  2. The picture may never contradict the sentence next to it.Ten bugs of exactly this class have shipped and been caught in screenshot review: a disclosed artefact rendering as the longest bar, a matrix reading backwards, glow bloom making 11.6% look like a third of the field, a masthead dot pulsing as though the page updated live when the record arrives in a monthly bulk load. Every chart is reviewed as an image, not as source. The same applies to the type: no synthetic oblique, no faux bold. A skewed roman is the rendering claiming an italic exists when none was drawn — which is exactly what shipped on the riding pages until a screenshot caught it.
  3. No score, rank, grade, or league table.Counting is the product. The moment a number is weighted toward a conclusion this becomes a scorecard with better typography.
  4. Every number links to its source.Not a methodology page — the actual division, the actual bill, the actual query. A figure the reader cannot follow home is an assertion.
  5. The disclosure travels with the thing.Caveats live beside the chart they qualify, in the same viewport, at readable size. Never in a footnote, never behind a toggle.
  6. Motion is reveal only.Data may fade or draw in once on entry. Nothing loops, nothing pulses, nothing draws attention to itself after it has arrived. All of it respects prefers-reduced-motion.
  7. Assets are vendored.Fonts and libraries are served from our own origin with a one-year immutable cache. A page that claims to be independently verifiable should not require a third party to be up — and no reader looking up their own MP should have their address handed to a font CDN.
  8. Every page footer carries the snapshot date and hash.Two people comparing numbers a month apart need to be able to tell whether they disagree or whether the record moved.

06 — Grid and rhythm

One column, 940px, generous rules.

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

The sans is Satoshi, and it is served in known tension with its licence.

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.

What the decision cost, and what was done to limit it

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 same page components set twice: on the left in Geist, on the right in Satoshi. Both use Geist Mono for numerals.
Left: Geist, which shipped first. Right: Satoshi, which is what you are reading. Same copy, same sizes, same colours, Geist Mono for numerals in both. Rendered locally from the font files, so this page still makes no third-party request.

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.