3D stadium model (Blender assets, Three.js). The blue ring is the near-post target zone.
The science
Flight model. Same 3D model as the free-kick simulations: gravity, quadratic drag and a Magnus force, integrated with fixed-step RK4 (2 ms): m dv/dt = m g − ½ρA Cd|v|v + ½ρA CL|v|² (ω×v)/|ω×v|, CL = 1/(2+1/S), S = rω/|v| (Goff & Carré, 2009). Ball: 0.43 kg, radius 0.11 m; ρ = 1.2 kg/m³; Cd = 0.25 (typical values).
Corner geometry. The corner is at the origin, the goal line runs along +x, and the goal centre is 34 m away (half of a 68 m wide pitch). The near post is at x = 30.3 m. An inswinger bends towards the goal line (here: negative curl); an outswinger bends away. The delivery is judged where the ball comes back down through the header height.
Lateral drift and the small-angle estimate. For a vertical spin axis the Magnus force is horizontal and perpendicular to the ball's heading, with magnitude F = ½ρA CL |v|². In the small-angle limit (path turned by only a few degrees) the sideways displacement is the double integral of aL = F/m; the constant-acceleration shortcut is ½ aL t² with the launch speed. Without drag |v|² = v0² − 2gΔy is exact, so the double integral can be evaluated independently of the RK4 code; the in-page check and test_numeric.js compare it with the RK4 drift (agreement within a few percent, typically < 1 %). The graph overlays the RK4 drift (with your drag) on the drag-free small-angle curve.
Honest simplifications. Constant Cd and constant spin rate; no wind; no goalkeeper or players; the target zone (30 m, 3.5 m, radius 1.5 m by default) is an illustrative marker, not a rule of the game. Realistic corner spin is a few revolutions per second; a few rad/s of side-spin is already enough for metres of drift over a 2-second flight.
3D assets built in Blender (headless, Cycles-baked textures), exported as a Draco GLB; the physics module is identical to the 2D page.