3D stadium model (Blender assets, Three.js). Choose a corner: the solver returns the curl; the blue marker is the target.
The science
Inverse problem. Instead of guessing, the solver asks: which side-spin makes this kick cross the goal line exactly at the chosen corner? The flight model is the same as in the wall simulation: gravity, quadratic drag and a Magnus force, m dv/dt = m g − ½ρA Cd|v|v + ½ρA CL|v|² (ω×v)/|ω×v|, with CL = 1/(2+1/S), S = rω/|v| (Goff & Carré, 2009), integrated with RK4 (2 ms).
Shooting method. Let z(ω) be the lateral position where the flown ball crosses the plane x = D. It is monotone in the side-spin ω for a fixed aim, so the root of z(ω) − ztarget = 0 is found by bisection (60 halvings of [−80, +80] rad/s). The graph shows z(ω) and the root. In “curl + elevation” mode an outer bisection on the launch elevation fixes the height too (nested shooting).
Numerical check. The solved kick is re-flown with a 4× finer time step and the miss distance at the goal plane is shown as “residual” (must be < 5 cm; typically a fraction of a millimetre). test_numeric.js additionally checks mirror symmetry (target at −z needs −ω), zero curl when the target is on the aim line, and agreement with an independent explicit-Euler re-implementation of the force law.
Honest simplifications. Constant Cd (real balls show a drag crisis and knuckle effects); constant spin rate (real spin decays slowly); no wind; no goalkeeper; the wall (5 players, 1.8 m) is only checked for blocking. Curl above ~70 rad/s (about 11 rev/s) is flagged because it is rarely reached by real kickers (typical value, not a measurement). The ball and drag numbers are typical published values, not a particular ball.
3D assets built in Blender (headless, Cycles-baked textures), exported as a Draco GLB; the physics module is identical to the 2D page.