* fix(editor): preserve grab offset when moving items (no teleport-to-cursor) Grabbing a placed item to move it (move-cross handle or the Move affordance) snapped the item's origin to the cursor instead of keeping the offset between the grab point and the origin. - Floor (regression): the grab-offset rewrite patched event.localPosition, but floorStrategy.move reads event.position (the world cursor) for its world-grid snap on the default non-Shift path -- a read added after the offset fix landed. Now also correct event.position, derived from the corrected building-local point via buildingLocalToWorld. - Wall / ceiling / item-surface / shelf: the shared surface strategies snapped the origin straight to the cursor with no grab offset. Added per-surface grab anchors (start + (raw - anchor)) seeded on the first move per host and reset on leave/detach; host-resting items start in their surface, and the level-reparent effect skips intentionally-hosted drafts so the dragged mesh stays on its host. Rename preserveFloorDragOffset -> preserveDragOffset (it now governs all surfaces). 2D move paths already preserved the grab offset, so no sibling change is needed -- this brings 3D into parity. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * refactor(editor): tidy grab-offset floor/wall paths (quality pass) Behaviour-preserving readability pass before shipping: - Extract the floor grab-offset IIFE into a named `applyFloorGrabOffset` helper (parity with `resolveHostSurfaceWorld`); drop redundant tuple casts via the return annotation and tighten the comment. - Wall move: always set `position` (raw hit when the wall mesh is absent) instead of a conditional object spread. A reviewed dedup of the three per-surface anchors was deliberately NOT taken — the wall (X/Y) / ceiling (X/Z) / host-surface frames are heterogeneous enough that unifying them adds more indirection than it removes. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>