One completed route: its elevation profile, and its eight splits.
Direction
- Archetype: document. One measure, one figure allowed to break it, and nothing else competing for the column. Every word on the page — heading, prose, figure caption and the stacked callout list — hangs on the same left edge; only the plot bleeds, and it bleeds symmetrically.
- Data stance: chart-first. The profile carries the screen and the splits are callouts on it; the table under it is the record, not the argument.
- Density: comfortable. Every control clears Apple's 44 pt floor, with at least 8 pt between neighbours.
- The one bold thing: Dynamic Type, honoured. The size control drives the real iOS ramp, and the page holds at AX5.
Generator
hig_type.py --responsive # tokens.css
hig_type.py writes tokens.css. The page links it and never edits it.
The AX3, AX5, and xxxLarge overrides inside index.html come from the same script, one run per size, and the checks behind the layout come from three more:
hig_type.py --size xxxLarge # and --size AX3, --size AX5
hig_type.py --all-sizes --format table
hig_type.py --targets
hig_type.py --concentric 16 8
Colour
hig_type.py emits no colour, and Apple publishes no colour token values. The HIG's first rule on colour is that the documented ones "may fluctuate from release to release", so nobody may transcribe them. The page's semantic set therefore comes from the web's own system colours — Canvas and CanvasText, with color-mix() for the three label levels and the separator — modelled on the HIG's label and grouped-background hierarchies. One custom accent carries both appearances through light-dark(). The appearance switch sets color-scheme, and that is what flips all of them together.
Measured with color-and-contrast/scripts/contrast.py:
- Tertiary label on the grouped surface, the tightest pair on the page: 5.17:1 light, 6.45:1 dark.
- Secondary label on the page ground: 10.86:1 light, 10.97:1 dark.
- The accent, which paints the route line and the links: 6.49:1 light, 10.39:1 dark.
Apple's own secondaryLabel and tertiaryLabel are lighter than 4.5:1 by design. Canvas and CanvasText are ours to mix and no Apple value is being transcribed either way, so the three levels here are set by measurement: 76% and 60% are the shallowest mixes that clear AA against the grouped background, which is the worst ground on the page. A browser probe reads the painted pixel of every text node in both appearances and reports no finding.
The chart's two non-text marks were measured too. A callout's leader is a graphical object a reader needs to pair a label with its point, so it takes --control-edge and clears SC 1.4.11: 3.36:1 light, 4.83:1 dark. The hatch over the gap is deliberately below that, near 1.4:1 — it is a texture behind a fact the dashed route line, the callout, the notice and the table each state in full, so it reinforces rather than carries, and giving it enough weight to pass would put more ink on the absence of data than on the data.
Two overrides on the generated type
Both live in the page, never in tokens.css, and both leave size, family and weight with the token:
- Running prose is set to 1.52 leading. The text styles carry Apple's 17/22, which is a control label's leading under a 70-character line. The override is scoped to prose elements, so
font: -apple-system-bodystill supplies everything else where Safari honours it. - Display tracking resets to normal under
@supports not (font: -apple-system-body). The −0.01em intokens.cssis SF Pro's optical-size compensation; that query is false exactly where the stack has fallen through to whatever grotesque the OS has, and a face that is not SF Pro is not improved by SF Pro's tracking. On this machine the whole stack resolves to DejaVu Sans — measured, every candidate name renders at an identical advance width — so the fallback is a stated condition rather than an accident.
The second state
The 1.9 km where the watch held no fix. The chart draws a hatched band with a dashed line between the last and first known points; the split row reads No data for ascent, and a dash where nothing can compute a pace; the day's total leaves the gap out and says so. Three marks that must not look alike sit on screen together — a measured 0, a No data, and the dash.
Dynamic Type
Built at Large, then measured at every size from Large to AX5 across 375, 768, 1024, 1440 and 1920 px: no horizontal overflow and no truncation at any pair. Four layout changes fire at the accessibility sizes, which follows Apple's own guidance rather than patching around it:
- the callouts leave the profile and become the list under it;
- the five axis labels leave the plot, and the range moves into the caption;
- the segmented control stacks;
- the readable measure grows (38rem, then 56rem at AX3 and 72rem at AX5) so a line still holds a sensible number of characters at 53 pt.