Mirage · graded-index ray bending
Drop the sharp interface: let the refractive index vary continuously with height (hot, thin air near a sun-baked road). What does a ray do — and why does the road look wet?

▶ Run the simulationSee the measured result
Units: dimensionless Bouguer exponent (sinθ ∝ n^γ along any ray in a stratified medium)
How the lab tests it
Integrate the exact ray equation y'' = (n'/n)(1 + y'²) (RK4) for light launched gently downward through n(y) = N0 + G·y, for a fan of launch angles. Track the invariant n(y)·sinθ along each ray, mark each ray's turning point, and compare the analytic turning height y_t = (C − N0)/G with the integrated trajectory's lowest point.
What it checks
SNELL-IN-LAYERS as a conservation law — across each infinitesimal layer n sinθ is unchanged, so n(y)·sinθ = C holds along the whole curving ray (verified to ~1e-12), the optical analogue of conserved horizontal momentum; the ray turns where n(y_t) = C (a total internal reflection spread over a thickness) and arcs back UP before reaching the ground — the inferior mirage, the sky refracted into your eye from below
Mirage & graded-index calculator — Bouguer's invariant n·sinθ = C, the turning height, the grazing distance to the puddle on the road, and the corpuscular rival that makes it impossible
Drop the sharp interface and let the index vary continuously with height, and refraction stops being an event and becomes a conservation law: n(y)·sinθ stays put along the whole ray, however the air is stacked. That one sentence is this page. Nothing the lab measured is stored in the computation — every number below is assembled out of the profile, the gradient and the angles you type, and the six readings carried from the finding are there to be SCORED against, so zeroing all six moves nothing. The default row is the simulation's own configuration (N₀ = 1, G = 0.06, source at y = 7, the swept probe's 58° from the vertical), which is why the grazing half-span direction returns 14.785608479504 — bit-identical to the closed form the oracle bisected its way onto, reassembled here from three numbers rather than quoted. Three things on this page are not restatements of the finding. The exponent γ is taken as a free logarithmic slope of sinθ against n and comes back −1.000000000000 with nothing about the law in the arithmetic. The grazing span's spelling is CHOSEN rather than inherited: arccosh(n_s/N₀) hands acosh an argument whose leading 1 has already eaten the small part, and at a fractional index rise of one part in a million million — an ordinary atmosphere over an ordinary eye height — that spelling is 4.4e-5 out where log1p(t + √(t(t+2))) is exact; the page measures the gap in your browser rather than asserting it. And the road direction builds the gradient from the air itself, turning a temperature profile into a distance to the puddle (≈128 m for a standing adult over a road 20 K hotter than the air a decimetre up), then carries the same arithmetic through the sign change into inversions, looming, the radio handbook's 4/3-earth factor and the ducting threshold where the ray bends harder than the planet. What this page will not do is give you brightness — Bouguer routes light and says nothing about how much arrives — or pretend the linear profile is the law: the cosh, the arccosh and y_t = (C − N₀)/G are that profile's answers, while n(y)·sinθ = C is the one that survives arbitrary stratification.
n(y)·sinθ = C · n(y) = N₀ + G·y · sinθ ∝ n^γ with γ = −1 · n(y_t) = C ⇒ y_t = (C − N₀)/G · X* = (N₀/G)·arccosh(n_s/N₀) → √(2N₀y_s/G) · y(x) = (C·cosh(Gx/C) − N₀)/G · R = n√(1+y′²)/G · dn/dy = −((n−1)/T)·dT/dy · k = 1/(1 + R⊕·(dn/dy)/n) · rival: sinθ/n = const, γ = +1