When should the runner start? 3D stadium model (Blender assets, Three.js): the blue ring marks where the runner is when the ball arrives. Compare his arrival time with the ball’s time of flight (drag + Magnus) at the header point.
The science
Two clocks. A well-timed run-in is a coincidence of two times. The ball clock: the time tball at which the delivery comes back down through the header height, from the same RK4 flight model as the corner-kick simulation (gravity, drag ½ρA Cd|v|v, Magnus lift with CL = 1/(2+1/S)). The runner clock: trun to cover the distance d to that point.
Runner model. The runner keeps jogging at speed vi for a hesitation time th, then accelerates uniformly at a up to a top speed vmax and holds it. After the hesitation, with remaining distance r = d − vith: if r ≤ (vmax² − vi²)/(2a) then t = th + (−vi + √(vi² + 2ar))/a, otherwise t = th + (vmax − vi)/a + (r − dacc)/vmax. The margin is tball − trun; “latest start” is the largest hesitation that still arrives on time (bisection on the monotone trun).
Numerical check. The closed-form runner time is compared with an independent explicit integration at 0.01 ms steps, and the ball time of flight with a 4× finer step; both agree to well under 1 ms (limit shown in the page; asserted in test_numeric.js together with the vacuum time from the quadratic formula).
Honest simplifications. Illustrative runner numbers (acceleration 2–6 m/s², top speed 5–9.5 m/s, hesitation 0–1 s) are typical ranges for a demonstration, not measurements of an athlete. The runner moves in a straight line, ignores opponents, and “arrival” means reaching the point under the header, not the jump itself. Constant Cd, constant spin, no wind. Players are generic figures.
3D assets built in Blender (headless, Cycles-baked textures), exported as a Draco GLB; the physics module is identical to the 2D page.