Collision model
Every frame the ball is advanced, then tested against the wall rails, the paddle AABB and the live brick grid. Candidates are ranked by squared distance to their centre, and only the closest one is resolved — no multi-brick chain flips.
Side is inferred from the pre-move position: if the ball's previous span sat entirely above the brick's top edge it's a vertical hit (dy flips); if it sat to the left or right it's a lateral hit (dx flips). When both axes are ambiguous, the smaller penetration axis wins. The ball is then pushed clear along that normal, so it can never re-collide on the next frame.