╭ changed ──────────╮ │src/embed/script.js│ ╰───────────────────╯ ╭───────────╮ │← all files│ ╰───────────╯ ╭───────────────────────────────────────────────────────────────────────────────╮ │174 if (!t || !t.dataset || !t.dataset.focusId) return; │ │175 wasmInstance.exports._onMouseClick(Number(t.dataset.focusId)); │ │176 wasmInstance.exports._tick(minRows(), maxCols()); │ │177 + }); │ │178 + │ │179 + // submit handled on mousedown rather than click because submit-button│ │180 + // spans are tabbable: a mouse click on one moves focus to it, which │ │181 + // fires focusin, which re-renders via innerHTML, which detaches the │ │182 + // very span the click event was about to target. mousedown fires │ │183 + // before the focus change, so the target is guaranteed to be live. │ │184 + grid.addEventListener("mousedown", (event) => { │ │185 + const span = event.target.closest(".clickable"); │ │186 + if (!span || span.dataset.action !== "submit") return; │ │187 + event.preventDefault(); │ │188 + submitForm(span.dataset.url); │ │189 }); │ │190 │ │191 grid.addEventListener("click", (event) => { │ ╰───────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────╮ │192 const span = event.target.closest(".clickable");│ │193 if (!span) return; │ │194 + // submit is handled in mousedown above │ │195 if (span.dataset.action === "submit") { │ │196 event.preventDefault(); │ │184 - submitForm(span.dataset.url); │ │197 return; │ │198 } │ │199 const focusId = Number(span.dataset.focusId); │ ╰─────────────────────────────────────────────────────────────╯