- gofmt domain.go struct alignment.
- Memoize the bed grid line arrays so a high-frequency plop drag doesn't
rebuild them each pointermove.
- Route the non-snapping placement/move paths through snapLocalToBedGrid
with step 0 (pure clamp), removing the duplicated inline clamps in
GardenCanvas.onPlace and PlopOverlay (drop the dead clampLocal helper).
- Factor snapLocalToBedGrid's per-axis snap-and-clamp into one local fn.
- Correct the gardenFromInput doc: grid size is defaulted from 0 on update.
- Fix inconsistent indentation of the Inspector Notes field.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01JdQpdYYsTgtkJBxbcpAszi
Two independent grids, each with a size and a snap toggle:
- Garden grid (owner-set, in the garden settings form): drives the
editor's visual grid and, when snapping is on, snaps objects on
place/move and snaps their dimensions to whole grid steps on resize.
- Bed grid (per plantable object, in the bed Inspector): when snapping
is on, plants snap to the bed's grid on place/move, and the grid is
drawn inside the focused bed. Plant radius stays free.
Snapping defaults off on both, so existing gardens keep free placement.
Grid spacing shares the [1cm, 100m] range and defaults to 1m (garden) /
30cm (bed); 0 is treated as unset and re-defaulted.
Backend: migration 0005 adds grid_size_cm/snap_to_grid to gardens and
garden_objects, threaded through domain/store/service/api with service +
api round-trip tests. Frontend: new geometry snap helpers (unit-tested),
schema/type plumbing, canvas + overlay snapping, and the two forms.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01JdQpdYYsTgtkJBxbcpAszi