Use a plain EventTarget for io's testing fallback, not jsdom
Context
Testing io's keyboard/mouse polling for real (not mocked) needed a browser-less stand-in for `window`/addEventListener/dispatchEvent under Node. A full jsdom window polyfill (mirroring the pattern already used for webgpu) reliably hung or crashed the whole process whenever io's tests ran in the same gleeunit process as cs's WebGPU tests -- confirmed by isolation (io alone: fine; io+pe: fine; io+cs: broken every time).
Options considered
Decision
io_ffi.mjs uses `globalThis.window ?? new EventTarget()`; the jsdom devDependency was added then removed in the same work session.
Verification
10/10 clean runs after switching, versus reliable hangs/crashes with jsdom in the same process as cs's tests.
Consequences
General lesson applied elsewhere in this project since: prefer the lightest-weight real (not mocked) polyfill that satisfies the actual API surface used, not the most realistic/heaviest one available.