Basefox · Decisions locked · 26 Aug 2026

Warm Sans, caps, and the line-art tier

Both calls applied and shipping. The line-art approach is wired end to end and verified against a real build; brand cards stay logo-led.

62Swift tests pass
60Pipeline tests pass
3Typefaces, down from 5
0 / 20Assets outstanding

1 · Warm Sans is now the system

Archivo for display, Source Sans 3 for body, Spline Sans Mono unchanged. The other three candidates are deleted, along with Space Grotesk, Barlow, and Fraunces — five bundled faces down to three. TypeSystem.swift and the -type= flag are gone, and the winner is inlined in Fonts.swift.

2 · Hero display is set in caps

Caps at 22pt and above, letterspaced 0.3, narrowing to wdth 89 — the width axis was already switching at that threshold, so caps and condensing arrive together. Below 22pt display stays sentence case at full width, which keeps row titles and labels readable. The accent rule from your mockup sits between the headline and the descriptor, in the card's own colour.

Before — Space Grotesk, sentence case
Hero card before
After — Archivo caps + accent rule
Hero card after

This settles the spec contradiction. basefox-spec-v03.md no longer says “no letterspaced all-caps”; it now states the caps threshold, the letterspacing, the width axis, and the accent rule.

3 · The line-art tier is wired

Tier 3 became two rungs. A category names a drawing and an SF Symbol, so the tier always resolves and the app is still complete with an empty asset directory.

TierWhat it isSourceNeeds a file
1 · CampaignLine art composed for one saleExchangeEvent.heroyes
2 · BrandMerchant lockupBrand.logoyes
3 · CategoryLibrary object, else SF SymbolCategory.illustration → Category.glyphno
4 · GenericAbstract pattern, drawn in code—no

Three decisions baked in

Verified against a real build

I drew two throwaway placeholders to the spec, ran the sync, and rendered them. Both were deleted afterwards, so nothing fake ships — the screenshot is the evidence, not the artwork.

Exchange cards with placeholder line art

Placeholder tent resolving through tier 3, with the accent disc and topo texture drawn in code behind it. The thin stroke is the placeholder's fault, and it is what produced the calibration fix below.

A bug the verification caught

The AAFES card carries [footwear, outdoor]. The resolver took the first-named illustration, so it asked for illus-footwear, found no file, and dropped to the SF Symbol — even though outdoor's drawing existed. It now tries every named candidate in card order and takes the first that resolves. Without this, partial library coverage would have looked like no coverage.

A calibration finding for whoever draws these

My placeholders used 4pt strokes on a 512pt artboard. On a standard card that renders at roughly 0.8pt and nearly disappears. registry/assets/README.md now specifies 10pt and says so explicitly: if the drawing looks heavy on the artboard, it is probably right in the app.

Related: while coverage is partial, the browse tiles mix line art and SF Symbols, and the two do not match in weight. Commissioning all seven category objects together avoids a transitional period where the row looks inconsistent.

4 · Brand cards stay logo-led

Line art cannot distinguish Hoka from Brooks — both would show a generic running shoe — so tier 2 remains the treatment for a merchant, and the ten lockups are still needed. That is now written into the spec rather than left implicit.

Where the app stands with nothing supplied

Clean install · 0 of 20 assets
Home on a clean install
Browse tiles falling through to SF Symbols
Category tiles

The asset queue, now 20

CountWhatFormatCost of absence
10Brand lockupsPNG, 900 × 240 @3xCard drops to the category mark
7Category objectsPDF vector, 512pt artboardFalls back to the SF Symbol
3Campaign compositionsPDF vectorFalls back to the category object

larchpipe assets sync --dry-run lists all twenty by name and states what each one's absence costs. Drawing specs are in registry/assets/README.md.

Deliberately not done