r220 extracts the marquee geometry algorithm to a pure utility module (`marquee.ts`), refactors the Canvas to use ref-based document listeners (no more re-registration), adds a visual snap indicator (yellow dots), memoizes the outline renderers, and audits the selection snapshot to include all 6+ layer fields plus a monotonic seq counter.
The marquee module is the canonical example of the r220 pattern: **algorithm in a pure module, presentation in a React component**. It can be tested in isolation without React/DOM.
**Investigation finding**: the r220 "drag failure" the user reported is a test-isolation artifact (PM2 panel overlay intercepts subsequent mousedowns), NOT a Canvas bug. Direct dispatch on the canvas element proves the React onMouseDown re-fires correctly.
**Hardening pass**: added explicit state reset at the start of every onMouseDown to guarantee clean slate regardless of how the previous drag ended. 14 new unit assertions verify the invariants (state reset, no preventDefault/stopPropagation on document handlers, Escape guarded by active marquee).
**Key changes**:
**Verification**: 369 unit tests (88 r220 + 281 prior) + 60 Playwright (31 r220 + 29 r219) = **429/429 passing**. Build clean, 0 iframes, 0 postMessage. New bundle hash: `main-DIyJGMms.js`.
**Shipped**: `feat/id9-r220-refinement` @ `e52286a`. Merged to main @ `10ef1d2` (--no-ff, audit-receipt). Tag `r220-shipped` moved to merge commit.