Each gallery tile gets a small drag handle (top-left, ✱). Grab it and
drop it anywhere among the others - the tile moves live as you drag
over neighbours, then the new order is saved automatically on drop.
- Artwork gets a `position` column; the gallery lists by position (was
upload date). New uploads land after everything else.
- New POST /art/reorder endpoint takes an ordered list of ids (one
shared CSRF token, "reorder-art") and rewrites positions 1..n.
- Migration backfills position from the existing upload-date order via
ROW_NUMBER(), then drops the bootstrap default so it matches the
Doctrine mapping.
- New Stimulus controller (art-reorder): native HTML5 drag/drop, no
library. dragover live-reorders the DOM by comparing cursor x to the
hovered tile's midpoint; dragend posts the resulting id order and
shows a small "Saving order… / Order saved" status pill.
Verified: schema validate clean: a throwaway script exercised
persist+reload of a reordered set against the real DB, and a live
browser check dispatched real DragEvents through the actual Stimulus
controller and confirmed the exact POST payload it sent. phpunit 9/9.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>