Rendering it headlessly for the first time turned up two defects that
neither typecheck nor 112 tests could see:
- pads were labelled PAD 1, PAD 2 rather than printing their numeral.
The hardware prints the number, and swaps in a function name only when
a layer lights the pad up; Key now does the same.
- the LCD showed MODE:S, the context code, instead of the mode name. A
single letter tells the reader nothing.
Both are only visible by looking, which is the point: the geometry was
arithmetically correct the whole time and still read wrong.
CLAUDE.md now records how to look. There is no Chromium here, but
Firefox screenshots headlessly with no new dependency, given three
things that otherwise waste an afternoon: -no-remote and a throwaway
profile, or it opens a tab in the running browser and captures nothing;
an HTTP server, because module scripts will not load over file://; and a
user.js pref to force dark mode.
Verified in both light and dark at 360x735. 112 tests, build clean,
www/ untouched.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Panel.tsx is presentational - told what is lit, reports presses, holds no
state. The arrangement lives in panelLayout.ts as data, so the component
stays readable and the layout can be tested.
panelLayout.test.ts asserts allPanelControls covers all 54 labelled
controls exactly once; a typo'd id would otherwise quietly vanish from
the panel. It also pins the bank row at six keys ending in SHIFT, because
Panel.module.css widens that key with :last-child:nth-child(6), a
coupling that stops matching silently if the row changes length.
Geometry is the measured one: 8 + 36 + 8 + 124 + 10 + 134 + 10 + 187 + 8
= 525. The screen is the hardware's arrangement - a 124px circle behind a
168x84 LCD, showing only as caps above and below, with no ring around the
display. Key labels are 7px with no tracking, which is what stops
RESAMPLE overflowing its 35.9px button.
cx() absorbs CSS-module lookups typing as string | undefined under
noUncheckedIndexedAccess, rather than turning that flag off - it has
already caught real bugs.
Two fixed on the way through: panelLabel used PL without importing it,
which broke typecheck and the layout test at runtime; and ten className
type errors from the same CSS-module typing, in the places that needed a
definite string rather than React's optional one.
112 tests, build clean, www/ untouched so the Phase 1 APK still installs.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>