Collision was checking grid[py+2] instead of grid[py+1].
Pieces stopped one row too early, creating gaps.
Now checks grid[py+1] (where top cells would land) with full
3-column width (px, px+1, px+2).
Pieces now stack directly on top of each other.
Added 'blocked' signal that checks frozen grid cells below active piece.
Collision check branches on py to inspect the correct grid row (13-19).
Gravity only drops when not blocked. Lock triggers on blocked state.
Freeze writes piece into correct row based on py (7 rows supported).
Added grid rendering for rows 13-15 (total 7 visible frozen rows).
Build output: 84KB