The label band was built from raw magic numbers — baseline 18 px above the
frame, hit box from 32 px above it — which left the text's visual bottom
15 px clear of the frame. Because the offset is screen-space and does not
scale with zoom, that gap is the same 15 px however far out the canvas is,
so on a zoomed-out board the name reads as floating in empty canvas rather
than belonging to the frame beneath it.
Shrink the band instead of scaling it with zoom. A constant screen-space
offset is the right model for chrome — it is why the label stays legible
at any zoom — and the defect was only that the constant was too big;
scaling by zoom would have kept the same too-tall band at 100% and made
the doc-space clearance a moving target that the generator cannot reserve
space for ahead of time. So the geometry is now derived from the type it
draws rather than picked: a 6 px gap from the text's descender to the
frame edge, plus the 12 px font's 9 px cap height and 3 px descent, plus
3 px of box padding. Baseline lands 9 px above the frame and the hit box
spans 21 px to 3 px above it — down from a 32 px band, with the visible
gap cut from 15 px to 6.
Paint, hit-test and cull all read the same derived constants, so they
cannot drift apart. Three invariants are now asserted rather than assumed:
the hit box never reaches the frame's top edge (otherwise a click just
inside the frame would select the root via its label instead of the node
under the cursor), the glyphs and the taller generating icon stay inside
the box that hit-tests them, and the text stays within ~8 px of its frame.
ROW_LABEL_HEADROOM stays at 240 doc px, re-derived against the narrower
band: the extra margin costs nothing on an infinite canvas and the
zoomed-out end of the range is worth over-serving. Comments there and in
the slide template are updated to the new number.
Claude-Session: https://claude.ai/code/session_01FqKQqNj8exYwopGDpYUU7x