The arrow-key nudge handler existed but only ever acted on a POINTER selection, and nothing could select without a mouse — so the feature was unusable by exactly the keyboard users it's for. This is the scoped first slice: give the canvas a keyboard path in, and fix the Modal focus trap that every destructive confirmation goes through. Canvas: - The <svg> gets role="application" + an aria-label describing the controls, and a <title> naming the garden — a screen reader now announces an interactive canvas rather than an empty graphic. - Each object <g> is a focusable role="button" with an aria-label (name + kind) and aria-pressed reflecting selection. Enter/Space selects it — the step that was missing — which makes the existing arrow-key nudge reachable. - A :focus-visible CSS rule draws a dashed accent ring on keyboard focus (and NOT on a mouse click, which is the point of :focus-visible). CSS rather than React state because onFocus on an SVG <g> is unreliable, and a CSS rule cleanly overrides the shape's inline stroke. Modal (blast radius: DeleteGarden/ClearBed/DeletePlant/DeleteSeedLot/Share): - Tab is trapped inside the dialog and wraps at the ends, instead of walking out into the page behind the backdrop. - On close, focus returns to the element that opened the dialog rather than landing on <body>. Verified live against the built binary with real keyboard input: Tab focuses an object (SVG <g tabindex> genuinely takes focus), Enter flips aria-pressed false→true, the focus-visible dash renders (computed stroke-dasharray "5px, 4px"), the dialog traps focus through 5 Tabs, and Escape closes it and restores focus to the opener. Follow-ups noted, not done here: object dimensions in the aria-label (needs the garden's unit context this component doesn't hold), roving-tabindex between plops inside a focused bed, and the EditorRail tablist semantics. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01H3zbym8Doka2d7D48maSgZ