Split drag into two unambiguous gestures: relocate vs fill/copy

Previously both relocate (move/swap) and fill/copy used the exact same
trigger (double-click then drag), so there was no way to tell which
one the user meant - a drag was always interpreted as relocate first,
making the fill/copy gesture effectively unreachable in practice.

Now there are two distinct triggers:
- Double-click a filled cell (turns blue/"armed"), then drag it ->
  Relocate mode: drop on empty = move, drop on filled = swap. Any
  direction, unchanged from before.
- Click-and-drag directly, with no double-click first -> Fill/Copy
  mode: copies the source into every empty cell the pointer crosses
  before release. Same-row only; filled cells or cells in other rows
  crossed along the way are simply not valid targets (browser shows a
  "not allowed" cursor there) rather than being swapped or overwritten.
  Works identically for one cell or several, so the Ctrl/Cmd-copy
  modifier from the previous version is gone - redundant now that the
  gesture itself is unambiguous.

Implementation: every filled cell is now draggable="true" at all times
(previously only after double-click), since fill mode has to be
startable without any preceding arm step. dragstart checks whether the
cell being dragged is the one double-click just armed and sets a mode
flag ('relocate' vs 'fill') that dragover/drop branch on for the rest
of the gesture. A plain single click still only fires a normal click
event (native drag only engages on an actual drag gesture), so cell
selection (spec 2.8) is unaffected.

Verified via render checks that all filled cells carry draggable=true
and the script contains no syntax errors; full page regression and
test suite pass. Backend endpoints (move/swap/copy) are unchanged from
the previous commit, already verified directly against the server.
