The translation desk at Halvorsen & Wren, a literary press: chapter seven of a novel out of Spanish, the source and the English side by side, and every open decision in the margin beside the line it is about.
claude-brand is the third house style in this portfolio, after calm-practice and apex-brand, and the one that needed the least inventing. The other two had no vendor and no published values, so their generators solve a palette from a declared ground up. This style publishes everything: a twenty-one step ramp, thirteen named colours, fifteen type steps, a leading ladder, ten radii, four border widths, seventeen spacing rungs, six measures in ch, nine easings and three durations, all of it in its own stylesheet. There was nothing here to make up, which changes what the generator is for.
Where the style comes from
The reference is claude.com. Seven stylesheets carry the whole style — 419,714 bytes, re-fetched 2026-09-16 across /, /pricing and /product/claude-code, which is what it takes to see all seven — and everything in the table below was measured out of those files rather than described from a look at the page.
| Decision | Measured |
|---|---|
| Faces | three, self-hosted: a sans (28 declarations), a serif (21), a mono (7), each shipping a roman and an italic |
| Ramp | 21 steps at 50-unit granularity, L 0.9818 down to 0.1908, plus pure white and pure black at the ends |
| Ramp hue | 19 of the 21 steps carry chroma, at hue 95–107; two of them (850, 900) leave for hue 68 |
| Named colours | 13: one brand terracotta with two darker rungs, and twelve illustration colours named after materials |
| Type ramp | 15 steps: 2 display, 6 headline, 2 large body, 3 body, a caption at 12px and a micro at 10px |
| Fluid | every step above 19px is a clamp(), and all of them are solved between 320px and 1440px |
| Leading | a named ladder of seven — 1, 1.1, 1.2, 1.3, 1.5, 1.6, 1.7 — where every reading step takes 1.6 and every display step takes 1.1 or 1.2 |
| Tracking | six distinct values in 373 kB, and the display steps are not among them: the largest type is set at normal tracking |
| Weights | 300 to 700, plus 480 for a button, which only a variable face can express |
| Radii | 2 · 4 · 6 · 8 · 12 · 16 · 24 · 32 · 48 · 64px, and the four in real use are 8, 12, 16 and 24 (21, 19, 21 and 16 declarations) |
| Borders | 0.5 · 1 · 1.5 · 2px |
| Spacing | 17 rungs, 2px to 200px |
| Section rhythm | three rungs, 64→96 · 96→128 · 128→200, plus an even half-step at 52→64. The 32→64 clamp beside them is the page's own side gutter, --container-margin, and is not a rung |
| Measures | six, in ch: 20 · 30 · 45 · 60 · 70 · 80 |
| Holds | 660 · 960 · 1192 · 1440px |
| Easings | nine, named by curve rather than by use, the extreme of them cubic-bezier(1, 0, 0, 1) |
| Durations | three: 60ms · 200ms · 450ms. .3s appears eighteen times as a literal and never as a declared rung |
| Shadows | three, and the largest is 16px of blur at 10% black |
The structural finding, and the reason this is a system rather than a palette. Every step of that ramp is warm. The lightest is a paper at hue 95 and the darkest is an ink at hue 107, with a real chroma on nineteen of the twenty-one steps — so a page in this style is not a grey page with a colour on it, it is paper. That is also why neither end of the ramp is white or black even though both are declared: the two pure values sit outside the family and are used for a label on a fill rather than for a ground.
The second finding is about what a published palette leaves out. A ramp is not a palette until something says which step is body text and which is a rule, and the reference's own semantic layer answers that for its pages, not for somebody else's. So claude_tokens.py solves the assignment: each role is the step nearest its limit that still clears its WCAG ratio against the worst ground in its theme rather than against the page background, which is the mistake that ships a secondary colour legible on a card and illegible in the well beside it. Fifty pairs, both themes, none failing.
The three things that came out of doing it that way
- The brand terracotta cannot be text on the paper. It measures 2.96:1, which clears neither the 4.5:1 body text owes nor the 3:1 a control boundary owes; its two darker published rungs reach 3.68:1 and 3.85:1 and stop. So a text rung is solved at the same hue and chroma — the only colour in the emitted file the reference does not publish — and the brand colour itself stays a fill and a mark.
- White on terracotta is 4.05:1, and the reference puts white on terracotta. The label on the fill is the near-black here instead, at 4.55:1. Darkening the brand colour until white cleared was the other option and it was refused: this style publishes that colour, and moving it to keep a white label spends the thing the style is for. The reference's own primary button token is the far end of the ramp rather than the brand colour, which is the same conclusion reached from the other direction, so the filled control on this page is the ink at 17.50:1.
- The illustration palette is theme-independent. All twelve of those colours are lighter than L 0.84, so the near-black is the only label either theme can put on them — 11.42:1 to 13.31:1 — and a note keeps its colour when the page inverts. They are grounds for a mark, never ink: every one of them is under 1.6:1 as text on the paper, which
--self-testasserts in both directions so that spending one as a colour is impossible rather than discouraged.
The direction
- Archetype. Split. Two documents in one grid, so a source paragraph and its translation are the same row and cannot drift apart while somebody scrolls.
splitis taken once elsewhere in this portfolio, bysap-fiori, and that page spendstable-first. - Stance. Prose-first. The heading is the book, the sentence under it is what the chapter is waiting on, and the counts are evidence beneath the sentence rather than four tiles across the top. The product is two columns of prose and a decision about a word; anything tile-first here would be a dashboard about a novel.
- Density. Comfortable, and read rather than scanned: 17px at 1.6, a forty-five character measure in each column, and a fourteen-rem margin between them that is a column of its own rather than an overlay.
- The bold thing. No toolbar. Every control that acts on the translation sits in the margin at the segment it changes, and the one warm colour does exactly one job per screen: it marks the segment waiting on a person. Three controls sit outside that rule and none of them touches the book — the way back to the portfolio, the balance of the two columns, and the theme. Balance and theme are the same kind of thing, which is the line the page draws.
The hard state
CONTRACT.md §3b asks for the state the archetype makes hardest, and for a split that is non-correspondence: the shape pretends the two sides pair up one to one, and a real translation does not. Three of the six segments on the page are that, drawn as ordinary states of a bilingual document rather than as errors:
- 28 — one paragraph into three. Her sentence turns twice on semicolons and English will not hold both turns in one breath, so the pair is deliberately not one to one and the margin says so.
- 29 — a sentence with no source. The translator's own clause, added for a reader who does not know what a conventillo was. The source half is a written-out absence rather than an empty cell.
- 31 — held for rights. Ocampo-Salas quotes a stanza from 1911. The Spanish is out of copyright and the 1978 English translation the press wants is not, so the segment cannot ship and the chapter goes without it. The control that would quote it is present, disabled, styled as disabled, and carries the reason beside it.
And 30 is the one waiting on a person: a term with three defensible renderings and no right answer, each with what it costs, on the page's only ground of its own. Choosing one writes it into the translation, settles the segment, and takes one off the count the chapter head and the delivery panel both report.
Generated
python3 tools/claude_tokens.py --both > systems/claude-brand/tokens.css
python3 tools/claude_tokens.py --check # 50 pairs, both palettes
python3 tools/claude_tokens.py --self-test
Measured
python3 tools/claude_tokens.py --check — 50 pairs across both palettes, 0 failing. The pairs the page leans on hardest:
| What sits on what | Carries | Ratio |
|---|---|---|
#141413 on #faf9f5 | the source, the translation, every heading | 17.50:1 |
#4d4c48 on #f0eee6 | every margin line, on the worst ground | 7.40:1 |
#5e5d59 on #f0eee6 | the quietest label, on the worst ground | 5.67:1 |
#141413 on #c6613f | the label on the terracotta mark | 4.55:1 |
#ad5030 on #f0eee6 | every link, on the worst ground | 4.56:1 |
#87867f on #f0eee6 | every control boundary, on the worst ground | 3.15:1 |
#141413 on #e3dacc | the marked term, both themes | 13.31:1 |
Dark theme, the same roles: 16.66:1, 6.82:1, 5.38:1, 5.90:1, 4.51:1, 3.14:1 and 13.31:1.
The decorative rule is held deliberately below the 3:1 a control boundary owes — 2.11:1 light, 2.04:1 dark — so substituting it for a stroke has to be somebody's decision. --self-test asserts that, and asserts that the step one rung past each solved limit fails, without which every pass above is uninformative.
The highlight under segment 30 is solved as a ground rather than as a colour: the faintest wash of the brand colour into the paper that is still visibly another ground, at ΔEOK 0.02, which lands at 6% and carries the body ink at 16.51:1 light and 15.83:1 dark. Solved the other way — the strongest wash the ink still clears — it came out at 100%, which is the brand colour itself, and a highlight the same colour as the mark beside it is one signal doing two jobs.
Browser, both themes: a11y-probe.mjs clean at 1280px with every run catching its control probe; shots.mjs clean at 1440px and 375px, document 1440/1440 and 375/375; drive-probe.mjs drove thirteen controls without a throw, an emptied region or a lost focus. Driven by hand as well: choosing a rendering moves the counts 3 → 2 and 40 → 41 and back on reopen, the balance writes the column header and the segment list to the same three tracks (428/224/428 even, 548/224/308 source-wide), and interrupting the swap mid-exit still lands the last choice, which is the transitioncancel path.
Deviations, and their reasons
- The three faces are not the reference's. They are proprietary and self-hosted, and CONTRACT.md §2 admits Google Fonts only, so each is substituted by an open-licensed variable face doing the same job: Instrument Sans where the interface speaks, Source Serif 4 where the book does, JetBrains Mono for the numbers. What is kept is the division of labour — a serif that reads and a sans that operates — which is the part of the decision that belongs to the style rather than to the foundry.
- The fluid sizes keep the measured endpoints and not the measured form. The reference's clamps carry a px constant plus a vw term (
28.857px + 1.607vw), which between the two bounds ignores the reader's own font-size setting. Every step here is re-solved through the same two widths inrem, whichtypography's own solver warns about and is the reason it is not a transcription.
- Four literal colours, in the two places a
var()cannot reach. The favicon'sdata:URI and the twotheme-colormetas are parsed outside CSS. Each value is transcribed fromtokens.cssand the comment above them names which token it is.
- The caption step is 12px, and APCA licenses no body text that small at any contrast. Measured: the near-black on paper is Lc 101 and still fails APCA's font table at 12px/400, as does every other pair on the page, because the table itself starts at 15px. It is the published step and this page keeps it, at weight 500 or above, for labels and margin notes rather than for anything read at length; the two state marks that sit lowest on APCA (Lc 36 light, Lc 45 dark) each carry a word and a shape as well as a colour. The gate this portfolio holds is WCAG 2.2 AA, which every pair clears.
Findings kept, with reasons
slop_scan·default-ai-palette— cream and terracotta is named as one of the three palettes generated design converges on, "legitimate if the brief asked for it". The brief is this palette: every value is the reference's own.direction_check --ledger·hero-undecided, andtype scale flat/shape unset—centaurireports the same hero warning for the same reason (a working surface has no first screen to decide about), and the twounsetlines are the known blind spot recorded intools/distinctness.sh: a fully tokenised page, which §1 mandates, declares no literal sizes or radii for that tool to count.copy_lint·jargon 'input'×3 — matching the<input type="radio">attribute, not the copy.title-case×1 — it is a book's title.label-period×20 — full sentences of prose, not labels.craft_lint·disabled-unstyledand twohover-no-transition— the disabled state is.btn[disabled]in a stylesheet rather than adisabled:utility, and the two modifier selectors inherit their transition from.btn.keyboard_probe·unreachable-control×2 per width — the two unchecked radios in the balance group. A radio group is one tab stop and the arrow keys move inside it, which is the native behaviour the page is relying on.audit_page·apple-touch-icon-missing,manifest-missing— a specimen page is not an installable application.
The logo-swap test, and why its number is high here
tools/distinct-one.sh claude-brand — 22 pairs, worst 0.74 against a ceiling of 0.75, which passes by one hundredth and is worth explaining rather than celebrating. Every point of it is the instrument. Against luxury-hospitality, the pair that scores highest, five of the seven dimensions come back 1.00 — radii and type_steps because CONTRACT.md §1 forbids a literal and both pages are fully tokenised, so the tool compares two empty sets and scores them identical; hero, card_density and bleed because both pages have none of the thing being counted. The one dimension with real content in it, grid_shapes, is 0.17: a two-column bilingual document with a margin track and a photography-led hospitality page do not share a shape. The same holds for centauri at 0.73, where grid_shapes is 0.10.
That is the floor tools/distinctness.sh's own header warns about, and this page sits closer to the ceiling than any other in the set because it declares no literals at all and has no hero, no cards and no bleed to be counted against. Reading the number without the breakdown would report a resemblance that does not exist.
What I am least sure about
Whether the margin should hold the decision at all. The bold thing says every control sits beside the line it changes, and the three renderings with their costs are the most valuable thing on the page — a fourteen-rem column is where they fit worst. They were three cards at twelve rem and every label broke inside its own border; the boxes came off and the margin went to fourteen, which is legible now and still the narrowest column on the screen. The alternative is a panel that opens over the translation, and I think it is worse — it covers the text the decision is about at the moment somebody is deciding — but it would let the three costs be read side by side, and somebody could reasonably prefer that trade.