Played a bunch of runs. The feel is right: the speed ramp and the shrinking jump window read well, and the one-button loop is clean.
One real bug though: you can fall into a gap and get lifted up onto the far edge instead of dying. Steps: tap once to start a run, then do not tap again. The character runs into the first gap and starts falling; as the next platform's left edge scrolls under you while you are still below ground level, you get snapped up onto it and the run keeps going instead of ending. I measured it on a 1536x643 window: at ~4.3m the character is at y=698 (falling, onGround=false), and one tick later y=514 (ground level) with state still 'play'.
Cause: the landing test only checks 'py>=GY-26 && vy>=0' then 'groundAt(wx)'. When groundAt flips true it sets py=GY-26, so entering a platform from below or from the side teleports the player up. There is no 'was above the surface' check. Fix: only land when the previous y was above GY-26 (e.g. keep prevY and require prevY<=GY-26), or resolve the side collision / kill on side contact.
Related: the kill line is py>H+80 while the ground sits at H*0.16, so the fall tolerance changes with window height (a taller window clips more). Tying the kill line to the ground line would keep it consistent.