Dedupe a Shell-side pattern into game_ffi.mjs's setElementVisibilityMessage, mirroring decision 0062's Core-side reasoning one layer up
Context
While auditing the codebase for other instances of the same 'independently duplicated across all three games' pattern that motivated decision 0062 (per an explicit request to check for more, not just fix the one already found), direct comparison of each game's own FFI file found game_tiers_ffi.mjs's setGameOver and game_breakout_ffi.mjs's/game_platformer_ffi.mjs's setStatusMessage to be byte-identical: same (visible, message) signature, same three-line body (set textContent, set hidden), differing only in which DOM element id each one hardcoded (#glemy-game-over vs #glemy-status).
Options considered
Decision
Added game_ffi.mjs's setElementVisibilityMessage(elementId, visible, message) -- the shared implementation. Each game's own set_game_over (game_tiers.gleam) / set_status_message (game_breakout.gleam, game_platformer.gleam) is now a thin Gleam-side wrapper: a new private set_element_visibility_message extern pointed at the shared JS function, called with that game's own hardcoded element id string. Every existing call site (set_game_over(visible, message), set_status_message(visible, message)) is completely unchanged in arity, name, and meaning. Deleted the three now-redundant per-game JS implementations from game_tiers_ffi.mjs/game_breakout_ffi.mjs/game_platformer_ffi.mjs.
Verification
gleam test and gleam test --target javascript both pass with identical counts to decision 0062 (288 Erlang / 315 JavaScript) -- a pure Shell-layer refactor with no new Gleam-testable logic, so no new unit tests were expected. deno task check-warnings passes with the baseline completely unchanged (104/104). All three real browser-checks (browser-check/browser-check-breakout/browser-check-platformer) re-run and pass for real -- browser-check-platformer specifically confirms #glemy-status genuinely renders "You fell!" and becomes visible through the new shared FFI path end to end, the most direct possible regression proof for a DOM-write change.
Consequences
game_ffi.mjs now covers one more genuinely generic Shell concern (a visibility+text DOM write, parameterized by element id) alongside requestFrame/canvasBoundingRectLeftAndWidth. A fourth game's own game-over/status display is a two-line addition (an extern pointing at the shared function, a wrapper naming its own element id) rather than a fourth from-scratch copy of the same three lines. Completes the pattern audit requested alongside decision 0062: the wall-handling duplication (Core) and this FFI duplication (Shell) were the two real, already-independently-triplicated patterns found; the two additional candidates considered (a shared rect-search helper, a held-key-direction helper) were checked and declined, recorded in decision 0062's own entry.