The canvas paints each top-level frame's name ABOVE the frame at a fixed
screen-space offset that does not scale with zoom (canvas_frame_labels.rs
puts the baseline at sy-18 and the label box top at sy-32). A row gap
equal to the column gap therefore cannot work: at the zoom where a
wrapped canvas is actually viewed, the gap is narrower than the label
itself, so every second-row label sat pressed against the bottom edge of
the row above.
For the 3x2 deck the numbers are exact: 6000 doc px of content framed by
zoom_to_fit into a 944-1424 px canvas region lands at zoom 0.14-0.22,
where a 120 doc px row gap is only 16-26 screen px against a label that
always occupies 32. It overlapped at every realistic window size.
Add 240 doc px of headroom to the VERTICAL step only — 33-52 screen px at
that zoom, clearing the label with room to spare. Columns are untouched:
labels are left-aligned to their own frame and never reach sideways. The
slide-deck template takes the same allowance on top of its own gap, so
both the generated canvas and the shipped template space rows the same
way.
Claude-Session: https://claude.ai/code/session_01FqKQqNj8exYwopGDpYUU7x