Two real bugs, both confirmed live:
1. dragover's preventDefault() was gated on dataTransfer.types including
'Files' -- during a real OS file drag, Chromium does not reliably
populate that list synchronously on every dragover event, so the
condition failed often enough that preventDefault was silently
skipped. Per the HTML5 DnD spec, an element only becomes a valid drop
target once dragover (and, in some browsers, dragenter) has been
cancelled -- without that, the browser falls through to its native
"open the dropped file" behaviour, which is exactly what was
reported. Removed the gate entirely; dragenter is now also handled,
not just dragover.
2. No page-wide safety net existed, so a drop landing even slightly
outside the dropzone element bubbled to the browser's default action
uncontested. Added a window-level dragover/drop preventDefault
installed once regardless of which section is active.
This also explains the "no hover highlight" symptom: the same
gated-preventDefault bug meant dragover never reliably reached the
class-toggle code either.
Verified live: dragenter/dragover/drop each report defaultPrevented,
the highlight class appears on dragenter and clears on drop, the
dropped file populates the hidden input, and a drop dispatched directly
on <body> (simulating one that misses the zone) is also intercepted by
the new window-level guard.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>